arcane-os 0.5.17 → 0.5.18
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 +24 -0
- package/README.md +9 -9
- package/bin/arcane-test.mjs +16 -13
- package/browser-runtime/ai/browser-speech-artifacts.mjs +41 -38
- package/browser-runtime/ai/browser-speech-providers.mjs +46 -43
- package/browser-runtime/ai/browser-wasm-llm-provider.mjs +127 -124
- package/browser-runtime/ai/browser-wasm.mjs +6 -3
- package/browser-runtime/ai/browser-wllama-runtime.mjs +26 -23
- package/browser-runtime/ai/model-controller.mjs +94 -91
- package/browser-runtime/ai/speech-worker-client.mjs +12 -9
- package/browser-runtime/ai/speech-worker-runtime.mjs +56 -53
- package/browser-runtime/dependencies/strong-type/index.js +207 -82
- package/browser-runtime/dependencies/strong-type/package.json +15 -6
- package/browser-runtime/dom-event-instrumentation.mjs +24 -20
- package/browser-runtime/event-manager.mjs +111 -108
- package/browser-runtime/speech-text.mjs +5 -1
- package/docs/reference/ai/browser-speech.md +198 -5
- package/docs/reference/availability-and-normalization.md +40 -0
- package/docs/reference/inventory/package-api.json +1 -1
- package/docs/reference/inventory/runtime-components.json +1 -1
- package/docs/reference/inventory/runtime-modules.json +20 -24
- package/docs/reference/protocols.md +1 -1
- package/docs/reference/runtime-modules.md +125 -35
- package/docs/reference/sdk-api.md +23 -7
- package/examples/wasm-ai-demo/index.html +1 -0
- package/node_modules/event-pubsub/node_modules/strong-type/README.md +408 -0
- package/node_modules/event-pubsub/node_modules/strong-type/assets/strong-type-header.png +0 -0
- package/node_modules/event-pubsub/node_modules/strong-type/index.js +1151 -0
- package/node_modules/event-pubsub/node_modules/strong-type/licence +21 -0
- package/node_modules/event-pubsub/node_modules/strong-type/node.js +125 -0
- package/node_modules/event-pubsub/node_modules/strong-type/package.json +61 -0
- package/node_modules/strong-type/README.md +42 -24
- package/node_modules/strong-type/benchmark/core.js +324 -0
- package/node_modules/strong-type/index.js +207 -82
- package/node_modules/strong-type/package.json +14 -6
- package/package.json +3 -3
- package/runtime/arcane/components/app-bar.html +5 -2
- package/runtime/arcane/components/assistant-panel.html +5 -2
- package/runtime/arcane/components/chart.html +15 -12
- package/runtime/arcane/components/chat.html +117 -138
- package/runtime/arcane/components/dashboard-config.html +6 -3
- package/runtime/arcane/components/data-view.html +4 -1
- package/runtime/arcane/components/directory-picker.html +5 -2
- package/runtime/arcane/components/document-inspector.html +6 -3
- package/runtime/arcane/components/file-drop.html +5 -2
- package/runtime/arcane/components/file-inspector.html +9 -6
- package/runtime/arcane/components/file-manager.html +16 -13
- package/runtime/arcane/components/local-ai-status.html +5 -2
- package/runtime/arcane/components/markdown-document.html +14 -11
- package/runtime/arcane/components/markdown-editor.html +4 -1
- package/runtime/arcane/components/modal.html +4 -1
- package/runtime/arcane/components/output-panel.html +6 -3
- package/runtime/arcane/components/preferences-form.html +4 -1
- package/runtime/arcane/components/record-timeline.html +8 -5
- package/runtime/arcane/components/relationship-board.html +9 -6
- package/runtime/arcane/components/source-code-viewer.html +12 -9
- package/runtime/arcane/components/source-explanation.html +8 -5
- package/runtime/arcane/components/speech.html +24 -21
- package/runtime/arcane/components/summary-strip.html +4 -1
- package/runtime/arcane/components/task-progress.html +6 -3
- package/runtime/arcane/components/terminal-workspace.html +4 -1
- package/runtime/arcane/components/voice-transcription.html +11 -8
- package/runtime/arcane/components/web-navigator.html +5 -2
- package/runtime/arcane/entities/ApiModelRecord.js +5 -2
- package/runtime/arcane/entities/Calculation.js +5 -2
- package/runtime/arcane/entities/Chat.js +33 -33
- package/runtime/arcane/entities/CommunicationMessage.js +4 -1
- package/runtime/arcane/entities/CommunicationThread.js +4 -1
- package/runtime/arcane/entities/File.js +1 -1
- package/runtime/arcane/entities/Image.js +8 -5
- package/runtime/arcane/entities/IntentEnvelope.js +20 -17
- package/runtime/arcane/entities/Preference.js +9 -6
- package/runtime/arcane/entities/Theme.js +5 -2
- package/runtime/arcane/entities/User.js +11 -11
- package/runtime/arcane/entities/Weather.js +5 -2
- package/runtime/arcane/modules/AI.js +491 -165
- package/runtime/arcane/modules/AIPreferenceRuntime.js +5 -2
- package/runtime/arcane/modules/AIPreferenceTuple.js +9 -6
- package/runtime/arcane/modules/AIProviderRuntime.js +88 -85
- package/runtime/arcane/modules/AIResponseURLPolicy.js +148 -62
- package/runtime/arcane/modules/AIRuntimeState.js +29 -26
- package/runtime/arcane/modules/AnsiText.js +4 -1
- package/runtime/arcane/modules/ApiModelDatabase.js +22 -19
- package/runtime/arcane/modules/AppDataScope.js +8 -5
- package/runtime/arcane/modules/ArcaneCommunicationBridge.js +4 -1
- package/runtime/arcane/modules/ArcaneNavigationPolicy.js +8 -5
- package/runtime/arcane/modules/ArcaneNetworkPolicy.js +18 -15
- package/runtime/arcane/modules/AsyncBoundary.js +13 -10
- package/runtime/arcane/modules/BrowserTestSuite.js +19 -16
- package/runtime/arcane/modules/CalculatorEngine.js +5 -2
- package/runtime/arcane/modules/ChatRecords.js +18 -15
- package/runtime/arcane/modules/CommunicationAppController.js +9 -6
- package/runtime/arcane/modules/CommunicationHub.js +9 -6
- package/runtime/arcane/modules/CommunicationPreferences.js +4 -1
- package/runtime/arcane/modules/CommunicationProviderRegistry.js +4 -1
- package/runtime/arcane/modules/ComponentContracts.js +56 -53
- package/runtime/arcane/modules/ConfiguredAIChatSession.js +30 -27
- package/runtime/arcane/modules/ConversationActionItems.js +15 -12
- package/runtime/arcane/modules/ConversationClosingReport.js +11 -8
- package/runtime/arcane/modules/ConversationTimebox.js +28 -25
- package/runtime/arcane/modules/CoreLocalModelCatalog.js +17 -14
- package/runtime/arcane/modules/DBLS.js +7 -4
- package/runtime/arcane/modules/DBOPFS.js +7 -7
- package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +34 -31
- package/runtime/arcane/modules/DevelopmentWorkspace.js +4 -1
- package/runtime/arcane/modules/DirectoryPicker.js +8 -5
- package/runtime/arcane/modules/DocumentLexicalSearch.js +11 -8
- package/runtime/arcane/modules/DocumentNavigation.js +7 -4
- package/runtime/arcane/modules/Errors.js +28 -25
- package/runtime/arcane/modules/HTMLImport.js +7 -4
- package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +15 -12
- package/runtime/arcane/modules/LocalAIReadiness.js +21 -18
- package/runtime/arcane/modules/LocalAIReadinessController.js +6 -3
- package/runtime/arcane/modules/MD.js +1 -1
- package/runtime/arcane/modules/Mail.js +46 -43
- package/runtime/arcane/modules/MailOutbox.mjs +48 -45
- package/runtime/arcane/modules/MailTransport.mjs +29 -26
- package/runtime/arcane/modules/MemoryRecords.js +7 -4
- package/runtime/arcane/modules/MessageAdvisory.js +6 -3
- package/runtime/arcane/modules/ModelDefinition.js +7 -4
- package/runtime/arcane/modules/Ollama.js +6 -3
- package/runtime/arcane/modules/OllamaModelIdentifier.js +4 -1
- package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +18 -15
- package/runtime/arcane/modules/PersistentAIChatSession.js +33 -30
- package/runtime/arcane/modules/PreferenceStore.js +20 -17
- package/runtime/arcane/modules/PreparedSpeech.js +485 -0
- package/runtime/arcane/modules/Questionnaire.js +6 -3
- package/runtime/arcane/modules/RecordLinkIndex.js +4 -1
- package/runtime/arcane/modules/RecordPassageIndex.js +9 -6
- package/runtime/arcane/modules/RecordReviewStore.js +12 -9
- package/runtime/arcane/modules/RiskSignalAnalyzer.js +4 -1
- package/runtime/arcane/modules/ScopedOPFSCache.js +6 -3
- package/runtime/arcane/modules/ScreenCapture.js +20 -17
- package/runtime/arcane/modules/SpeechPlayback.js +29 -26
- package/runtime/arcane/modules/StaticDocumentCatalog.js +33 -30
- package/runtime/arcane/modules/SystemAppearance.js +5 -2
- package/runtime/arcane/modules/SystemToolRegistry.js +6 -3
- package/runtime/arcane/modules/TerminalClient.js +14 -11
- package/runtime/arcane/modules/TerminalCommandRegistry.js +4 -1
- package/runtime/arcane/modules/ThemeBootstrap.js +9 -6
- package/runtime/arcane/modules/ThemeManager.js +5 -2
- package/runtime/arcane/modules/TimeGuard.js +1 -1
- package/runtime/arcane/modules/ToolCallRouter.js +11 -8
- package/runtime/arcane/modules/WaitForComponent.js +19 -16
- package/runtime/arcane/modules/YouTubeMedia.js +4 -1
- package/runtime/strong-type/index.js +1276 -352
- package/runtime/strong-type/package.json +69 -45
- package/src/app-descriptor.mjs +17 -14
- package/src/application-tests.mjs +4 -1
- package/src/cli/main.mjs +8 -5
- package/src/constants.mjs +4 -1
- package/src/dev-server.mjs +8 -5
- package/src/doctor.mjs +5 -2
- package/src/dom-event-instrumentation.mjs +24 -20
- package/src/errors.mjs +7 -3
- package/src/event-manager.mjs +111 -108
- package/src/event-queue.mjs +8 -5
- package/src/events.mjs +12 -9
- package/src/import-map.mjs +35 -27
- package/src/installed-sdk-runtime.mjs +4 -1
- package/src/integrated-provider-loader.mjs +9 -6
- package/src/mail-credentials.mjs +16 -13
- package/src/mail-server.mjs +53 -50
- package/src/mail.mjs +18 -15
- package/src/native-plan.mjs +12 -9
- package/src/native-provider-loader.mjs +7 -4
- package/src/packager/core.mjs +18 -15
- package/src/process.mjs +6 -3
- package/src/release-bundle.mjs +14 -11
- package/src/runtime.mjs +4 -1
- package/src/scaffold.mjs +9 -6
- package/src/sdk-browser-runtime.mjs +4 -1
- package/src/source-server.mjs +17 -14
- package/src/targets/index.mjs +5 -2
- package/src/templates/workspace-template.mjs +13 -6
- package/src/testing-loader.mjs +7 -4
- package/src/testing.mjs +10 -7
- package/src/toolchain.mjs +13 -10
- package/src/update-check.mjs +9 -6
- package/src/workspace-operation-lock.mjs +14 -11
- package/src/workspace-runtime.mjs +4 -1
- package/src/workspace.mjs +17 -14
- package/runtime/arcane/modules/AIResponseLength.js +0 -32
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import Is from 'strong-type';
|
|
2
|
+
const is=new Is(false);
|
|
3
|
+
|
|
1
4
|
import DocumentLexicalSearch,{
|
|
2
5
|
documentContextExcerpt,
|
|
3
6
|
documentSearchTokens,
|
|
@@ -31,8 +34,8 @@ function fail(message,code='DBOPFS_DOCUMENT_INVALID',ErrorType=TypeError){
|
|
|
31
34
|
|
|
32
35
|
function isPlainRecord(value){
|
|
33
36
|
return Boolean(value)
|
|
34
|
-
&&
|
|
35
|
-
&&!
|
|
37
|
+
&&is.object(value)
|
|
38
|
+
&&!is.array(value)
|
|
36
39
|
&&Object.getPrototypeOf(value)===Object.prototype;
|
|
37
40
|
}
|
|
38
41
|
|
|
@@ -42,7 +45,7 @@ function assertKnownKeys(value,allowed,label){
|
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
function boundedInteger(value,label,{minimum,maximum}){
|
|
45
|
-
if(!
|
|
48
|
+
if(!is.safeInteger(value)||value<minimum||(maximum!==undefined&&value>maximum)){
|
|
46
49
|
const range=maximum===undefined?`${minimum} or greater`:`${minimum} through ${maximum}`;
|
|
47
50
|
fail(`${label} must be an integer from ${range}.`,'DBOPFS_DOCUMENT_INVALID_LIMIT',RangeError);
|
|
48
51
|
}
|
|
@@ -51,7 +54,7 @@ function boundedInteger(value,label,{minimum,maximum}){
|
|
|
51
54
|
|
|
52
55
|
function normalizedText(value,label,{optional=false}={}){
|
|
53
56
|
if(optional&&(value===undefined||value===null||value==='')) return '';
|
|
54
|
-
if(
|
|
57
|
+
if(!is.string(value)) fail(`${label} must be a string.`);
|
|
55
58
|
const text=value;
|
|
56
59
|
if(!text.trim()&&!optional) fail(`${label} cannot be empty.`);
|
|
57
60
|
return text;
|
|
@@ -59,10 +62,10 @@ function normalizedText(value,label,{optional=false}={}){
|
|
|
59
62
|
|
|
60
63
|
function signalLike(value){
|
|
61
64
|
return value===undefined||value===null||(
|
|
62
|
-
|
|
63
|
-
&&
|
|
64
|
-
&&
|
|
65
|
-
&&
|
|
65
|
+
is.object(value)
|
|
66
|
+
&&is.boolean(value.aborted)
|
|
67
|
+
&&is.function(value.addEventListener)
|
|
68
|
+
&&is.function(value.removeEventListener)
|
|
66
69
|
);
|
|
67
70
|
}
|
|
68
71
|
|
|
@@ -80,7 +83,7 @@ async function yieldEvaluationTask(signal){
|
|
|
80
83
|
throwIfAborted(signal);
|
|
81
84
|
await new Promise((resolve,reject)=>{
|
|
82
85
|
try{
|
|
83
|
-
if(
|
|
86
|
+
if(is.function(globalThis.MessageChannel)){
|
|
84
87
|
const channel=new globalThis.MessageChannel();
|
|
85
88
|
channel.port1.onmessage=()=>{
|
|
86
89
|
channel.port1.close();
|
|
@@ -122,13 +125,13 @@ function normalizeSchema(input){
|
|
|
122
125
|
|
|
123
126
|
function stringList(value,label){
|
|
124
127
|
if(value===undefined||value===null) return [];
|
|
125
|
-
if(!
|
|
128
|
+
if(!is.array(value)) fail(`${label} must be an array.`);
|
|
126
129
|
return value.map((item,index)=>normalizedText(item,`${label} entry ${index+1}`));
|
|
127
130
|
}
|
|
128
131
|
|
|
129
132
|
function headings(value){
|
|
130
133
|
if(value===undefined||value===null) return [];
|
|
131
|
-
if(!
|
|
134
|
+
if(!is.array(value)) fail('Document headings must be an array.');
|
|
132
135
|
return value.map((item,index)=>{
|
|
133
136
|
if(!isPlainRecord(item)) fail(`Document heading ${index+1} must be a plain object.`);
|
|
134
137
|
assertKnownKeys(item,new Set(['id','level','text']),`Document heading ${index+1}`);
|
|
@@ -153,7 +156,7 @@ function normalizeDocument(input,schema,index,{stored=false}={}){
|
|
|
153
156
|
const id=normalizedText(input[fields.id],`Document ${index+1} id`);
|
|
154
157
|
if(!IDENTIFIER.test(id)) fail(`Document ${index+1} id is invalid.`);
|
|
155
158
|
const body=input[fields.body];
|
|
156
|
-
if(
|
|
159
|
+
if(!is.string(body)) fail(`Document ${id} body must be a string.`);
|
|
157
160
|
const mediaType=normalizedText(input[fields.mediaType]??'text/markdown',`Document ${id} mediaType`);
|
|
158
161
|
if(!['text/markdown','text/plain'].includes(mediaType)) fail(`Document ${id} mediaType is unsupported.`);
|
|
159
162
|
const kind=normalizedText(input[fields.kind]??'document',`Document ${id} kind`).toLowerCase();
|
|
@@ -213,7 +216,7 @@ function manifestKey(schema){
|
|
|
213
216
|
|
|
214
217
|
function generationId(){
|
|
215
218
|
const value=globalThis.crypto?.randomUUID?.();
|
|
216
|
-
if(
|
|
219
|
+
if(is.string(value)&&value)return value;
|
|
217
220
|
generationSequence+=1;
|
|
218
221
|
return `generation-${Date.now().toString(36)}-${generationSequence.toString(36)}`;
|
|
219
222
|
}
|
|
@@ -248,7 +251,7 @@ function readFailureError(message,errors,failures){
|
|
|
248
251
|
function sourceFailureKey(file,index,schema){
|
|
249
252
|
for(const field of ['id','sourcePath','path']){
|
|
250
253
|
const value=file?.[schema.fields[field]];
|
|
251
|
-
if(
|
|
254
|
+
if(is.string(value)&&value.trim()) return normalizedFailureText(value,`source:${index+1}`);
|
|
252
255
|
}
|
|
253
256
|
return `source:${index+1}`;
|
|
254
257
|
}
|
|
@@ -258,11 +261,11 @@ function normalizeReadCoverage(input,count){
|
|
|
258
261
|
if(
|
|
259
262
|
!isPlainRecord(input)
|
|
260
263
|
||Object.keys(input).some(key=>!['errors','failures','readable','total'].includes(key))
|
|
261
|
-
||!
|
|
264
|
+
||!is.array(input.failures)
|
|
262
265
|
||Object.keys(input.failures).length!==input.failures.length
|
|
263
|
-
||!
|
|
264
|
-
||!
|
|
265
|
-
||!
|
|
266
|
+
||!is.safeInteger(input.errors)
|
|
267
|
+
||!is.safeInteger(input.readable)
|
|
268
|
+
||!is.safeInteger(input.total)
|
|
266
269
|
) fail('Stored document read coverage is invalid.','DBOPFS_DOCUMENT_INCOMPLETE');
|
|
267
270
|
const failures=input.failures.map((item,index)=>{
|
|
268
271
|
if(!isPlainRecord(item)||item.phase!=='source-read'
|
|
@@ -416,7 +419,7 @@ async function readEvaluationSources(sources,options){
|
|
|
416
419
|
body=await read(descriptor.source,{
|
|
417
420
|
ordinal:descriptor.ordinal,signal:signal??null
|
|
418
421
|
});
|
|
419
|
-
if(
|
|
422
|
+
if(!is.string(body)) fail('read must resolve to document text.');
|
|
420
423
|
}catch(error){return {error};}
|
|
421
424
|
return {body,record:{...descriptor.record,body}};
|
|
422
425
|
}));
|
|
@@ -478,7 +481,7 @@ class DBOPFSDocumentLibrary{
|
|
|
478
481
|
'concurrency','db','maxCorpusCharacters','maxDocumentCharacters','maxSearchCharacters','schema'
|
|
479
482
|
]),'DBOPFS document library options');
|
|
480
483
|
const db=options.db??globalThis.dbopfs;
|
|
481
|
-
if(!db
|
|
484
|
+
if(!db||!is.function(db.get)||!is.function(db.set)||!is.function(db.getAllKeys)||!is.function(db.delete)){
|
|
482
485
|
fail('A DBOPFS-compatible db with get, set, getAllKeys, and delete is required.','DBOPFS_DOCUMENT_STORAGE_UNAVAILABLE');
|
|
483
486
|
}
|
|
484
487
|
this.#db=db;
|
|
@@ -511,9 +514,9 @@ class DBOPFSDocumentLibrary{
|
|
|
511
514
|
new Set(['files','onProgress','read','readFailurePolicy','signal']),
|
|
512
515
|
'Document bootstrap options',
|
|
513
516
|
);
|
|
514
|
-
if(!
|
|
515
|
-
if(options.onProgress!==undefined
|
|
516
|
-
if(options.read!==undefined
|
|
517
|
+
if(!is.array(options.files)) fail('Document bootstrap files must be an array.');
|
|
518
|
+
if(options.onProgress!==undefined&&!is.function(options.onProgress)) fail('onProgress must be a function.');
|
|
519
|
+
if(options.read!==undefined&&!is.function(options.read)) fail('read must be a function.');
|
|
517
520
|
const readFailurePolicy=options.readFailurePolicy??'preserve-readable';
|
|
518
521
|
if(!READ_FAILURE_POLICIES.has(readFailurePolicy)){
|
|
519
522
|
fail('readFailurePolicy must be "reject" or "preserve-readable".');
|
|
@@ -537,9 +540,9 @@ class DBOPFSDocumentLibrary{
|
|
|
537
540
|
this.#concurrency,
|
|
538
541
|
options.signal,
|
|
539
542
|
async file=>{
|
|
540
|
-
if(
|
|
543
|
+
if(is.string(file?.[this.#schema.fields.body])) return file;
|
|
541
544
|
const body=await options.read({...file},{signal:options.signal??null});
|
|
542
|
-
if(
|
|
545
|
+
if(!is.string(body)) fail('read must resolve to document text.');
|
|
543
546
|
return {...file,[this.#schema.fields.body]:body};
|
|
544
547
|
},
|
|
545
548
|
(_result,file)=>reportProgress(options.onProgress,{
|
|
@@ -689,9 +692,9 @@ class DBOPFSDocumentLibrary{
|
|
|
689
692
|
||manifest.schemaId!==this.#schema.id
|
|
690
693
|
||manifest.table!==this.#schema.table
|
|
691
694
|
||manifest.schemaVersion!==this.#schema.version
|
|
692
|
-
|
|
695
|
+
||!is.string(manifest.generation)
|
|
693
696
|
||!manifest.generation
|
|
694
|
-
||!
|
|
697
|
+
||!is.array(manifest.keys)
|
|
695
698
|
) fail('The DBOPFS document corpus has not completed bootstrap.','DBOPFS_DOCUMENT_NOT_BOOTSTRAPPED');
|
|
696
699
|
const readCoverage=normalizeReadCoverage(manifest.readCoverage,manifest.keys.length);
|
|
697
700
|
if((manifest.completed===PARTIAL_COMPLETION)!==(readCoverage.errors>0)){
|
|
@@ -700,7 +703,7 @@ class DBOPFSDocumentLibrary{
|
|
|
700
703
|
const keys=[...manifest.keys];
|
|
701
704
|
if(
|
|
702
705
|
new Set(keys).size!==keys.length
|
|
703
|
-
||keys.some(key
|
|
706
|
+
||keys.some(key=>!is.string(key)||!key)
|
|
704
707
|
) fail('The DBOPFS document corpus differs from its completion manifest.','DBOPFS_DOCUMENT_INCOMPLETE');
|
|
705
708
|
const settled=await boundedMap(
|
|
706
709
|
keys,
|
|
@@ -776,7 +779,7 @@ class DBOPFSDocumentLibrary{
|
|
|
776
779
|
'maxScoringCharacters','onProgress','read','readFailurePolicy','signal','sources','tags'
|
|
777
780
|
]),'Document evaluation options');
|
|
778
781
|
if(!signalLike(options.signal)) fail('signal must be an AbortSignal.');
|
|
779
|
-
if(options.onProgress!==undefined
|
|
782
|
+
if(options.onProgress!==undefined&&!is.function(options.onProgress)) fail('onProgress must be a function.');
|
|
780
783
|
throwIfAborted(options.signal);
|
|
781
784
|
new DocumentLexicalSearch([]).rank(query,{
|
|
782
785
|
kinds:options.kinds,
|
|
@@ -784,8 +787,8 @@ class DBOPFSDocumentLibrary{
|
|
|
784
787
|
});
|
|
785
788
|
const filters=normalizedEvaluationFilters(options.kinds,options.tags);
|
|
786
789
|
|
|
787
|
-
if(!
|
|
788
|
-
if(
|
|
790
|
+
if(!is.array(options.sources)) fail('Document evaluation sources must be an array.');
|
|
791
|
+
if(!is.function(options.read)) fail('Source evaluation requires a read function.');
|
|
789
792
|
const readFailurePolicy=options.readFailurePolicy??'preserve-readable';
|
|
790
793
|
if(!READ_FAILURE_POLICIES.has(readFailurePolicy)){
|
|
791
794
|
fail('readFailurePolicy must be "reject" or "preserve-readable".');
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import Is from 'strong-type';
|
|
2
|
+
const is=new Is(false);
|
|
3
|
+
|
|
1
4
|
function workspaceRoot(value){
|
|
2
5
|
const root=String(value??'').trim();
|
|
3
6
|
if(!root||/[\u0000-\u001f]/.test(root)){
|
|
@@ -44,7 +47,7 @@ export default class DevelopmentWorkspace{
|
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
require(method){
|
|
47
|
-
if(!this.available
|
|
50
|
+
if(!this.available||!is.function(this.api?.[method])){
|
|
48
51
|
throw new Error('The Arcane development-workspace capability is unavailable. Open this application through an installed Arcane OS developer build.');
|
|
49
52
|
}
|
|
50
53
|
return this.api[method].bind(this.api);
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import Is from 'strong-type';
|
|
2
|
+
const is=new Is(false);
|
|
3
|
+
|
|
1
4
|
function isRecord(value){
|
|
2
5
|
return Boolean(value)
|
|
3
|
-
&&
|
|
4
|
-
&&!
|
|
6
|
+
&&is.object(value)
|
|
7
|
+
&&!is.array(value);
|
|
5
8
|
}
|
|
6
9
|
|
|
7
10
|
function coded(error,code){
|
|
@@ -11,7 +14,7 @@ function coded(error,code){
|
|
|
11
14
|
|
|
12
15
|
function optionalText(value,label){
|
|
13
16
|
if(value===undefined||value===null) return value;
|
|
14
|
-
if(
|
|
17
|
+
if(!is.string(value)) throw new TypeError(`${label} must be a string when provided.`);
|
|
15
18
|
return value;
|
|
16
19
|
}
|
|
17
20
|
|
|
@@ -30,7 +33,7 @@ function normalizeDirectoryPickerOptions(input={}){
|
|
|
30
33
|
function normalizeDirectorySelection(input){
|
|
31
34
|
if(
|
|
32
35
|
!isRecord(input)
|
|
33
|
-
|
|
36
|
+
||!is.boolean(input.cancelled)
|
|
34
37
|
){
|
|
35
38
|
throw coded(
|
|
36
39
|
new TypeError('The directory picker provider returned an invalid result.'),
|
|
@@ -73,7 +76,7 @@ export default class DirectoryPicker{
|
|
|
73
76
|
}
|
|
74
77
|
|
|
75
78
|
get available(){
|
|
76
|
-
return
|
|
79
|
+
return is.function(this.provider?.selectDirectory);
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
async select(options={}){
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import Is from 'strong-type';
|
|
2
|
+
const is=new Is(false);
|
|
3
|
+
|
|
1
4
|
const DOCUMENT_SEARCH_FIELD_ORDER=[
|
|
2
5
|
'title','searchTerms','tags','headings','summary','category','navigationGroup',
|
|
3
6
|
'navigationParent','audiences','platforms','sourcePath','path','language','id'
|
|
@@ -17,8 +20,8 @@ function fail(message,code='DOCUMENT_SEARCH_INVALID'){
|
|
|
17
20
|
|
|
18
21
|
function isPlainRecord(value){
|
|
19
22
|
return Boolean(value)
|
|
20
|
-
&&
|
|
21
|
-
&&!
|
|
23
|
+
&&is.object(value)
|
|
24
|
+
&&!is.array(value)
|
|
22
25
|
&&Object.getPrototypeOf(value)===Object.prototype;
|
|
23
26
|
}
|
|
24
27
|
|
|
@@ -32,7 +35,7 @@ function documentSearchTokens(value){
|
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
function list(value,mapper=normalizedDocumentSearchText){
|
|
35
|
-
return
|
|
38
|
+
return is.array(value)?value.map(mapper):[];
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
function createDocumentLexicalIndex(record){
|
|
@@ -125,7 +128,7 @@ function compareText(left,right){
|
|
|
125
128
|
}
|
|
126
129
|
|
|
127
130
|
function normalizeQuery(value){
|
|
128
|
-
if(
|
|
131
|
+
if(!is.string(value)) fail('Search query must be a string.','DOCUMENT_SEARCH_INVALID_QUERY');
|
|
129
132
|
const query=value.trim();
|
|
130
133
|
if(CONTROL_CHARACTERS.test(query)){
|
|
131
134
|
fail('Search query must be plain text.','DOCUMENT_SEARCH_INVALID_QUERY');
|
|
@@ -135,9 +138,9 @@ function normalizeQuery(value){
|
|
|
135
138
|
|
|
136
139
|
function normalizeFilter(value,label){
|
|
137
140
|
if(value===undefined) return null;
|
|
138
|
-
if(!
|
|
141
|
+
if(!is.array(value)) fail(`${label} must be an array.`,'DOCUMENT_SEARCH_INVALID_QUERY');
|
|
139
142
|
return new Set(value.map((item,index)=>{
|
|
140
|
-
if(
|
|
143
|
+
if(!is.string(item)||!item.trim()){
|
|
141
144
|
fail(`${label} entry ${index+1} must contain text.`,'DOCUMENT_SEARCH_INVALID_QUERY');
|
|
142
145
|
}
|
|
143
146
|
return canonicalKey(item.trim());
|
|
@@ -152,7 +155,7 @@ function lineNumberAt(value,offset){
|
|
|
152
155
|
}
|
|
153
156
|
|
|
154
157
|
function documentContextExcerpt(value){
|
|
155
|
-
if(
|
|
158
|
+
if(!is.string(value)) fail('Document context must be text.');
|
|
156
159
|
return {
|
|
157
160
|
lineEnd:lineNumberAt(value,Math.max(0,value.length-1)),
|
|
158
161
|
lineStart:1,
|
|
@@ -165,7 +168,7 @@ class DocumentLexicalSearch{
|
|
|
165
168
|
#records;
|
|
166
169
|
|
|
167
170
|
constructor(records){
|
|
168
|
-
if(!
|
|
171
|
+
if(!is.array(records)) fail('Document search records must be an array.');
|
|
169
172
|
this.#records=[...records];
|
|
170
173
|
this.#indexes=new Map(this.#records.map(record=>[record.id,createDocumentLexicalIndex(record)]));
|
|
171
174
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import Is from 'strong-type';
|
|
2
|
+
const is=new Is(false);
|
|
3
|
+
|
|
1
4
|
const documentNavigationBindings=new WeakMap();
|
|
2
5
|
const documentNavigationForms=new WeakSet();
|
|
3
6
|
|
|
@@ -41,7 +44,7 @@ function nearestDocumentNavigationDetails(group){
|
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
function documentNavigationDetailsIsOpen(details){
|
|
44
|
-
return
|
|
47
|
+
return is.boolean(details.open)
|
|
45
48
|
?details.open
|
|
46
49
|
:details.hasAttribute('open');
|
|
47
50
|
}
|
|
@@ -113,8 +116,8 @@ function revealCurrentDocumentNavigationItem(binding){
|
|
|
113
116
|
if(
|
|
114
117
|
!currentItem
|
|
115
118
|
||currentItem.hidden
|
|
116
|
-
|
|
117
|
-
|
|
119
|
+
||!is.function(currentItem.getBoundingClientRect)
|
|
120
|
+
||!is.function(binding.navigation.getBoundingClientRect)
|
|
118
121
|
)return false;
|
|
119
122
|
|
|
120
123
|
const navigationBounds=binding.navigation.getBoundingClientRect();
|
|
@@ -204,7 +207,7 @@ function autoInitializeDocumentNavigation(){
|
|
|
204
207
|
initializeDocumentNavigation(globalThis.document);
|
|
205
208
|
}
|
|
206
209
|
|
|
207
|
-
if(
|
|
210
|
+
if(!is.undefined(globalThis.document)){
|
|
208
211
|
if(globalThis.document.readyState==='loading'){
|
|
209
212
|
globalThis.document.addEventListener(
|
|
210
213
|
'DOMContentLoaded',
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import Is from 'strong-type';
|
|
2
|
+
const is=new Is(false);
|
|
3
|
+
|
|
1
4
|
import waitForComponent from './WaitForComponent.js';
|
|
2
5
|
import { arcaneLogging,readArcaneDeveloperMode } from 'arcane-os/logging';
|
|
3
6
|
import {
|
|
@@ -22,7 +25,7 @@ const ERROR_REASONS={
|
|
|
22
25
|
unhandledRejectionCaptured:'unhandled-promise-rejection-captured'
|
|
23
26
|
};
|
|
24
27
|
const RUNTIME_OCCURRENCE_PREFIX=(
|
|
25
|
-
|
|
28
|
+
is.function(globalThis.crypto?.randomUUID)
|
|
26
29
|
? globalThis.crypto.randomUUID()
|
|
27
30
|
: `${Date.now().toString(36)}-${Math.random().toString(36).replace(/^0\./,'')}`
|
|
28
31
|
);
|
|
@@ -43,7 +46,7 @@ function safeText(value,fallback=''){
|
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
try{
|
|
46
|
-
const text=
|
|
49
|
+
const text=is.string(value) ? value:String(value);
|
|
47
50
|
return text||fallback;
|
|
48
51
|
}catch{
|
|
49
52
|
return fallback;
|
|
@@ -52,7 +55,7 @@ function safeText(value,fallback=''){
|
|
|
52
55
|
|
|
53
56
|
function safeNumber(value){
|
|
54
57
|
const number=Number(value);
|
|
55
|
-
return
|
|
58
|
+
return is.finite(number) ? number:null;
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
function safeIso(timestamp){
|
|
@@ -111,7 +114,7 @@ export function normalizeErrorEvent(event={},target=globalThis.window){
|
|
|
111
114
|
export function normalizeRejectionEvent(event={},target=globalThis.window){
|
|
112
115
|
const reason=event?.reason;
|
|
113
116
|
const reasonIsObject=reason!==null
|
|
114
|
-
&& (
|
|
117
|
+
&& (is.object(reason)||is.function(reason));
|
|
115
118
|
|
|
116
119
|
return {
|
|
117
120
|
type:'unhandledrejection',
|
|
@@ -144,11 +147,11 @@ function defaultStorage(target){
|
|
|
144
147
|
}
|
|
145
148
|
|
|
146
149
|
async function sendWithWindowMail(target,...args){
|
|
147
|
-
if(
|
|
150
|
+
if(!is.function(target?.mail?.send)){
|
|
148
151
|
await import('./Mail.js');
|
|
149
152
|
}
|
|
150
153
|
|
|
151
|
-
if(
|
|
154
|
+
if(!is.function(target?.mail?.send)){
|
|
152
155
|
throw new Error('Mail notification service is unavailable');
|
|
153
156
|
}
|
|
154
157
|
|
|
@@ -178,8 +181,8 @@ function buildDeveloperIncidentContent(document,incident,occurrenceId){
|
|
|
178
181
|
const details=document.createElement('dl');
|
|
179
182
|
const source=[
|
|
180
183
|
safeText(incident?.filename),
|
|
181
|
-
|
|
182
|
-
|
|
184
|
+
is.finite(incident?.lineno) ? incident.lineno:'',
|
|
185
|
+
is.finite(incident?.colno) ? incident.colno:'',
|
|
183
186
|
].filter(value => value!=='').join(':');
|
|
184
187
|
|
|
185
188
|
content.className='developer-error-content';
|
|
@@ -262,7 +265,7 @@ async function presentDeveloperIncidentModal(target,incident,occurrenceId){
|
|
|
262
265
|
};
|
|
263
266
|
const onPageHide=() => {
|
|
264
267
|
try{
|
|
265
|
-
if(
|
|
268
|
+
if(is.function(modal.close)){
|
|
266
269
|
modal.close(undefined,true);
|
|
267
270
|
}else{
|
|
268
271
|
modal.remove();
|
|
@@ -308,7 +311,7 @@ class Errors {
|
|
|
308
311
|
|
|
309
312
|
constructor(options={}) {
|
|
310
313
|
const target=options.target||globalThis.window;
|
|
311
|
-
if(!target
|
|
314
|
+
if(!target||!is.function(target.addEventListener)){
|
|
312
315
|
throw new TypeError('Errors requires an event target');
|
|
313
316
|
}
|
|
314
317
|
|
|
@@ -334,15 +337,15 @@ class Errors {
|
|
|
334
337
|
? defaultStorage(target)
|
|
335
338
|
: options.storage;
|
|
336
339
|
this.storageHealthy=(
|
|
337
|
-
|
|
338
|
-
&&
|
|
340
|
+
is.function(this.storage?.getItem)
|
|
341
|
+
&& is.function(this.storage?.setItem)
|
|
339
342
|
);
|
|
340
343
|
this.sendMail=options.sendMail
|
|
341
344
|
|| sendWithWindowMail.bind(null,target);
|
|
342
|
-
this.isDeveloperMode=
|
|
345
|
+
this.isDeveloperMode=is.function(options.isDeveloperMode)
|
|
343
346
|
? options.isDeveloperMode
|
|
344
347
|
: readArcaneDeveloperMode.bind(null,target);
|
|
345
|
-
this.presentDeveloperIncident=
|
|
348
|
+
this.presentDeveloperIncident=is.function(options.presentDeveloperIncident)
|
|
346
349
|
? options.presentDeveloperIncident
|
|
347
350
|
: presentDeveloperIncidentModal.bind(null,target);
|
|
348
351
|
|
|
@@ -397,12 +400,12 @@ class Errors {
|
|
|
397
400
|
|
|
398
401
|
try{
|
|
399
402
|
const value=JSON.parse(this.storage.getItem(LEDGER_STORAGE_KEY));
|
|
400
|
-
if(!value
|
|
403
|
+
if(!value||!is.object(value)){
|
|
401
404
|
return empty;
|
|
402
405
|
}
|
|
403
406
|
|
|
404
407
|
return {
|
|
405
|
-
pending:
|
|
408
|
+
pending:is.array(value.pending)
|
|
406
409
|
? value.pending
|
|
407
410
|
: []
|
|
408
411
|
};
|
|
@@ -470,7 +473,7 @@ class Errors {
|
|
|
470
473
|
}
|
|
471
474
|
|
|
472
475
|
restorePending(records){
|
|
473
|
-
if(!
|
|
476
|
+
if(!is.array(records)){
|
|
474
477
|
return;
|
|
475
478
|
}
|
|
476
479
|
|
|
@@ -478,23 +481,23 @@ class Errors {
|
|
|
478
481
|
for(const storedRecord of records){
|
|
479
482
|
if(
|
|
480
483
|
!storedRecord
|
|
481
|
-
||
|
|
484
|
+
|| !is.object(storedRecord)
|
|
482
485
|
|| !storedRecord.incident
|
|
483
|
-
||
|
|
486
|
+
|| !is.object(storedRecord.incident)
|
|
484
487
|
){
|
|
485
488
|
this.warn('A persisted error delivery could not be restored.');
|
|
486
489
|
continue;
|
|
487
490
|
}
|
|
488
491
|
|
|
489
|
-
const capturedAt=
|
|
492
|
+
const capturedAt=is.finite(storedRecord.capturedAt)
|
|
490
493
|
? storedRecord.capturedAt
|
|
491
|
-
:
|
|
494
|
+
: is.finite(storedRecord.firstSeen)
|
|
492
495
|
? storedRecord.firstSeen
|
|
493
496
|
: timestamp;
|
|
494
|
-
const dueAt=
|
|
497
|
+
const dueAt=is.finite(storedRecord.dueAt)
|
|
495
498
|
? storedRecord.dueAt:capturedAt+this.delayMs;
|
|
496
499
|
let occurrenceId=(
|
|
497
|
-
|
|
500
|
+
is.string(storedRecord.occurrenceId)
|
|
498
501
|
&& storedRecord.occurrenceId.trim()
|
|
499
502
|
)
|
|
500
503
|
? storedRecord.occurrenceId
|
|
@@ -777,7 +780,7 @@ class Errors {
|
|
|
777
780
|
const modal=this.target.document?.querySelector?.(
|
|
778
781
|
'html-import[data-global-error-modal]'
|
|
779
782
|
);
|
|
780
|
-
if(
|
|
783
|
+
if(is.function(modal?.close)){
|
|
781
784
|
modal.close(undefined,true);
|
|
782
785
|
}else{
|
|
783
786
|
modal?.remove?.();
|
|
@@ -812,7 +815,7 @@ class Errors {
|
|
|
812
815
|
}
|
|
813
816
|
}
|
|
814
817
|
|
|
815
|
-
if(
|
|
818
|
+
if(!is.undefined(globalThis.window)&&window.errors?.[HANDLER_MARKER]!==true){
|
|
816
819
|
new Errors();
|
|
817
820
|
}
|
|
818
821
|
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import Is from 'strong-type';
|
|
2
|
+
const is=new Is(false);
|
|
3
|
+
|
|
1
4
|
import { arcaneLogging } from 'arcane-os/logging';
|
|
2
5
|
import {
|
|
3
6
|
createArcaneEventSource,
|
|
@@ -17,7 +20,7 @@ const htmlImportModuleURL=new URL(import.meta.url);
|
|
|
17
20
|
const htmlImportAssetVersion=htmlImportModuleURL.searchParams.get('arcaneVersion');
|
|
18
21
|
|
|
19
22
|
function versionComponentResource(value,baseHref){
|
|
20
|
-
if(!htmlImportAssetVersion
|
|
23
|
+
if(!htmlImportAssetVersion||!is.string(value)||!value||value.startsWith('#')){
|
|
21
24
|
return value;
|
|
22
25
|
}
|
|
23
26
|
let resolvedURL;
|
|
@@ -64,7 +67,7 @@ function componentRuntimeRoot(resolvedHref){
|
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
function resolveComponentResource(value,runtimeRoot){
|
|
67
|
-
if(!runtimeRoot
|
|
70
|
+
if(!runtimeRoot||!is.string(value)||!value.startsWith('./arcane/')){
|
|
68
71
|
return value;
|
|
69
72
|
}
|
|
70
73
|
return new URL(value.slice('./arcane/'.length),runtimeRoot).href;
|
|
@@ -509,7 +512,7 @@ class HTMLImport extends HTMLElement {
|
|
|
509
512
|
htmlImportHostRegistry.set(hostToken,binding);
|
|
510
513
|
try{
|
|
511
514
|
document.head.appendChild(executable);
|
|
512
|
-
if(!binding.promise
|
|
515
|
+
if(!binding.promise||!is.function(binding.promise.then)){
|
|
513
516
|
throw new Error('The HTML import script did not start.');
|
|
514
517
|
}
|
|
515
518
|
await binding.promise;
|
|
@@ -522,7 +525,7 @@ class HTMLImport extends HTMLElement {
|
|
|
522
525
|
}finally{
|
|
523
526
|
const installedDescriptor=Object.getOwnPropertyDescriptor(this,'destroy')??null;
|
|
524
527
|
const installedDestroy=this.destroy;
|
|
525
|
-
if(
|
|
528
|
+
if(is.function(installedDestroy)
|
|
526
529
|
&&installedDestroy!==previousDestroy
|
|
527
530
|
&&!samePropertyDescriptor(installedDescriptor,previousDescriptor)){
|
|
528
531
|
this.#importedDestroy={
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import Is from 'strong-type';
|
|
2
|
+
const is=new Is(false);
|
|
3
|
+
|
|
1
4
|
const SENTENCE_BOUNDARY=/[.!?]+(?:["'\\u2019\\u201d)\\]}]+)?(?=\\s|$)/gu;
|
|
2
5
|
const WORD_OR_NUMBER=/[\\p{L}\\p{N}]/u;
|
|
3
6
|
|
|
@@ -9,12 +12,12 @@ function codedError(code,message,ErrorType=Error){
|
|
|
9
12
|
|
|
10
13
|
function isPlainRecord(value){
|
|
11
14
|
return Boolean(value)
|
|
12
|
-
&&
|
|
13
|
-
&&!
|
|
15
|
+
&&is.object(value)
|
|
16
|
+
&&!is.array(value);
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
function countSentences(value){
|
|
17
|
-
if(
|
|
20
|
+
if(!is.string(value)){
|
|
18
21
|
throw new TypeError('Sentence counting requires a string.');
|
|
19
22
|
}
|
|
20
23
|
if(!value.trim()){
|
|
@@ -36,8 +39,8 @@ function countSentences(value){
|
|
|
36
39
|
|
|
37
40
|
function requireLocalAI(localAI){
|
|
38
41
|
if(!localAI
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
||!is.function(localAI.inspectIsolatedModel)
|
|
43
|
+
||!is.function(localAI.runIsolatedQuestion)){
|
|
41
44
|
throw codedError(
|
|
42
45
|
'ARCANE_ISOLATED_MODEL_API_UNAVAILABLE',
|
|
43
46
|
'The Arcane isolated-model API is unavailable. Open this application through a compatible Arcane OS host.'
|
|
@@ -52,14 +55,14 @@ class IsolatedModelQuestionRunner{
|
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
async inspectModel(model,expectedModel,contextTokens){
|
|
55
|
-
if(
|
|
58
|
+
if(!is.string(model)||!model.trim()){
|
|
56
59
|
throw codedError(
|
|
57
60
|
'INVALID_ISOLATED_MODEL_RUNNER_REQUEST',
|
|
58
61
|
'The isolated-model inspection requires a model.',
|
|
59
62
|
TypeError
|
|
60
63
|
);
|
|
61
64
|
}
|
|
62
|
-
if(contextTokens!==undefined&&(!
|
|
65
|
+
if(contextTokens!==undefined&&(!is.safeInteger(contextTokens)||contextTokens<1)){
|
|
63
66
|
throw codedError(
|
|
64
67
|
'INVALID_ISOLATED_MODEL_RUNNER_REQUEST',
|
|
65
68
|
'The isolated-model inspection context token value must be positive when provided.',
|
|
@@ -81,12 +84,12 @@ class IsolatedModelQuestionRunner{
|
|
|
81
84
|
);
|
|
82
85
|
}
|
|
83
86
|
const {onPhase,...request}=input;
|
|
84
|
-
if(
|
|
87
|
+
if(!is.string(request.model)
|
|
85
88
|
||!request.model.trim()
|
|
86
|
-
|
|
87
|
-
||(Object.hasOwn(request,'systemPrompt')
|
|
89
|
+
||!is.string(request.prompt)
|
|
90
|
+
||(Object.hasOwn(request,'systemPrompt')&&!is.string(request.systemPrompt))
|
|
88
91
|
||(Object.hasOwn(request,'options')&&!isPlainRecord(request.options))
|
|
89
|
-
||(onPhase!==undefined
|
|
92
|
+
||(onPhase!==undefined&&!is.function(onPhase))){
|
|
90
93
|
throw codedError(
|
|
91
94
|
'INVALID_ISOLATED_MODEL_RUNNER_REQUEST',
|
|
92
95
|
'The isolated-model question request contains invalid values.',
|
|
@@ -95,7 +98,7 @@ class IsolatedModelQuestionRunner{
|
|
|
95
98
|
}
|
|
96
99
|
const streamOptions=onPhase===undefined?{}:{onPhase};
|
|
97
100
|
const result=await this.localAI.runIsolatedQuestion(request,streamOptions);
|
|
98
|
-
if(!isPlainRecord(result)
|
|
101
|
+
if(!isPlainRecord(result)||!is.string(result.answer)){
|
|
99
102
|
throw codedError(
|
|
100
103
|
'ARCANE_ISOLATED_MODEL_RESPONSE_INVALID',
|
|
101
104
|
'Arcane Core returned an invalid isolated-model response.'
|