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.
- package/CHANGELOG.md +14 -0
- package/README.md +86 -117
- package/bin/arcane-test.mjs +170 -46
- package/browser-runtime/ai/browser-speech-artifacts.mjs +855 -895
- package/browser-runtime/ai/browser-speech-providers.mjs +80 -204
- package/browser-runtime/ai/browser-wasm-llm-provider.mjs +627 -819
- package/browser-runtime/ai/browser-wasm.mjs +24 -35
- package/browser-runtime/ai/browser-wllama-runtime.mjs +64 -316
- package/browser-runtime/ai/model-controller.mjs +584 -181
- package/browser-runtime/ai/speech-worker-client.mjs +8 -148
- package/browser-runtime/ai/speech-worker-runtime.mjs +642 -374
- package/browser-runtime/dom-event-instrumentation.mjs +55 -147
- package/browser-runtime/event-manager.mjs +239 -624
- package/package.json +5 -6
- package/runtime/arcane/components/app-bar.html +3 -15
- package/runtime/arcane/components/assistant-panel.html +10 -10
- package/runtime/arcane/components/calculator.html +1 -1
- package/runtime/arcane/components/chat.html +1359 -135
- package/runtime/arcane/components/conversation-view.html +2 -2
- package/runtime/arcane/components/document-inspector.html +11 -17
- package/runtime/arcane/components/file-manager.html +13 -56
- package/runtime/arcane/components/markdown-document.html +82 -281
- package/runtime/arcane/components/markdown-editor.html +7 -10
- package/runtime/arcane/components/media-embed.html +6 -6
- package/runtime/arcane/components/screen-capture.html +4 -4
- package/runtime/arcane/components/source-explanation.html +2 -2
- package/runtime/arcane/components/speech.html +112 -68
- package/runtime/arcane/components/terminal-workspace.html +4 -4
- package/runtime/arcane/components/theme-editor.html +1 -1
- package/runtime/arcane/components/unified-inbox.html +2 -2
- package/runtime/arcane/components/voice-transcription.html +31 -21
- package/runtime/arcane/entities/Calculation.js +2 -3
- package/runtime/arcane/entities/Chat.js +228 -43
- package/runtime/arcane/entities/Preference.js +3 -5
- package/runtime/arcane/entities/Weather.js +5 -5
- package/runtime/arcane/modules/AI.js +1042 -427
- package/runtime/arcane/modules/AIProviderRuntime.js +618 -359
- package/runtime/arcane/modules/AIResponseLength.js +9 -19
- package/runtime/arcane/modules/AIRuntimeState.js +109 -72
- package/runtime/arcane/modules/ArcaneNavigationPolicy.js +45 -32
- package/runtime/arcane/modules/BrowserTestSuite.js +78 -122
- package/runtime/arcane/modules/CalculatorEngine.js +9 -9
- package/runtime/arcane/modules/CommunicationAppController.js +3 -7
- package/runtime/arcane/modules/ComponentContracts.js +30 -32
- package/runtime/arcane/modules/ConfiguredAIChatSession.js +281 -230
- package/runtime/arcane/modules/ConversationActionItems.js +26 -59
- package/runtime/arcane/modules/ConversationClosingReport.js +34 -61
- package/runtime/arcane/modules/ConversationTimebox.js +27 -15
- package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +152 -344
- package/runtime/arcane/modules/DocumentLexicalSearch.js +25 -91
- package/runtime/arcane/modules/HTMLImport.js +54 -1
- package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +40 -203
- package/runtime/arcane/modules/LocalAIReadiness.js +40 -60
- package/runtime/arcane/modules/LocalAIReadinessController.js +15 -13
- package/runtime/arcane/modules/MD.js +1 -45
- package/runtime/arcane/modules/Mail.js +51 -103
- package/runtime/arcane/modules/MailOutbox.mjs +95 -193
- package/runtime/arcane/modules/MailTransport.mjs +36 -57
- package/runtime/arcane/modules/ModelDefinition.js +22 -106
- package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +39 -101
- package/runtime/arcane/modules/PersistentAIChatSession.js +281 -18
- package/runtime/arcane/modules/PreferenceStore.js +102 -30
- package/runtime/arcane/modules/RiskSignalAnalyzer.js +8 -9
- package/runtime/arcane/modules/ScopedOPFSCache.js +7 -42
- package/runtime/arcane/modules/ScreenCapture.js +175 -128
- package/runtime/arcane/modules/SpeechPlayback.js +46 -149
- package/runtime/arcane/modules/StaticDocumentCatalog.js +173 -407
- package/runtime/arcane/modules/ToolCallRouter.js +25 -12
- package/runtime/arcane/modules/YouTubeMedia.js +6 -5
- package/schemas/arcane-app-bundle.schema.json +13 -78
- package/schemas/arcane-app.schema.json +9 -25
- package/schemas/arcane-lock.schema.json +18 -151
- package/schemas/arcane-package.schema.json +2 -16
- package/schemas/native-build-plan.schema.json +119 -122
- package/src/app-descriptor.mjs +75 -132
- package/src/application-tests.mjs +200 -0
- package/src/cli/main.mjs +27 -46
- package/src/constants.mjs +3 -4
- package/src/dev-server.mjs +30 -324
- package/src/doctor.mjs +92 -154
- package/src/dom-event-instrumentation.mjs +55 -147
- package/src/errors.mjs +2 -3
- package/src/event-manager.mjs +239 -624
- package/src/event-queue.mjs +3 -3
- package/src/import-map.mjs +273 -1028
- package/src/index.mjs +14 -16
- package/src/installed-sdk-runtime.mjs +27 -67
- package/src/integrated-provider-loader.mjs +53 -382
- package/src/mail-api.mjs +0 -2
- package/src/mail-server.mjs +224 -580
- package/src/mail.mjs +4 -10
- package/src/native-plan.mjs +163 -598
- package/src/native-provider-loader.mjs +104 -1063
- package/src/packager/core.mjs +485 -3229
- package/src/process.mjs +5 -10
- package/src/release-bundle.mjs +292 -2405
- package/src/runtime.mjs +76 -396
- package/src/scaffold.mjs +30 -80
- package/src/sdk-browser-runtime.mjs +70 -626
- package/src/source-server.mjs +588 -0
- package/src/targets/index.mjs +78 -188
- package/src/templates/workspace-template.mjs +19 -135
- package/src/testing-loader.mjs +164 -0
- package/src/testing.mjs +1 -1
- package/src/toolchain.mjs +131 -544
- package/src/update-check.mjs +26 -64
- package/src/workspace-operation-lock.mjs +139 -430
- package/src/workspace-runtime.mjs +109 -1558
- package/src/workspace.mjs +40 -302
- package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +0 -218
- package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +0 -203
- package/browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json +0 -80
- package/browser-runtime/ai/internal/sha256.mjs +0 -166
- package/docs/architecture.md +0 -344
- package/docs/compatibility.md +0 -36
- package/docs/event-manager.md +0 -294
- package/docs/platform-targets.md +0 -108
- package/docs/publishing.md +0 -201
- package/docs/reference/README.md +0 -185
- package/docs/reference/ai/browser-speech-package-authority.json +0 -835
- package/docs/reference/ai/browser-speech.md +0 -1295
- package/docs/reference/ai/browser-wasm.md +0 -530
- package/docs/reference/arcane-ollama.md +0 -288
- package/docs/reference/availability-and-normalization.md +0 -183
- package/docs/reference/behavioral-testing.md +0 -133
- package/docs/reference/cli.md +0 -779
- package/docs/reference/core/README.md +0 -62
- package/docs/reference/core/arcane-ai-contracts.md +0 -907
- package/docs/reference/core/arcane-api.md +0 -601
- package/docs/reference/core/arcane-entities.md +0 -65
- package/docs/reference/core/arcane-events.md +0 -134
- package/docs/reference/core/ollama-module.md +0 -181
- package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +0 -1909
- package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +0 -1057
- package/docs/reference/core/reference/arcane-api/core-and-events.md +0 -320
- package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +0 -610
- package/docs/reference/core/reference/arcane-api/namespaces.md +0 -1157
- package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +0 -1423
- package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +0 -315
- package/docs/reference/event-manager.md +0 -1511
- package/docs/reference/inventory/package-api.json +0 -3284
- package/docs/reference/inventory/runtime-components.json +0 -1011
- package/docs/reference/inventory/runtime-entities.json +0 -26
- package/docs/reference/inventory/runtime-modules.json +0 -1431
- package/docs/reference/mail.md +0 -316
- package/docs/reference/protocols.md +0 -719
- package/docs/reference/runtime-components.md +0 -1366
- package/docs/reference/runtime-entities.md +0 -303
- package/docs/reference/runtime-modules.md +0 -2965
- package/docs/reference/sdk-api.md +0 -6698
- package/docs/roadmap.md +0 -79
- package/docs/work-amplification.md +0 -129
- package/runtime/ARCANE_RUNTIME_RELEASE.json +0 -826
|
@@ -7,29 +7,24 @@ import {
|
|
|
7
7
|
|
|
8
8
|
let userInstance=null;
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const MAX_NATIVE_REPORT_BYTES=768*1024;
|
|
10
|
+
function completeResult(value){return value;}
|
|
11
|
+
|
|
13
12
|
const MAIL_TYPES=new Set(['error','report','crisis_detected']);
|
|
14
|
-
const MAIL_OUTBOX_EVENTS=
|
|
13
|
+
const MAIL_OUTBOX_EVENTS=completeResult([
|
|
15
14
|
'mail-outbox-state',
|
|
16
15
|
'mail-outbox-delivery',
|
|
17
16
|
'mail-outbox-drain'
|
|
18
17
|
]);
|
|
19
18
|
const PENDING_OUTBOX_STATES=new Set(['queued','sending','retry_wait']);
|
|
20
|
-
const NATIVE_MAIL_RESPONSE_STATUS_CODES=
|
|
19
|
+
const NATIVE_MAIL_RESPONSE_STATUS_CODES=completeResult({
|
|
21
20
|
accepted:202,
|
|
22
21
|
delivery_uncertain:207,
|
|
23
22
|
partially_accepted:207
|
|
24
23
|
});
|
|
25
|
-
const
|
|
26
|
-
'partial','requestId','sent','status','statusCode','uncertain'
|
|
27
|
-
]);
|
|
28
|
-
const NATIVE_MAIL_REQUEST_ID_PATTERN=/^[A-Za-z0-9-]{8,128}$/;
|
|
24
|
+
const NATIVE_MAIL_REQUEST_ID_PATTERN=/^[A-Za-z0-9-]+$/;
|
|
29
25
|
const NATIVE_MAIL_UNCERTAIN_ERROR_CODES=new Set([
|
|
30
26
|
'ARCANE_REQUEST_TIMEOUT',
|
|
31
27
|
'MAIL_GATEWAY_RESPONSE_INVALID',
|
|
32
|
-
'MAIL_GATEWAY_RESPONSE_TOO_LARGE',
|
|
33
28
|
'MAIL_GATEWAY_UNAVAILABLE',
|
|
34
29
|
'MAIL_NATIVE_RESULT_INVALID',
|
|
35
30
|
'MAIL_SEND_TIMEOUT',
|
|
@@ -74,10 +69,10 @@ function linkedMailSignal(primary,secondary){
|
|
|
74
69
|
if(signal&&!signals.includes(signal)) signals.push(signal);
|
|
75
70
|
}
|
|
76
71
|
if(signals.length===0){
|
|
77
|
-
return
|
|
72
|
+
return completeResult({signal:null,dispose:function disposeEmptyMailSignal(){}});
|
|
78
73
|
}
|
|
79
74
|
if(signals.length===1){
|
|
80
|
-
return
|
|
75
|
+
return completeResult({signal:signals[0],dispose:function disposeSingleMailSignal(){}});
|
|
81
76
|
}
|
|
82
77
|
const controller=new AbortController();
|
|
83
78
|
const listeners=[];
|
|
@@ -89,7 +84,7 @@ function linkedMailSignal(primary,secondary){
|
|
|
89
84
|
if(signal.aborted) listener();
|
|
90
85
|
else signal.addEventListener('abort',listener,{once:true});
|
|
91
86
|
}
|
|
92
|
-
return
|
|
87
|
+
return completeResult({
|
|
93
88
|
signal:controller.signal,
|
|
94
89
|
dispose:function disposeLinkedMailSignal(){
|
|
95
90
|
for(const entry of listeners){
|
|
@@ -129,7 +124,6 @@ function waitForMailOperation(operation,signal){
|
|
|
129
124
|
|
|
130
125
|
function exactNativeMailResult(value){
|
|
131
126
|
if(!value||typeof value!=='object'||Array.isArray(value)
|
|
132
|
-
||Object.keys(value).sort().join(',')!==[...NATIVE_MAIL_RESULT_KEYS].sort().join(',')
|
|
133
127
|
||typeof value.requestId!=='string'
|
|
134
128
|
||!NATIVE_MAIL_REQUEST_ID_PATTERN.test(value.requestId)
|
|
135
129
|
||!Object.hasOwn(NATIVE_MAIL_RESPONSE_STATUS_CODES,value.status)
|
|
@@ -157,12 +151,15 @@ function normalizedNativeMailError(error){
|
|
|
157
151
|
const retryable=uncertain||NATIVE_MAIL_RETRYABLE_ERROR_CODES.has(error?.code);
|
|
158
152
|
if(!retryable) return error;
|
|
159
153
|
const normalized=new Error(
|
|
160
|
-
|
|
161
|
-
?
|
|
162
|
-
:
|
|
154
|
+
typeof error?.message==='string'&&error.message
|
|
155
|
+
?error.message
|
|
156
|
+
:uncertain
|
|
157
|
+
?'Native Arcane mail delivery has an uncertain outcome.'
|
|
158
|
+
:'Native Arcane mail transport is temporarily unavailable.',
|
|
163
159
|
{cause:error}
|
|
164
160
|
);
|
|
165
|
-
normalized
|
|
161
|
+
Object.assign(normalized,error);
|
|
162
|
+
normalized.code=error?.code;
|
|
166
163
|
normalized.retryable=true;
|
|
167
164
|
normalized.uncertain=uncertain;
|
|
168
165
|
const statusCode=Number(error?.statusCode??error?.status);
|
|
@@ -253,7 +250,7 @@ export function resolveMailConfig(
|
|
|
253
250
|
const appName=typeof supplied.appName==='string'&&supplied.appName.trim()
|
|
254
251
|
? supplied.appName.trim()
|
|
255
252
|
: declaredApplicationId(document);
|
|
256
|
-
return
|
|
253
|
+
return completeResult({
|
|
257
254
|
appName:ARCANE_APP_ID_PATTERN.test(appName) ? appName:'',
|
|
258
255
|
appKey:typeof supplied.appKey==='string' ? supplied.appKey:'',
|
|
259
256
|
endpoint:typeof supplied.endpoint==='string'&&supplied.endpoint.trim()
|
|
@@ -274,10 +271,6 @@ function escapeHtml(value){
|
|
|
274
271
|
.replaceAll("'",''');
|
|
275
272
|
}
|
|
276
273
|
|
|
277
|
-
function utf8ByteLength(value){
|
|
278
|
-
return new TextEncoder().encode(value).byteLength;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
274
|
function clonePayload(value){
|
|
282
275
|
if(typeof globalThis.structuredClone==='function'){
|
|
283
276
|
return globalThis.structuredClone(value);
|
|
@@ -288,28 +281,18 @@ function clonePayload(value){
|
|
|
288
281
|
function serializePayload(value){
|
|
289
282
|
try{
|
|
290
283
|
return JSON.stringify(value,null,2);
|
|
291
|
-
}catch{
|
|
292
|
-
|
|
284
|
+
}catch(error){
|
|
285
|
+
const failure=codedError(
|
|
286
|
+
'Mail payload must be completely JSON serializable.',
|
|
287
|
+
'MAIL_PAYLOAD_NOT_SERIALIZABLE',
|
|
288
|
+
TypeError
|
|
289
|
+
);
|
|
290
|
+
failure.cause=error;
|
|
291
|
+
throw failure;
|
|
293
292
|
}
|
|
294
293
|
}
|
|
295
294
|
|
|
296
|
-
|
|
297
|
-
const messageBytes=['text','html'].reduce(
|
|
298
|
-
function sumMessageBytes(total,key){
|
|
299
|
-
return total+utf8ByteLength(report[key]||'');
|
|
300
|
-
},
|
|
301
|
-
0
|
|
302
|
-
);
|
|
303
|
-
if(messageBytes>MAX_MESSAGE_BYTES){
|
|
304
|
-
throw new Error('Generated report email content exceeds the 25 MiB limit');
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
function assertNativeReportSize(serializedReport){
|
|
309
|
-
if(utf8ByteLength(serializedReport)>MAX_NATIVE_REPORT_BYTES){
|
|
310
|
-
throw new RangeError('Native Arcane mail reports cannot exceed 786,432 serialized bytes');
|
|
311
|
-
}
|
|
312
|
-
}
|
|
295
|
+
let reportNonceSequence=0;
|
|
313
296
|
|
|
314
297
|
function randomReportNonce(cryptoProvider){
|
|
315
298
|
if(typeof cryptoProvider?.randomUUID==='function'){
|
|
@@ -320,19 +303,8 @@ function randomReportNonce(cryptoProvider){
|
|
|
320
303
|
}
|
|
321
304
|
}catch{}
|
|
322
305
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
const bytes=new Uint8Array(16);
|
|
326
|
-
cryptoProvider.getRandomValues(bytes);
|
|
327
|
-
return [...bytes].map(function reportNonceByte(value){
|
|
328
|
-
return value.toString(16).padStart(2,'0');
|
|
329
|
-
}).join('');
|
|
330
|
-
}catch{}
|
|
331
|
-
}
|
|
332
|
-
throw codedError(
|
|
333
|
-
'Mail requires Web Crypto to create a durable idempotency key.',
|
|
334
|
-
'MAIL_CRYPTO_UNAVAILABLE'
|
|
335
|
-
);
|
|
306
|
+
reportNonceSequence+=1;
|
|
307
|
+
return `${Date.now().toString(36)}-${reportNonceSequence.toString(36)}`;
|
|
336
308
|
}
|
|
337
309
|
|
|
338
310
|
function createReportKey(timestamp,cryptoProvider){
|
|
@@ -343,13 +315,8 @@ function normalizeRecipients(values){
|
|
|
343
315
|
if(!Array.isArray(values)){
|
|
344
316
|
throw new TypeError('Mail recipients must be an array');
|
|
345
317
|
}
|
|
346
|
-
if(values.length>50){
|
|
347
|
-
throw new TypeError('Mail supports no more than 50 recipients');
|
|
348
|
-
}
|
|
349
|
-
|
|
350
318
|
const recipients=[];
|
|
351
319
|
for(const value of values){
|
|
352
|
-
if(!value) continue;
|
|
353
320
|
if(typeof value!=='string'){
|
|
354
321
|
throw new TypeError('Every mail recipient must be an email address');
|
|
355
322
|
}
|
|
@@ -357,7 +324,7 @@ function normalizeRecipients(values){
|
|
|
357
324
|
if(address.length>254||!EMAIL_PATTERN.test(address)){
|
|
358
325
|
throw new TypeError('Mail contains an invalid recipient address');
|
|
359
326
|
}
|
|
360
|
-
|
|
327
|
+
recipients.push(address);
|
|
361
328
|
}
|
|
362
329
|
return recipients;
|
|
363
330
|
}
|
|
@@ -401,7 +368,9 @@ function normalizedDeliveryResult(value){
|
|
|
401
368
|
|
|
402
369
|
function publicSendResult(record){
|
|
403
370
|
return {
|
|
371
|
+
...record,
|
|
404
372
|
...(record.result||{}),
|
|
373
|
+
report:JSON.parse(record.serializedReport),
|
|
405
374
|
reportKey:record.reportKey,
|
|
406
375
|
state:record.state,
|
|
407
376
|
status:record.result?.status||record.state,
|
|
@@ -413,15 +382,11 @@ function publicSendResult(record){
|
|
|
413
382
|
}
|
|
414
383
|
|
|
415
384
|
function safeDrainDetail(summary){
|
|
416
|
-
return
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
invalidRecords:summary.invalidRecords,
|
|
422
|
-
bounded:summary.bounded,
|
|
423
|
-
pending:summary.pending,
|
|
424
|
-
states:Object.freeze({...summary.states})
|
|
385
|
+
return completeResult({
|
|
386
|
+
...summary,
|
|
387
|
+
records:[...summary.records],
|
|
388
|
+
invalidRecords:[...summary.invalidRecords],
|
|
389
|
+
states:completeResult({...summary.states})
|
|
425
390
|
});
|
|
426
391
|
}
|
|
427
392
|
|
|
@@ -468,13 +433,7 @@ function normalizeMailOptions(options){
|
|
|
468
433
|
isOnline,
|
|
469
434
|
onlineTarget,
|
|
470
435
|
outboxOptions:{
|
|
471
|
-
...(options.maxAttemptsPerDrain===undefined
|
|
472
|
-
?{}:{maxAttemptsPerDrain:options.maxAttemptsPerDrain}),
|
|
473
|
-
...(options.maxInvalidRecords===undefined
|
|
474
|
-
?{}:{maxInvalidRecords:options.maxInvalidRecords}),
|
|
475
|
-
...(options.maxRecords===undefined?{}:{maxRecords:options.maxRecords}),
|
|
476
436
|
...(options.lockManager===undefined?{}:{lockManager:options.lockManager}),
|
|
477
|
-
maxReportBytes:options.maxReportBytes??MAX_MESSAGE_BYTES,
|
|
478
437
|
},
|
|
479
438
|
storage:options.storage,
|
|
480
439
|
storageInjected:Object.hasOwn(options,'storage'),
|
|
@@ -563,7 +522,7 @@ class Mail {
|
|
|
563
522
|
get disposed(){return this.#disposed;}
|
|
564
523
|
get events(){return this.#events;}
|
|
565
524
|
get invalidOutboxRecords(){
|
|
566
|
-
return this.#outbox?.invalidRecords??
|
|
525
|
+
return this.#outbox?.invalidRecords??[];
|
|
567
526
|
}
|
|
568
527
|
get lastBackgroundError(){return this.#backgroundError;}
|
|
569
528
|
|
|
@@ -607,16 +566,14 @@ class Mail {
|
|
|
607
566
|
}
|
|
608
567
|
|
|
609
568
|
#publishState(detail,operationId=null){
|
|
610
|
-
this.#publish('mail-outbox-state',
|
|
569
|
+
this.#publish('mail-outbox-state',{...detail},operationId);
|
|
611
570
|
}
|
|
612
571
|
|
|
613
572
|
#publishRecord(record){
|
|
614
|
-
const stateDetail=
|
|
615
|
-
|
|
616
|
-
state:record.state,
|
|
617
|
-
attempts:record.attempts,
|
|
573
|
+
const stateDetail={
|
|
574
|
+
...record,
|
|
618
575
|
pending:PENDING_OUTBOX_STATES.has(record.state)
|
|
619
|
-
}
|
|
576
|
+
};
|
|
620
577
|
this.#publish('mail-outbox-state',stateDetail,record.reportKey);
|
|
621
578
|
if(record.attempts<1||record.state==='queued'||record.state==='sending') return;
|
|
622
579
|
const outcome={
|
|
@@ -626,12 +583,11 @@ class Mail {
|
|
|
626
583
|
reconciliation_required:'reconciliation_required'
|
|
627
584
|
}[record.state];
|
|
628
585
|
if(!outcome) return;
|
|
629
|
-
this.#publish('mail-outbox-delivery',
|
|
630
|
-
|
|
631
|
-
state:record.state,
|
|
586
|
+
this.#publish('mail-outbox-delivery',{
|
|
587
|
+
...record,
|
|
632
588
|
outcome,
|
|
633
589
|
uncertain:record.failure?.uncertain===true
|
|
634
|
-
}
|
|
590
|
+
},record.reportKey);
|
|
635
591
|
}
|
|
636
592
|
|
|
637
593
|
#handleOutboxRecord(record){
|
|
@@ -652,7 +608,6 @@ class Mail {
|
|
|
652
608
|
...(request.signal?{signal:request.signal}:{})
|
|
653
609
|
});
|
|
654
610
|
}
|
|
655
|
-
assertNativeReportSize(request.serializedReport);
|
|
656
611
|
try{
|
|
657
612
|
const result=await globalThis.Arcane.mail.send({
|
|
658
613
|
report:request.report,
|
|
@@ -821,8 +776,8 @@ class Mail {
|
|
|
821
776
|
return (await this.#getOutbox()).repairInvalid(fileName,replacement);
|
|
822
777
|
}
|
|
823
778
|
|
|
824
|
-
async quarantineInvalidOutbox(
|
|
825
|
-
return (await this.#getOutbox()).quarantineInvalid(
|
|
779
|
+
async quarantineInvalidOutbox(){
|
|
780
|
+
return (await this.#getOutbox()).quarantineInvalid();
|
|
826
781
|
}
|
|
827
782
|
|
|
828
783
|
stop(){
|
|
@@ -857,10 +812,10 @@ class Mail {
|
|
|
857
812
|
|
|
858
813
|
async send(to=[], subject='', payload={}, messageStyle='', messageType='') {
|
|
859
814
|
this.#assertActive();
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
throw new TypeError(`Mail subject must contain 1-${MAX_SUBJECT_LENGTH} characters without line breaks`);
|
|
815
|
+
if(typeof subject!=='string'){
|
|
816
|
+
throw new TypeError('Mail subject must be a string');
|
|
863
817
|
}
|
|
818
|
+
const normalizedSubject=subject;
|
|
864
819
|
if(!payload||typeof payload!=='object'||Array.isArray(payload)){
|
|
865
820
|
throw new TypeError('Mail payload must be an object');
|
|
866
821
|
}
|
|
@@ -904,7 +859,6 @@ class Mail {
|
|
|
904
859
|
to:recipients,
|
|
905
860
|
type:messageType,
|
|
906
861
|
};
|
|
907
|
-
assertMessageSize(reportPayload.report);
|
|
908
862
|
const record=await outbox.enqueue(
|
|
909
863
|
{report:reportPayload.report,reportKey},
|
|
910
864
|
{signal}
|
|
@@ -933,14 +887,9 @@ class Mail {
|
|
|
933
887
|
? `<pre>${escapeHtml(serialized)}</pre>`
|
|
934
888
|
: serialized;
|
|
935
889
|
|
|
936
|
-
const sourceUser=String(reportPayload.source_user||'')
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
.slice(0,80);
|
|
940
|
-
const subjectSuffix=sourceUser ? ` - ${sourceUser}`:'';
|
|
941
|
-
const deliverySubject=normalizedSubject.length+subjectSuffix.length<=MAX_SUBJECT_LENGTH
|
|
942
|
-
? `${normalizedSubject}${subjectSuffix}`
|
|
943
|
-
: normalizedSubject;
|
|
890
|
+
const sourceUser=String(reportPayload.source_user||'');
|
|
891
|
+
const subjectSuffix=sourceUser?` - ${sourceUser}`:'';
|
|
892
|
+
const deliverySubject=`${normalizedSubject}${subjectSuffix}`;
|
|
944
893
|
|
|
945
894
|
reportPayload.report = {
|
|
946
895
|
subject:deliverySubject,
|
|
@@ -960,7 +909,6 @@ Email: ${profile.email || 'not provided'}`
|
|
|
960
909
|
:generatedMessage;
|
|
961
910
|
}
|
|
962
911
|
|
|
963
|
-
assertMessageSize(reportPayload.report);
|
|
964
912
|
throwIfMailAborted(signal);
|
|
965
913
|
const record=await outbox.enqueue(
|
|
966
914
|
{report:reportPayload.report,reportKey},
|