arcane-os 0.46.0 → 0.48.0
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 +42 -0
- package/README.md +1 -1
- package/browser-runtime/ai/browser-speech-recognition.mjs +495 -0
- package/browser-runtime/ai/browser-speech.mjs +1 -0
- package/docs/reference/ai/browser-speech.md +80 -2
- package/docs/reference/availability-and-normalization.md +2 -1
- package/docs/reference/inventory/package-api.json +14 -0
- package/docs/reference/runtime-components.md +89 -14
- package/docs/reference/runtime-modules.md +55 -12
- package/docs/reference/sdk-api.md +57 -0
- package/package.json +1 -1
- package/runtime/arcane/components/chat.html +223 -2
- package/runtime/arcane/components/speech.html +263 -14
- package/runtime/arcane/components/voice-transcription.html +77 -10
- package/runtime/arcane/css/document-site.css +2 -35
- package/runtime/arcane/css/print.css +235 -0
- package/runtime/arcane/css/theme.css +2 -40
- package/runtime/arcane/modules/AI.js +15 -4
- package/runtime/arcane/modules/AIProviderRuntime.js +118 -0
- package/runtime/arcane/modules/PrintView.js +19 -55
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/* Shared paper presentation for direct pages and rendered PrintView snapshots.
|
|
2
|
+
* Theme/document styles import this file. PrintView loads the same complete
|
|
3
|
+
* text before registration so native beforeprint performs no asynchronous I/O.
|
|
4
|
+
*/
|
|
5
|
+
:root,
|
|
6
|
+
:host{
|
|
7
|
+
--arcane-print-paper:rgb(255, 255, 255);
|
|
8
|
+
--arcane-print-text:rgb(23, 34, 56);
|
|
9
|
+
--arcane-print-secondary:rgb(229, 233, 243);
|
|
10
|
+
--arcane-print-border:rgb(203, 211, 226);
|
|
11
|
+
--arcane-print-focus:rgb(118, 87, 213);
|
|
12
|
+
--arcane-print-muted:rgb(95, 107, 130);
|
|
13
|
+
--arcane-print-success:rgb(39, 122, 75);
|
|
14
|
+
--arcane-print-warning:rgb(154, 101, 0);
|
|
15
|
+
--arcane-print-danger:rgb(165, 56, 56);
|
|
16
|
+
--arcane-print-review:rgb(133, 85, 165);
|
|
17
|
+
--arcane-print-shadow:rgba(23, 34, 56, .16);
|
|
18
|
+
--arcane-print-platinum:rgb(102, 112, 133);
|
|
19
|
+
--arcane-print-icon-filter:none;
|
|
20
|
+
--arcane-print-file-icon-filter:hue-rotate(8deg) saturate(.62) brightness(.86);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* Snapshot rules are scoped to PrintView-owned nodes, including its shadow
|
|
24
|
+
* host. The source document's typography and artwork remain on the clones.
|
|
25
|
+
*/
|
|
26
|
+
:host([data-arcane-print-stage]){
|
|
27
|
+
color-scheme:light!important;
|
|
28
|
+
color:var(--arcane-print-text)!important;
|
|
29
|
+
background:var(--arcane-print-paper)!important;
|
|
30
|
+
font:12pt/1.5 serif;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
:host([data-arcane-print-stage])>h1{
|
|
34
|
+
margin:0 0 .75em;
|
|
35
|
+
font-size:1.5em;
|
|
36
|
+
line-height:1.2;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
[data-arcane-print-node]:not(svg,svg *,img,video,audio),
|
|
40
|
+
[data-arcane-print-node]:not(svg,svg *,img,video,audio)::before,
|
|
41
|
+
[data-arcane-print-node]:not(svg,svg *,img,video,audio)::after{
|
|
42
|
+
color:var(--arcane-print-text)!important;
|
|
43
|
+
background-color:transparent!important;
|
|
44
|
+
border-color:var(--arcane-print-border)!important;
|
|
45
|
+
color-scheme:light!important;
|
|
46
|
+
-webkit-text-fill-color:currentColor!important;
|
|
47
|
+
-webkit-text-stroke:0!important;
|
|
48
|
+
text-decoration-color:currentColor!important;
|
|
49
|
+
text-shadow:none!important;
|
|
50
|
+
box-shadow:none!important;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
a[data-arcane-print-node]:not(svg *){text-decoration:underline!important;}
|
|
54
|
+
table[data-arcane-print-node]:not(svg *){border-collapse:collapse!important;}
|
|
55
|
+
th[data-arcane-print-node]:not(svg *),
|
|
56
|
+
td[data-arcane-print-node]:not(svg *){
|
|
57
|
+
border:1px solid var(--arcane-print-border)!important;
|
|
58
|
+
padding:.35em .5em!important;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
[data-arcane-print-expand]{
|
|
62
|
+
height:auto!important;
|
|
63
|
+
min-height:0!important;
|
|
64
|
+
max-height:none!important;
|
|
65
|
+
width:auto!important;
|
|
66
|
+
min-width:0!important;
|
|
67
|
+
max-width:100%!important;
|
|
68
|
+
overflow:visible!important;
|
|
69
|
+
contain:none!important;
|
|
70
|
+
content-visibility:visible!important;
|
|
71
|
+
grid-template-rows:none!important;
|
|
72
|
+
break-inside:auto!important;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
img[data-arcane-print-node]{max-width:100%!important;height:auto!important;}
|
|
76
|
+
[data-arcane-print-static]{position:static!important;}
|
|
77
|
+
[data-arcane-print-root]{visibility:visible!important;}
|
|
78
|
+
[data-arcane-print-block]{display:block!important;}
|
|
79
|
+
pre[data-arcane-print-node]{white-space:pre-wrap!important;overflow-wrap:anywhere!important;}
|
|
80
|
+
table[data-arcane-print-node]{table-layout:auto!important;}
|
|
81
|
+
thead[data-arcane-print-node]{display:table-header-group!important;}
|
|
82
|
+
tfoot[data-arcane-print-node]{display:table-footer-group!important;}
|
|
83
|
+
td[data-arcane-print-node],
|
|
84
|
+
th[data-arcane-print-node]{overflow-wrap:anywhere!important;white-space:normal!important;}
|
|
85
|
+
|
|
86
|
+
/* Chat supplies the rendered transcript, not controls or session status.
|
|
87
|
+
* Keep public tool messages; inspection details and thinking are transient.
|
|
88
|
+
*/
|
|
89
|
+
.chat_output[data-arcane-print-node]{
|
|
90
|
+
display:block!important;
|
|
91
|
+
margin:0!important;
|
|
92
|
+
padding:0!important;
|
|
93
|
+
border:0!important;
|
|
94
|
+
border-radius:0!important;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.chat_output[data-arcane-print-node]>li{
|
|
98
|
+
display:block!important;
|
|
99
|
+
float:none!important;
|
|
100
|
+
clear:both!important;
|
|
101
|
+
max-inline-size:100%!important;
|
|
102
|
+
text-align:start!important;
|
|
103
|
+
margin:0 0 1em!important;
|
|
104
|
+
padding:0!important;
|
|
105
|
+
border:0!important;
|
|
106
|
+
border-radius:0!important;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.chat_output[data-arcane-print-node]>li [data-arcane-print-node]:not(.message_timestamp){
|
|
110
|
+
text-align:start!important;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.chat_output[data-arcane-print-node]>li>.thinking,
|
|
114
|
+
.chat_output[data-arcane-print-node]>li>.message_tool_details,
|
|
115
|
+
.chat_output[data-arcane-print-node]>li>.message_tool_calls>.message_tool_call>.message_tool_details,
|
|
116
|
+
.chat_output[data-arcane-print-node]>li:has(>.thinking):has(>.markdown:empty):not(:has(.message_tool_message)){
|
|
117
|
+
display:none!important;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
[data-arcane-print-stage]{display:none!important;}
|
|
121
|
+
|
|
122
|
+
@media print{
|
|
123
|
+
@page{margin:1in;}
|
|
124
|
+
|
|
125
|
+
:root,
|
|
126
|
+
body,
|
|
127
|
+
[data-arcane-palette]{
|
|
128
|
+
color-scheme:light!important;
|
|
129
|
+
--background:var(--arcane-print-paper)!important;
|
|
130
|
+
--modal-background:var(--arcane-print-paper)!important;
|
|
131
|
+
--text-color:var(--arcane-print-text)!important;
|
|
132
|
+
--primary-color:var(--arcane-print-text)!important;
|
|
133
|
+
--secondary-color:var(--arcane-print-secondary)!important;
|
|
134
|
+
--accent-color:var(--focus-color)!important;
|
|
135
|
+
--button-text-color:var(--arcane-print-paper)!important;
|
|
136
|
+
--border-color:var(--arcane-print-border)!important;
|
|
137
|
+
--focus-color:var(--arcane-print-focus)!important;
|
|
138
|
+
--muted-text-color:var(--arcane-print-muted)!important;
|
|
139
|
+
--success-color:var(--arcane-print-success)!important;
|
|
140
|
+
--warning-color:var(--arcane-print-warning)!important;
|
|
141
|
+
--danger-color:var(--arcane-print-danger)!important;
|
|
142
|
+
--review-color:var(--arcane-print-review)!important;
|
|
143
|
+
--shadow-color:var(--arcane-print-shadow)!important;
|
|
144
|
+
--platinum:var(--arcane-print-platinum)!important;
|
|
145
|
+
--icon-filter:var(--arcane-print-icon-filter)!important;
|
|
146
|
+
--file-icon-filter:var(--arcane-print-file-icon-filter)!important;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
html,
|
|
150
|
+
body{
|
|
151
|
+
margin:0;
|
|
152
|
+
background-color:var(--modal-background);
|
|
153
|
+
color:var(--text-color);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* The shared screen shell has a sidebar grid and a viewport-height main
|
|
157
|
+
* scroller. Paper uses the same main content in ordinary document flow.
|
|
158
|
+
*/
|
|
159
|
+
html:has(>body>main),
|
|
160
|
+
body:has(>main),
|
|
161
|
+
body>main,
|
|
162
|
+
body>main .data-workspace{
|
|
163
|
+
display:block!important;
|
|
164
|
+
position:static!important;
|
|
165
|
+
width:auto!important;
|
|
166
|
+
height:auto!important;
|
|
167
|
+
min-height:0!important;
|
|
168
|
+
max-height:none!important;
|
|
169
|
+
overflow:visible!important;
|
|
170
|
+
contain:none!important;
|
|
171
|
+
grid-template-columns:none!important;
|
|
172
|
+
grid-template-rows:none!important;
|
|
173
|
+
margin:0!important;
|
|
174
|
+
padding:0!important;
|
|
175
|
+
border:0!important;
|
|
176
|
+
border-radius:0!important;
|
|
177
|
+
box-shadow:none!important;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
body:has(>main)>.header,
|
|
181
|
+
body:has(>main)>.nav{
|
|
182
|
+
display:none!important;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* Expand only when an owned rendered snapshot is actually present. */
|
|
186
|
+
html:root:has(>body>[data-arcane-print-stage]),
|
|
187
|
+
html:root>body:has(>[data-arcane-print-stage]){
|
|
188
|
+
display:block!important;
|
|
189
|
+
height:auto!important;
|
|
190
|
+
min-height:0!important;
|
|
191
|
+
max-height:none!important;
|
|
192
|
+
overflow:visible!important;
|
|
193
|
+
contain:none!important;
|
|
194
|
+
margin:0!important;
|
|
195
|
+
padding:0!important;
|
|
196
|
+
border:0!important;
|
|
197
|
+
background:var(--arcane-print-paper)!important;
|
|
198
|
+
color:var(--arcane-print-text)!important;
|
|
199
|
+
color-scheme:light!important;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
html:root>body:has(>[data-arcane-print-stage])>*:not([data-arcane-print-stage]),
|
|
203
|
+
html:root>body:has(>[data-arcane-print-stage])::before,
|
|
204
|
+
html:root>body:has(>[data-arcane-print-stage])::after{
|
|
205
|
+
display:none!important;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
html:root>body>[data-arcane-print-stage]{
|
|
209
|
+
display:block!important;
|
|
210
|
+
position:static!important;
|
|
211
|
+
width:auto!important;
|
|
212
|
+
height:auto!important;
|
|
213
|
+
overflow:visible!important;
|
|
214
|
+
margin:0!important;
|
|
215
|
+
padding:0!important;
|
|
216
|
+
border:0!important;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
body.static-doc-site :is(.static-site-header,.static-site-footer,.static-section-nav,.static-previous-next,.static-related,.static-document__source,.skip-link){
|
|
220
|
+
display:none!important;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
body.static-doc-site :is(.static-site-main,.static-site-main--document){
|
|
224
|
+
max-inline-size:none!important;
|
|
225
|
+
padding:0!important;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
body.static-doc-site .static-document-layout{display:block!important;}
|
|
229
|
+
body.static-doc-site .static-document{inline-size:100%!important;}
|
|
230
|
+
body.static-doc-site .static-document__content table{display:table!important;overflow:visible!important;}
|
|
231
|
+
body.static-doc-site .static-document__content table :where(code,kbd){
|
|
232
|
+
overflow-wrap:anywhere!important;
|
|
233
|
+
word-break:break-word!important;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@import url('./print.css');
|
|
2
|
+
|
|
1
3
|
/* Shared default and named palettes. layout.css imports this owner, and
|
|
2
4
|
* standalone applications may load it directly before their own styles.
|
|
3
5
|
* data-user-skin selects the root palette; data-arcane-palette scopes a swatch.
|
|
@@ -328,43 +330,3 @@ body{
|
|
|
328
330
|
transition-duration:.01ms !important;
|
|
329
331
|
}
|
|
330
332
|
|
|
331
|
-
/* Paper uses the existing base light palette regardless of the screen skin.
|
|
332
|
-
* Print-only importance also overrides custom-theme inline tokens; no saved
|
|
333
|
-
* preference, screen layout, media paint, or scrolling state changes here.
|
|
334
|
-
*/
|
|
335
|
-
@media print {
|
|
336
|
-
@page {
|
|
337
|
-
margin: 15mm;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
:root,
|
|
341
|
-
body,
|
|
342
|
-
[data-arcane-palette] {
|
|
343
|
-
color-scheme: light !important;
|
|
344
|
-
--background: rgb(255, 255, 255) !important;
|
|
345
|
-
--modal-background: rgb(255, 255, 255) !important;
|
|
346
|
-
--text-color: rgb(23, 34, 56) !important;
|
|
347
|
-
--primary-color: rgb(23, 34, 56) !important;
|
|
348
|
-
--secondary-color: rgb(229, 233, 243) !important;
|
|
349
|
-
--accent-color: var(--focus-color) !important;
|
|
350
|
-
--button-text-color: rgb(255, 255, 255) !important;
|
|
351
|
-
--border-color: rgb(203, 211, 226) !important;
|
|
352
|
-
--focus-color: rgb(118, 87, 213) !important;
|
|
353
|
-
--muted-text-color: rgb(95, 107, 130) !important;
|
|
354
|
-
--success-color: rgb(39, 122, 75) !important;
|
|
355
|
-
--warning-color: rgb(154, 101, 0) !important;
|
|
356
|
-
--danger-color: rgb(165, 56, 56) !important;
|
|
357
|
-
--review-color: rgb(133, 85, 165) !important;
|
|
358
|
-
--shadow-color: rgba(23, 34, 56, .16) !important;
|
|
359
|
-
--platinum: rgb(102, 112, 133) !important;
|
|
360
|
-
--icon-filter: none !important;
|
|
361
|
-
--file-icon-filter: hue-rotate(8deg) saturate(.62) brightness(.86) !important;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
html,
|
|
365
|
-
body {
|
|
366
|
-
margin: 0;
|
|
367
|
-
background-color: var(--modal-background);
|
|
368
|
-
color: var(--text-color);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
@@ -2081,8 +2081,10 @@ class AI {
|
|
|
2081
2081
|
#assertDeviceSpeechConfiguration(configuration){
|
|
2082
2082
|
for(const routeName of ['default','localOnly']){
|
|
2083
2083
|
const selection=configuration?.stt?.[routeName];
|
|
2084
|
-
|
|
2085
|
-
|
|
2084
|
+
const liveCapture=selection
|
|
2085
|
+
&&this.#providerRuntime.supportsTranscriptionCapture(selection.providerId);
|
|
2086
|
+
if(selection&&selection.localOnly!==true&&!liveCapture){
|
|
2087
|
+
const error=new TypeError('Speech recognition requires an on-device or explicitly selected live-capture provider.');
|
|
2086
2088
|
error.code='AI_STT_DEVICE_ONLY';
|
|
2087
2089
|
throw error;
|
|
2088
2090
|
}
|
|
@@ -3430,8 +3432,9 @@ class AI {
|
|
|
3430
3432
|
if(provider!==null&&provider?.role!==role){
|
|
3431
3433
|
throw new TypeError('The speech provider must implement the selected role.');
|
|
3432
3434
|
}
|
|
3433
|
-
if(role==='stt'&&provider&&provider.localOnly!==true
|
|
3434
|
-
|
|
3435
|
+
if(role==='stt'&&provider&&provider.localOnly!==true
|
|
3436
|
+
&&!is.function(provider.createCapture)){
|
|
3437
|
+
const error=new TypeError('Speech recognition requires an on-device or explicitly selected live-capture provider.');
|
|
3435
3438
|
error.code='AI_STT_DEVICE_ONLY';
|
|
3436
3439
|
throw error;
|
|
3437
3440
|
}
|
|
@@ -6875,6 +6878,14 @@ class AI {
|
|
|
6875
6878
|
}
|
|
6876
6879
|
}
|
|
6877
6880
|
|
|
6881
|
+
supportsTranscriptionCapture(){
|
|
6882
|
+
return this.#providerRuntime.supportsTranscriptionCapture();
|
|
6883
|
+
}
|
|
6884
|
+
|
|
6885
|
+
createTranscriptionCapture(options={}){
|
|
6886
|
+
return this.#providerRuntime.createTranscriptionCapture(options);
|
|
6887
|
+
}
|
|
6888
|
+
|
|
6878
6889
|
async fetchSTT(audioFile,signal=null){
|
|
6879
6890
|
const callId=this.#traceSpeech('fetchSTT.call',{audioFile,aborted:signal?.aborted});
|
|
6880
6891
|
try{
|
|
@@ -1366,6 +1366,9 @@ function validateProvider(provider) {
|
|
|
1366
1366
|
for (const method of PROVIDER_METHODS) {
|
|
1367
1367
|
record[method] = provider[method].bind(provider);
|
|
1368
1368
|
}
|
|
1369
|
+
if (provider.role === 'stt' && is.function(provider.createCapture)) {
|
|
1370
|
+
record.createCapture = provider.createCapture.bind(provider);
|
|
1371
|
+
}
|
|
1369
1372
|
const admitted = completeValue(record);
|
|
1370
1373
|
PROVIDER_RECORDS.set(provider, admitted);
|
|
1371
1374
|
return admitted;
|
|
@@ -4103,6 +4106,121 @@ export class AIProviderRuntime {
|
|
|
4103
4106
|
return this.#roleRequestAlias('llm', 'stream', payload, options);
|
|
4104
4107
|
}
|
|
4105
4108
|
|
|
4109
|
+
supportsTranscriptionCapture(providerId = null) {
|
|
4110
|
+
const slot = this.#slots.stt;
|
|
4111
|
+
const provider = providerId === null
|
|
4112
|
+
? this.#providerFor(slot)
|
|
4113
|
+
: this.#providers.get(providerKey('stt', providerId));
|
|
4114
|
+
return is.function(provider?.createCapture);
|
|
4115
|
+
}
|
|
4116
|
+
|
|
4117
|
+
createTranscriptionCapture(options = {}) {
|
|
4118
|
+
this.#assertOpen();
|
|
4119
|
+
this.#assertNotConfiguring();
|
|
4120
|
+
const slot = this.#slots.stt;
|
|
4121
|
+
const provider = this.#providerFor(slot);
|
|
4122
|
+
if (!is.function(provider?.createCapture)) return null;
|
|
4123
|
+
|
|
4124
|
+
const runtime = this;
|
|
4125
|
+
const generation = slot.generation;
|
|
4126
|
+
const capture = provider.createCapture(options);
|
|
4127
|
+
const controller = new AbortController();
|
|
4128
|
+
let requestRecord = null;
|
|
4129
|
+
let detachSignal = null;
|
|
4130
|
+
let started = false;
|
|
4131
|
+
let closed = false;
|
|
4132
|
+
const done = Promise.resolve(capture.done).finally(
|
|
4133
|
+
function releaseTranscriptionCapture() {
|
|
4134
|
+
closed = true;
|
|
4135
|
+
detachSignal?.();
|
|
4136
|
+
if (!requestRecord) return;
|
|
4137
|
+
slot.activeRequests.delete(requestRecord.requestSequence);
|
|
4138
|
+
runtime.#drainRoleRequestQueue(slot);
|
|
4139
|
+
if (slot.generation !== generation || slot.unloadPromise) return;
|
|
4140
|
+
if (slot.activeRequests.size || slot.requestQueue.length) {
|
|
4141
|
+
runtime.#publishRoleRequestState(slot);
|
|
4142
|
+
return;
|
|
4143
|
+
}
|
|
4144
|
+
const status = validateProviderStatus(provider.status());
|
|
4145
|
+
slot.ready = status.state === 'ready' && status.loaded && !status.busy;
|
|
4146
|
+
publishAIRuntimeRoleState(
|
|
4147
|
+
'stt',
|
|
4148
|
+
roleRecord(
|
|
4149
|
+
'stt',
|
|
4150
|
+
slot.selection,
|
|
4151
|
+
{state: slot.ready ? 'ready' : 'unloaded', loaded: status.loaded}
|
|
4152
|
+
)
|
|
4153
|
+
);
|
|
4154
|
+
}
|
|
4155
|
+
);
|
|
4156
|
+
done.catch(
|
|
4157
|
+
function observeTranscriptionCaptureCleanupFailure(error) {
|
|
4158
|
+
arcaneLogging.error('Transcription capture cleanup failed.', error);
|
|
4159
|
+
}
|
|
4160
|
+
);
|
|
4161
|
+
// Capture has its own synchronous start boundary so native microphone
|
|
4162
|
+
// permission retains the originating user gesture. It is never queued.
|
|
4163
|
+
return {
|
|
4164
|
+
done,
|
|
4165
|
+
start({signal} = {}) {
|
|
4166
|
+
if (started || closed) return Promise.resolve(false);
|
|
4167
|
+
try {
|
|
4168
|
+
runtime.#assertOpen();
|
|
4169
|
+
runtime.#assertNotConfiguring();
|
|
4170
|
+
const status = validateProviderStatus(provider.status());
|
|
4171
|
+
if (slot.generation !== generation || !slot.ready
|
|
4172
|
+
|| slot.unloadPromise || slot.disposePromise
|
|
4173
|
+
|| slot.activeRequests.size || slot.requestQueue.length
|
|
4174
|
+
|| status.state !== 'ready' || !status.loaded || status.busy) {
|
|
4175
|
+
throw operationError(
|
|
4176
|
+
'The selected transcription capture provider is not ready.',
|
|
4177
|
+
'ARCANE_AI_ROLE_NOT_READY'
|
|
4178
|
+
);
|
|
4179
|
+
}
|
|
4180
|
+
assertAbortSignal(signal);
|
|
4181
|
+
started = true;
|
|
4182
|
+
detachSignal = runtime.#forwardAbort(signal, controller);
|
|
4183
|
+
const requestSequence = runtime.#nextRequestSequence(slot);
|
|
4184
|
+
requestRecord = {
|
|
4185
|
+
controller,
|
|
4186
|
+
requestSequence,
|
|
4187
|
+
operationId: runtime.#nextOperationId(slot, 'capture'),
|
|
4188
|
+
promise: done,
|
|
4189
|
+
cancel: function cancelOwnedTranscriptionCapture(reason) {
|
|
4190
|
+
controller.abort(reason);
|
|
4191
|
+
capture.cancel();
|
|
4192
|
+
return done;
|
|
4193
|
+
}
|
|
4194
|
+
};
|
|
4195
|
+
slot.activeRequests.set(requestSequence, requestRecord);
|
|
4196
|
+
runtime.#publishRoleRequestState(slot);
|
|
4197
|
+
const starting = capture.start({signal: controller.signal});
|
|
4198
|
+
return Promise.resolve(starting).catch(
|
|
4199
|
+
function releaseFailedTranscriptionCaptureStart(error) {
|
|
4200
|
+
capture.cancel();
|
|
4201
|
+
throw error;
|
|
4202
|
+
}
|
|
4203
|
+
);
|
|
4204
|
+
} catch (error) {
|
|
4205
|
+
capture.cancel();
|
|
4206
|
+
throw error;
|
|
4207
|
+
}
|
|
4208
|
+
},
|
|
4209
|
+
stop() {
|
|
4210
|
+
capture.stop();
|
|
4211
|
+
return done;
|
|
4212
|
+
},
|
|
4213
|
+
cancel() {
|
|
4214
|
+
controller.abort();
|
|
4215
|
+
capture.cancel();
|
|
4216
|
+
},
|
|
4217
|
+
destroy() {
|
|
4218
|
+
controller.abort();
|
|
4219
|
+
capture.destroy();
|
|
4220
|
+
}
|
|
4221
|
+
};
|
|
4222
|
+
}
|
|
4223
|
+
|
|
4106
4224
|
transcribe(payload, options = {}) {
|
|
4107
4225
|
arcaneLogging.debug('[Arcane speech runtime] transcribe', payload, options);
|
|
4108
4226
|
return this.#roleRequestAlias('stt', 'transcribe', payload, options);
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import Is from 'strong-type';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
// Components import this module independently of their rendering. Await only
|
|
4
|
+
// the required print stylesheet here so every registered view is ready for the
|
|
5
|
+
// synchronous native beforeprint event, with no stylesheet fetch during print.
|
|
6
|
+
const printResponse=await fetch(new URL('../css/print.css',import.meta.url));
|
|
7
|
+
if(!printResponse.ok){
|
|
8
|
+
throw new Error(`Unable to load shared print styles: HTTP ${printResponse.status}.`);
|
|
9
|
+
}
|
|
10
|
+
const printStyles=await printResponse.text();
|
|
3
11
|
|
|
4
12
|
const is=new Is(false);
|
|
5
13
|
const registries=new WeakMap();
|
|
@@ -401,38 +409,13 @@ function capture(registry,session){
|
|
|
401
409
|
const heading=document.createElement('h1');
|
|
402
410
|
heading.textContent=session.title;
|
|
403
411
|
const rendered=copyRendered(session.content,state,true);
|
|
404
|
-
//
|
|
405
|
-
//
|
|
406
|
-
|
|
407
|
-
styles.textContent=`
|
|
408
|
-
:host{color-scheme:light!important;color:${arcaneLightThemeTokens.text}!important;background:${arcaneLightThemeTokens.surface}!important;font:12pt/1.5 serif}
|
|
409
|
-
:host>h1{margin:0 0 .75em;font-size:1.5em;line-height:1.2}
|
|
410
|
-
[data-arcane-print-node]:not(svg,svg *,img,video,audio),
|
|
411
|
-
[data-arcane-print-node]:not(svg,svg *,img,video,audio)::before,
|
|
412
|
-
[data-arcane-print-node]:not(svg,svg *,img,video,audio)::after{
|
|
413
|
-
color:${arcaneLightThemeTokens.text}!important;background-color:transparent!important;
|
|
414
|
-
border-color:${arcaneLightThemeTokens.border}!important;color-scheme:light!important;
|
|
415
|
-
-webkit-text-fill-color:currentColor!important;-webkit-text-stroke:0!important;
|
|
416
|
-
text-decoration-color:currentColor!important;text-shadow:none!important;box-shadow:none!important
|
|
417
|
-
}
|
|
418
|
-
a[data-arcane-print-node]:not(svg *){text-decoration:underline!important}
|
|
419
|
-
table[data-arcane-print-node]:not(svg *){border-collapse:collapse!important}
|
|
420
|
-
th[data-arcane-print-node]:not(svg *),td[data-arcane-print-node]:not(svg *){border:1px solid ${arcaneLightThemeTokens.border}!important;padding:.35em .5em!important}
|
|
421
|
-
${state.rules.join('\n')}
|
|
422
|
-
`;
|
|
412
|
+
// Only captured pseudo-element declarations are generated here. Authored
|
|
413
|
+
// print palette, page margins, and expansion rules share the CSS owner.
|
|
414
|
+
styles.textContent=printStyles+'\n'+state.rules.join('\n');
|
|
423
415
|
root.append(styles,heading,rendered);
|
|
424
416
|
const sheet=document.createElement('style');
|
|
425
417
|
session.sheet=sheet;
|
|
426
|
-
sheet.textContent
|
|
427
|
-
[data-arcane-print-stage]{display:none!important}
|
|
428
|
-
@media print{
|
|
429
|
-
@page{margin:15mm}
|
|
430
|
-
html:root,html:root>body{display:block!important;height:auto!important;min-height:0!important;max-height:none!important;overflow:visible!important;contain:none!important;margin:0!important;padding:0!important;border:0!important;background:${arcaneLightThemeTokens.surface}!important;color:${arcaneLightThemeTokens.text}!important;color-scheme:light!important}
|
|
431
|
-
html:root>body>*:not([data-arcane-print-stage]){display:none!important}
|
|
432
|
-
html:root>body::before,html:root>body::after{display:none!important}
|
|
433
|
-
html:root>body>[data-arcane-print-stage]{display:block!important;position:static!important;width:auto!important;height:auto!important;overflow:visible!important;margin:0!important;padding:0!important;border:0!important}
|
|
434
|
-
}
|
|
435
|
-
`;
|
|
418
|
+
sheet.textContent=printStyles;
|
|
436
419
|
document.head.append(sheet);
|
|
437
420
|
document.body.append(stage);
|
|
438
421
|
session.originalTitle=document.title;
|
|
@@ -523,36 +506,17 @@ function copyRendered(source,state,root=false){
|
|
|
523
506
|
clone.selected=source.selected;
|
|
524
507
|
}
|
|
525
508
|
if(!['img','svg','video','audio','input','canvas'].includes(name)){
|
|
526
|
-
|
|
527
|
-
['height','auto'],['min-height','0'],['max-height','none'],
|
|
528
|
-
['width','auto'],['min-width','0'],['max-width','100%'],['overflow','visible'],
|
|
529
|
-
['contain','none'],['content-visibility','visible'],['grid-template-rows','none'],
|
|
530
|
-
['break-inside','auto']
|
|
531
|
-
]){
|
|
532
|
-
clone.style.setProperty(property,value);
|
|
533
|
-
}
|
|
534
|
-
}else if(name==='img'||name==='canvas'){
|
|
535
|
-
clone.style.setProperty('max-width','100%');
|
|
536
|
-
clone.style.setProperty('height','auto');
|
|
509
|
+
clone.setAttribute('data-arcane-print-expand','');
|
|
537
510
|
}
|
|
538
511
|
if(['absolute','fixed','sticky'].includes(appearance.position)){
|
|
539
|
-
clone.
|
|
512
|
+
clone.setAttribute('data-arcane-print-static','');
|
|
540
513
|
}
|
|
541
514
|
if(root||name==='iframe'){
|
|
542
515
|
clone.hidden=false;
|
|
543
|
-
clone.
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
clone.style.setProperty('white-space','pre-wrap');
|
|
548
|
-
clone.style.setProperty('overflow-wrap','anywhere');
|
|
549
|
-
}
|
|
550
|
-
if(name==='table'){
|
|
551
|
-
clone.style.setProperty('table-layout','auto');
|
|
552
|
-
}
|
|
553
|
-
if(name==='td'||name==='th'){
|
|
554
|
-
clone.style.setProperty('overflow-wrap','anywhere');
|
|
555
|
-
clone.style.setProperty('white-space','normal');
|
|
516
|
+
clone.setAttribute('data-arcane-print-root','');
|
|
517
|
+
if(appearance.display==='none'){
|
|
518
|
+
clone.setAttribute('data-arcane-print-block','');
|
|
519
|
+
}
|
|
556
520
|
}
|
|
557
521
|
if(name==='iframe'){
|
|
558
522
|
const embedded=frameDocument(source);
|