arcane-os 0.1.0-dev.5
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 +154 -0
- package/COMMERCIAL-LICENSE.md +13 -0
- package/LICENSE +661 -0
- package/NOTICE +70 -0
- package/README.md +448 -0
- package/bin/arcane-test.mjs +741 -0
- package/bin/arcane.mjs +5 -0
- package/docs/architecture.md +234 -0
- package/docs/compatibility.md +36 -0
- package/docs/event-manager.md +166 -0
- package/docs/platform-targets.md +108 -0
- package/docs/publishing.md +203 -0
- package/docs/reference/README.md +117 -0
- package/docs/reference/arcane-ollama.md +288 -0
- package/docs/reference/availability-and-normalization.md +123 -0
- package/docs/reference/behavioral-testing.md +86 -0
- package/docs/reference/cli.md +569 -0
- package/docs/reference/core/README.md +62 -0
- package/docs/reference/core/arcane-ai-contracts.md +873 -0
- package/docs/reference/core/arcane-api.md +601 -0
- package/docs/reference/core/arcane-entities.md +65 -0
- package/docs/reference/core/arcane-events.md +134 -0
- package/docs/reference/core/ollama-module.md +181 -0
- package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +1909 -0
- package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +1057 -0
- package/docs/reference/core/reference/arcane-api/core-and-events.md +320 -0
- package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +610 -0
- package/docs/reference/core/reference/arcane-api/namespaces.md +1157 -0
- package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +1423 -0
- package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +315 -0
- package/docs/reference/event-manager.md +957 -0
- package/docs/reference/inventory/package-api.json +2632 -0
- package/docs/reference/inventory/runtime-components.json +934 -0
- package/docs/reference/inventory/runtime-entities.json +26 -0
- package/docs/reference/inventory/runtime-modules.json +1249 -0
- package/docs/reference/protocols.md +242 -0
- package/docs/reference/runtime-components.md +1098 -0
- package/docs/reference/runtime-entities.md +303 -0
- package/docs/reference/runtime-modules.md +2010 -0
- package/docs/reference/sdk-api.md +4901 -0
- package/docs/roadmap.md +79 -0
- package/docs/work-amplification.md +124 -0
- package/node_modules/event-pubsub/CHANGELOG.md +55 -0
- package/node_modules/event-pubsub/MIGRATION.md +70 -0
- package/node_modules/event-pubsub/README.md +363 -0
- package/node_modules/event-pubsub/SECURITY.md +37 -0
- package/node_modules/event-pubsub/index.js +141 -0
- package/node_modules/event-pubsub/licence +21 -0
- package/node_modules/event-pubsub/package.json +59 -0
- package/node_modules/strong-type/README.md +408 -0
- package/node_modules/strong-type/assets/strong-type-header.png +0 -0
- package/node_modules/strong-type/index.js +1151 -0
- package/node_modules/strong-type/licence +21 -0
- package/node_modules/strong-type/node.js +125 -0
- package/node_modules/strong-type/package.json +61 -0
- package/package.json +95 -0
- package/runtime/ARCANE_RUNTIME_RELEASE.json +791 -0
- package/runtime/arcane/components/app-bar.html +468 -0
- package/runtime/arcane/components/assistant-panel.html +715 -0
- package/runtime/arcane/components/calculator.html +8 -0
- package/runtime/arcane/components/chart.html +655 -0
- package/runtime/arcane/components/chat.html +1225 -0
- package/runtime/arcane/components/conversation-view.html +13 -0
- package/runtime/arcane/components/dashboard-config.html +341 -0
- package/runtime/arcane/components/data-maintenance.html +112 -0
- package/runtime/arcane/components/data-view.html +92 -0
- package/runtime/arcane/components/directory-picker.html +197 -0
- package/runtime/arcane/components/document-inspector.html +252 -0
- package/runtime/arcane/components/file-drop.html +264 -0
- package/runtime/arcane/components/file-inspector.html +293 -0
- package/runtime/arcane/components/file-manager.html +1715 -0
- package/runtime/arcane/components/header.html +142 -0
- package/runtime/arcane/components/integration-settings.html +14 -0
- package/runtime/arcane/components/local-ai-status.html +360 -0
- package/runtime/arcane/components/markdown-document.html +1048 -0
- package/runtime/arcane/components/markdown-editor.html +360 -0
- package/runtime/arcane/components/media-embed.html +8 -0
- package/runtime/arcane/components/modal.html +402 -0
- package/runtime/arcane/components/output-panel.html +259 -0
- package/runtime/arcane/components/preferences-form.html +135 -0
- package/runtime/arcane/components/record-timeline.html +105 -0
- package/runtime/arcane/components/relationship-board.html +116 -0
- package/runtime/arcane/components/screen-capture.html +8 -0
- package/runtime/arcane/components/source-code-viewer.html +441 -0
- package/runtime/arcane/components/source-explanation.html +124 -0
- package/runtime/arcane/components/speech.html +365 -0
- package/runtime/arcane/components/summary-strip.html +177 -0
- package/runtime/arcane/components/table.html +77 -0
- package/runtime/arcane/components/task-progress.html +282 -0
- package/runtime/arcane/components/terminal-workspace.html +65 -0
- package/runtime/arcane/components/theme-editor.html +41 -0
- package/runtime/arcane/components/theme-switcher.html +46 -0
- package/runtime/arcane/components/unified-inbox.html +20 -0
- package/runtime/arcane/components/voice-transcription.html +476 -0
- package/runtime/arcane/components/weather-widget.html +8 -0
- package/runtime/arcane/components/web-navigator.html +239 -0
- package/runtime/arcane/css/communications.css +1 -0
- package/runtime/arcane/css/dashboard-config.css +45 -0
- package/runtime/arcane/css/document-site.css +981 -0
- package/runtime/arcane/css/layout.css +438 -0
- package/runtime/arcane/css/primitives.css +321 -0
- package/runtime/arcane/css/theme.css +112 -0
- package/runtime/arcane/css/utility-workspace.css +1 -0
- package/runtime/arcane/entities/ApiModelRecord.js +20 -0
- package/runtime/arcane/entities/Calculation.js +13 -0
- package/runtime/arcane/entities/Chat.js +581 -0
- package/runtime/arcane/entities/CommunicationMessage.js +29 -0
- package/runtime/arcane/entities/CommunicationThread.js +21 -0
- package/runtime/arcane/entities/Document.js +10 -0
- package/runtime/arcane/entities/File.js +143 -0
- package/runtime/arcane/entities/Image.js +135 -0
- package/runtime/arcane/entities/IntentEnvelope.js +834 -0
- package/runtime/arcane/entities/Preference.js +83 -0
- package/runtime/arcane/entities/TWiNPolicyDecision.js +1092 -0
- package/runtime/arcane/entities/TerminalSession.js +46 -0
- package/runtime/arcane/entities/Theme.js +107 -0
- package/runtime/arcane/entities/User.js +1046 -0
- package/runtime/arcane/entities/Weather.js +23 -0
- package/runtime/arcane/img/arcane-os-everywhere.png +0 -0
- package/runtime/arcane/img/arrow-left.png +0 -0
- package/runtime/arcane/img/arrow-right.png +0 -0
- package/runtime/arcane/img/doc.svg +5 -0
- package/runtime/arcane/img/folder.svg +4 -0
- package/runtime/arcane/img/image.svg +5 -0
- package/runtime/arcane/img/refresh.png +0 -0
- package/runtime/arcane/img/send.svg +9 -0
- package/runtime/arcane/img/trash.svg +5 -0
- package/runtime/arcane/img/upload.svg +5 -0
- package/runtime/arcane/modules/AI.js +2048 -0
- package/runtime/arcane/modules/AIPreferenceRuntime.js +32 -0
- package/runtime/arcane/modules/AIPreferenceTuple.js +92 -0
- package/runtime/arcane/modules/AIResponseLength.js +42 -0
- package/runtime/arcane/modules/AIResponseURLPolicy.js +626 -0
- package/runtime/arcane/modules/AnsiText.js +53 -0
- package/runtime/arcane/modules/ApiModelDatabase.js +25 -0
- package/runtime/arcane/modules/AppDataScope.js +245 -0
- package/runtime/arcane/modules/AppearancePreferences.js +28 -0
- package/runtime/arcane/modules/ArcaneCommunicationBridge.js +22 -0
- package/runtime/arcane/modules/ArcaneNavigationPolicy.js +135 -0
- package/runtime/arcane/modules/ArcaneNetworkPolicy.js +255 -0
- package/runtime/arcane/modules/AsyncBoundary.js +161 -0
- package/runtime/arcane/modules/BrowserTestSuite.js +326 -0
- package/runtime/arcane/modules/CalculatorEngine.js +20 -0
- package/runtime/arcane/modules/CaseEvidenceIndexer.js +134 -0
- package/runtime/arcane/modules/ChartLibrary.js +35 -0
- package/runtime/arcane/modules/ChatRecords.js +13 -0
- package/runtime/arcane/modules/CommunicationAppController.js +43 -0
- package/runtime/arcane/modules/CommunicationHub.js +16 -0
- package/runtime/arcane/modules/CommunicationPreferences.js +13 -0
- package/runtime/arcane/modules/CommunicationProviderRegistry.js +16 -0
- package/runtime/arcane/modules/ComponentContracts.js +586 -0
- package/runtime/arcane/modules/ConfiguredAIChatSession.js +288 -0
- package/runtime/arcane/modules/ConversationActionItems.js +488 -0
- package/runtime/arcane/modules/ConversationClosingReport.js +274 -0
- package/runtime/arcane/modules/ConversationTimebox.js +527 -0
- package/runtime/arcane/modules/CoreLocalModelCatalog.js +255 -0
- package/runtime/arcane/modules/DBLS.js +171 -0
- package/runtime/arcane/modules/DBOPFS.js +1154 -0
- package/runtime/arcane/modules/DBOPFSWorker.js +116 -0
- package/runtime/arcane/modules/DataMaintenance.js +91 -0
- package/runtime/arcane/modules/DevelopmentWorkspace.js +74 -0
- package/runtime/arcane/modules/DirectoryPicker.js +109 -0
- package/runtime/arcane/modules/DocumentNavigation.js +223 -0
- package/runtime/arcane/modules/Errors.js +1025 -0
- package/runtime/arcane/modules/GifEncoder.js +29 -0
- package/runtime/arcane/modules/HTMLImport.js +114 -0
- package/runtime/arcane/modules/InMemoryCommunicationProvider.js +14 -0
- package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +275 -0
- package/runtime/arcane/modules/LocalAIReadiness.js +870 -0
- package/runtime/arcane/modules/LocalAIReadinessController.js +156 -0
- package/runtime/arcane/modules/MD.js +111 -0
- package/runtime/arcane/modules/Mail.js +352 -0
- package/runtime/arcane/modules/MailTransport.mjs +180 -0
- package/runtime/arcane/modules/Marked.min.js +71 -0
- package/runtime/arcane/modules/MemoryRecords.js +44 -0
- package/runtime/arcane/modules/MessageAdvisory.js +38 -0
- package/runtime/arcane/modules/ModelDefinition.js +189 -0
- package/runtime/arcane/modules/Ollama.js +74 -0
- package/runtime/arcane/modules/OllamaModelIdentifier.js +21 -0
- package/runtime/arcane/modules/OllamaSettings.js +24 -0
- package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +14 -0
- package/runtime/arcane/modules/PreferenceStore.js +109 -0
- package/runtime/arcane/modules/QRCode.min.js +1 -0
- package/runtime/arcane/modules/Questionnaire.js +61 -0
- package/runtime/arcane/modules/RecordLinkIndex.js +24 -0
- package/runtime/arcane/modules/RecordPassageIndex.js +222 -0
- package/runtime/arcane/modules/RecordReviewStore.js +94 -0
- package/runtime/arcane/modules/RevocableProjectionLedger.js +1623 -0
- package/runtime/arcane/modules/RiskSignalAnalyzer.js +37 -0
- package/runtime/arcane/modules/ScamRiskPolicy.js +62 -0
- package/runtime/arcane/modules/ScopedOPFSCache.js +183 -0
- package/runtime/arcane/modules/ScreenCapture.js +20 -0
- package/runtime/arcane/modules/SpeechPlayback.js +581 -0
- package/runtime/arcane/modules/StaticDocumentCatalog.js +1248 -0
- package/runtime/arcane/modules/SystemAppearance.js +20 -0
- package/runtime/arcane/modules/SystemPlatformPresentation.js +51 -0
- package/runtime/arcane/modules/SystemToolRegistry.js +28 -0
- package/runtime/arcane/modules/TerminalClient.js +52 -0
- package/runtime/arcane/modules/TerminalCommandRegistry.js +50 -0
- package/runtime/arcane/modules/ThemeBootstrap.js +26 -0
- package/runtime/arcane/modules/ThemeManager.js +131 -0
- package/runtime/arcane/modules/TimeGuard.js +149 -0
- package/runtime/arcane/modules/ToolCallRouter.js +83 -0
- package/runtime/arcane/modules/WaitForComponent.js +102 -0
- package/runtime/arcane/modules/YouTubeMedia.js +16 -0
- package/runtime/arcane/modules/uPlot.LICENSE.txt +21 -0
- package/runtime/arcane/modules/uPlot.iife.min.js +2 -0
- package/runtime/arcane/modules/uPlot.min.css +1 -0
- package/runtime/arcane/security/arcane-network-policy.json +6 -0
- package/runtime/strong-type/index.js +352 -0
- package/runtime/strong-type/licence +21 -0
- package/runtime/strong-type/package.json +45 -0
- package/schemas/arcane-app-bundle.schema.json +125 -0
- package/schemas/arcane-app.schema.json +329 -0
- package/schemas/arcane-lock.schema.json +86 -0
- package/schemas/arcane-package.schema.json +224 -0
- package/schemas/cli-event.schema.json +122 -0
- package/schemas/event-stack.schema.json +152 -0
- package/schemas/native-build-plan.schema.json +176 -0
- package/schemas/target-adapter.schema.json +117 -0
- package/src/app-descriptor.mjs +500 -0
- package/src/cli/main.mjs +561 -0
- package/src/constants.mjs +31 -0
- package/src/dev-server.mjs +718 -0
- package/src/doctor.mjs +315 -0
- package/src/dom-event-instrumentation.mjs +594 -0
- package/src/errors.mjs +75 -0
- package/src/event-manager.mjs +1342 -0
- package/src/event-queue.mjs +138 -0
- package/src/events.mjs +219 -0
- package/src/index.mjs +177 -0
- package/src/integrated-provider-loader.mjs +432 -0
- package/src/native-plan.mjs +698 -0
- package/src/native-provider-loader.mjs +1126 -0
- package/src/packager/core.mjs +2691 -0
- package/src/process.mjs +353 -0
- package/src/release-bundle.mjs +2523 -0
- package/src/repository.mjs +90 -0
- package/src/runtime.mjs +452 -0
- package/src/scaffold.mjs +380 -0
- package/src/targets/index.mjs +436 -0
- package/src/templates/assets/app-icon.png +0 -0
- package/src/templates/workspace-template.mjs +388 -0
- package/src/testing-loader.mjs +9 -0
- package/src/testing.mjs +427 -0
- package/src/toolchain.mjs +1335 -0
- package/src/update-check.mjs +307 -0
- package/src/workspace.mjs +449 -0
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
const own=(value,key)=>Object.prototype.hasOwnProperty.call(value,key);
|
|
2
|
+
|
|
3
|
+
function record(value,label){
|
|
4
|
+
if(value===undefined){
|
|
5
|
+
return {};
|
|
6
|
+
}
|
|
7
|
+
if(!value||typeof value!=='object'||Array.isArray(value)){
|
|
8
|
+
throw new TypeError(`${label} must be an object`);
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function string(value,fallback='',allowEmpty=false){
|
|
14
|
+
if(typeof value!=='string'){
|
|
15
|
+
return fallback;
|
|
16
|
+
}
|
|
17
|
+
const normalized=value.trim();
|
|
18
|
+
return normalized||(allowEmpty?'':fallback);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function text(value,fallback='',allowEmpty=false){
|
|
22
|
+
if(typeof value!=='string'){
|
|
23
|
+
return fallback;
|
|
24
|
+
}
|
|
25
|
+
return value||(allowEmpty?'':fallback);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function option(input,previous,key,fallback){
|
|
29
|
+
return own(input,key)
|
|
30
|
+
?input[key]
|
|
31
|
+
:own(previous,key)
|
|
32
|
+
?previous[key]
|
|
33
|
+
:fallback;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function optionAlias(input,previous,keys,fallback){
|
|
37
|
+
for(const key of keys){
|
|
38
|
+
if(own(input,key)){
|
|
39
|
+
return input[key];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
for(const key of keys){
|
|
43
|
+
if(own(previous,key)){
|
|
44
|
+
return previous[key];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return fallback;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function optionalCallback(input,previous,keys,label=keys[0]){
|
|
51
|
+
const value=optionAlias(input,previous,keys,null);
|
|
52
|
+
if(value!==null&&value!==undefined&&typeof value!=='function'){
|
|
53
|
+
throw new TypeError(`${label} must be a function or null`);
|
|
54
|
+
}
|
|
55
|
+
return typeof value==='function'?value:null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function finiteNumber(value,label){
|
|
59
|
+
if(value===null||value===undefined||value===''){
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const normalized=Number(value);
|
|
63
|
+
if(!Number.isFinite(normalized)){
|
|
64
|
+
throw new TypeError(`${label} must be a finite number or null`);
|
|
65
|
+
}
|
|
66
|
+
return normalized;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function stringRecord(value,defaults,label){
|
|
70
|
+
value=record(value,label);
|
|
71
|
+
const normalized={...defaults};
|
|
72
|
+
for(const [key,item] of Object.entries(value)){
|
|
73
|
+
if(typeof item!=='string'){
|
|
74
|
+
throw new TypeError(`${label}.${key} must be a string`);
|
|
75
|
+
}
|
|
76
|
+
normalized[key]=item;
|
|
77
|
+
}
|
|
78
|
+
return normalized;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const CHART_LABELS=Object.freeze({
|
|
82
|
+
empty:'No data yet.',
|
|
83
|
+
hover:'Point under cursor',
|
|
84
|
+
keyboard:'Keyboard-selected point',
|
|
85
|
+
latest:'Latest recorded point',
|
|
86
|
+
navigation:'Use left and right arrow keys to review every recorded point.',
|
|
87
|
+
noSelection:'No point selected',
|
|
88
|
+
selected:'Selected point',
|
|
89
|
+
time:'Date',
|
|
90
|
+
value:'Value'
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
function normalizeChartOptions(input={},previous={}){
|
|
94
|
+
input=record(input,'Chart options');
|
|
95
|
+
previous=record(previous,'Previous chart options');
|
|
96
|
+
const previousLabels=stringRecord(
|
|
97
|
+
previous.labels,
|
|
98
|
+
CHART_LABELS,
|
|
99
|
+
'Previous chart labels'
|
|
100
|
+
);
|
|
101
|
+
const labels=stringRecord(input.labels,previousLabels,'Chart labels');
|
|
102
|
+
const aliases={
|
|
103
|
+
emptyLabel:'empty',
|
|
104
|
+
hoverLabel:'hover',
|
|
105
|
+
keyboardLabel:'keyboard',
|
|
106
|
+
latestLabel:'latest',
|
|
107
|
+
navigationLabel:'navigation',
|
|
108
|
+
noSelectionLabel:'noSelection',
|
|
109
|
+
selectedLabel:'selected',
|
|
110
|
+
timeLabel:'time',
|
|
111
|
+
valueLabel:'value'
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
for(const [source,target] of Object.entries(aliases)){
|
|
115
|
+
if(typeof input[source]==='string'){
|
|
116
|
+
labels[target]=input[source];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const styleValue=string(
|
|
121
|
+
optionAlias(input,previous,['style','chartStyle'],'line'),
|
|
122
|
+
'line'
|
|
123
|
+
);
|
|
124
|
+
const style=['area','line','points'].includes(styleValue)?styleValue:'line';
|
|
125
|
+
const min=finiteNumber(option(input,previous,'min',null),'min');
|
|
126
|
+
const max=finiteNumber(option(input,previous,'max',null),'max');
|
|
127
|
+
if(min!==null&&max!==null&&max<=min){
|
|
128
|
+
throw new RangeError('max must be greater than min');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const chartOptions=option(input,previous,'chartOptions',null);
|
|
132
|
+
if(
|
|
133
|
+
chartOptions!==null
|
|
134
|
+
&&typeof chartOptions!=='function'
|
|
135
|
+
&&(!chartOptions||typeof chartOptions!=='object'||Array.isArray(chartOptions))
|
|
136
|
+
){
|
|
137
|
+
throw new TypeError('chartOptions must be an object, function, or null');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const data=optionAlias(input,previous,['data','dataset','datasets'],undefined);
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
key:string(optionAlias(input,previous,['key','chartKey'],''),'',true),
|
|
144
|
+
title:text(optionAlias(input,previous,['title','name'],'Chart'),'Chart'),
|
|
145
|
+
info:text(optionAlias(input,previous,['info','description'],'') ,'',true),
|
|
146
|
+
style,
|
|
147
|
+
seriesLabel:text(option(input,previous,'seriesLabel',labels.value),labels.value),
|
|
148
|
+
labels,
|
|
149
|
+
min,
|
|
150
|
+
max,
|
|
151
|
+
removable:option(input,previous,'removable',false)===true,
|
|
152
|
+
removeLabel:text(option(input,previous,'removeLabel',''),'',true),
|
|
153
|
+
color:text(option(input,previous,'color',''),'',true),
|
|
154
|
+
unit:text(option(input,previous,'unit',''),'',true),
|
|
155
|
+
time:option(input,previous,'time',true)!==false,
|
|
156
|
+
xKey:string(option(input,previous,'xKey',''),'',true),
|
|
157
|
+
yKey:string(option(input,previous,'yKey',''),'',true),
|
|
158
|
+
mapRow:optionalCallback(input,previous,['mapRow']),
|
|
159
|
+
parseX:optionalCallback(input,previous,['parseX']),
|
|
160
|
+
parseY:optionalCallback(input,previous,['parseY']),
|
|
161
|
+
formatTime:optionalCallback(input,previous,['formatTime']),
|
|
162
|
+
formatValue:optionalCallback(input,previous,['formatValue']),
|
|
163
|
+
chartOptions:typeof chartOptions==='object'&&chartOptions!==null
|
|
164
|
+
?{...chartOptions}
|
|
165
|
+
:chartOptions,
|
|
166
|
+
data
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function numericX(value,time=true){
|
|
171
|
+
if(value instanceof Date){
|
|
172
|
+
return value.getTime();
|
|
173
|
+
}
|
|
174
|
+
const number=Number(value);
|
|
175
|
+
if(Number.isFinite(number)){
|
|
176
|
+
return number;
|
|
177
|
+
}
|
|
178
|
+
if(time&&typeof value==='string'){
|
|
179
|
+
const parsed=Date.parse(value);
|
|
180
|
+
return Number.isFinite(parsed)?parsed:NaN;
|
|
181
|
+
}
|
|
182
|
+
return NaN;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function normalizeChartRows(data=[],options={}){
|
|
186
|
+
const config=normalizeChartOptions(options);
|
|
187
|
+
if(data&&typeof data==='object'&&!Array.isArray(data)){
|
|
188
|
+
data=Object.entries(data);
|
|
189
|
+
}
|
|
190
|
+
if(!Array.isArray(data)){
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
const normalized=[];
|
|
194
|
+
|
|
195
|
+
for(let index=0;index<data.length;index++){
|
|
196
|
+
const original=data[index];
|
|
197
|
+
const item=config.mapRow?config.mapRow(original,index):original;
|
|
198
|
+
const x=Array.isArray(item)
|
|
199
|
+
?item[0]
|
|
200
|
+
:config.xKey
|
|
201
|
+
?item?.[config.xKey]
|
|
202
|
+
:item?.date??item?.timestamp??item?.x;
|
|
203
|
+
const y=Array.isArray(item)
|
|
204
|
+
?item[1]
|
|
205
|
+
:config.yKey
|
|
206
|
+
?item?.[config.yKey]
|
|
207
|
+
:item?.value??item?.score??item?.y;
|
|
208
|
+
const parsedX=config.parseX?config.parseX(x,item,index):x;
|
|
209
|
+
const parsedY=config.parseY?config.parseY(y,item,index):y;
|
|
210
|
+
const normalizedX=numericX(parsedX,config.time);
|
|
211
|
+
const normalizedY=Number(parsedY);
|
|
212
|
+
|
|
213
|
+
if(Number.isFinite(normalizedX)&&Number.isFinite(normalizedY)){
|
|
214
|
+
normalized.push([normalizedX,normalizedY]);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
normalized.sort((left,right)=>left[0]-right[0]);
|
|
219
|
+
return Array.from(new Map(normalized.map(row=>[row[0],row])).values());
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function normalizeDashboardDefinitions(values=[]){
|
|
223
|
+
if(!Array.isArray(values)){
|
|
224
|
+
throw new TypeError('Dashboard definitions must be an array');
|
|
225
|
+
}
|
|
226
|
+
const keys=new Set();
|
|
227
|
+
return values.map(
|
|
228
|
+
(value,index)=>{
|
|
229
|
+
value=record(value,`Dashboard definition ${index}`);
|
|
230
|
+
const key=string(value.key,'');
|
|
231
|
+
if(!key||keys.has(key)){
|
|
232
|
+
throw new Error('Dashboard definition keys must be unique and nonempty');
|
|
233
|
+
}
|
|
234
|
+
keys.add(key);
|
|
235
|
+
const title=text(value.title??value.label??value.name??key,key);
|
|
236
|
+
const description=text(value.description??value.info??'','',true);
|
|
237
|
+
const suppliedChartOptions=record(
|
|
238
|
+
value.chartOptions,
|
|
239
|
+
'Dashboard chart options'
|
|
240
|
+
);
|
|
241
|
+
const chartOptions=normalizeChartOptions({
|
|
242
|
+
...value,
|
|
243
|
+
...suppliedChartOptions,
|
|
244
|
+
key,
|
|
245
|
+
title,
|
|
246
|
+
info:own(suppliedChartOptions,'info')
|
|
247
|
+
?suppliedChartOptions.info
|
|
248
|
+
:description
|
|
249
|
+
});
|
|
250
|
+
return {
|
|
251
|
+
...value,
|
|
252
|
+
key,
|
|
253
|
+
title,
|
|
254
|
+
description,
|
|
255
|
+
defaultVisible:value.defaultVisible!==false,
|
|
256
|
+
disabled:value.disabled===true,
|
|
257
|
+
group:text(value.group,'',true),
|
|
258
|
+
chartOptions
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const DASHBOARD_LABELS=Object.freeze({
|
|
265
|
+
description:'Choose which charts appear on your dashboard.',
|
|
266
|
+
empty:'No dashboard items are available.',
|
|
267
|
+
heading:'Configure Dashboard',
|
|
268
|
+
trigger:'Configure Dashboard'
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
function normalizeDashboardVisibility(values={}){
|
|
272
|
+
values=record(values,'Dashboard visibility');
|
|
273
|
+
const visibility={};
|
|
274
|
+
for(const [key,value] of Object.entries(values)){
|
|
275
|
+
if(typeof value==='boolean'){
|
|
276
|
+
visibility[key]=value;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return visibility;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function normalizeDashboardOptions(input={},previous={}){
|
|
283
|
+
input=record(input,'Dashboard configuration');
|
|
284
|
+
previous=record(previous,'Previous dashboard configuration');
|
|
285
|
+
const previousLabels=stringRecord(
|
|
286
|
+
previous.labels,
|
|
287
|
+
DASHBOARD_LABELS,
|
|
288
|
+
'Previous dashboard labels'
|
|
289
|
+
);
|
|
290
|
+
const labels=stringRecord(input.labels,previousLabels,'Dashboard labels');
|
|
291
|
+
const aliases={
|
|
292
|
+
description:'description',
|
|
293
|
+
emptyLabel:'empty',
|
|
294
|
+
heading:'heading',
|
|
295
|
+
triggerLabel:'trigger'
|
|
296
|
+
};
|
|
297
|
+
for(const [source,target] of Object.entries(aliases)){
|
|
298
|
+
if(typeof input[source]==='string'){
|
|
299
|
+
labels[target]=input[source];
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return {
|
|
303
|
+
labels,
|
|
304
|
+
definitions:own(input,'definitions')
|
|
305
|
+
?normalizeDashboardDefinitions(input.definitions)
|
|
306
|
+
:Array.isArray(previous.definitions)
|
|
307
|
+
?normalizeDashboardDefinitions(previous.definitions)
|
|
308
|
+
:[],
|
|
309
|
+
visibility:own(input,'visibility')
|
|
310
|
+
?normalizeDashboardVisibility(input.visibility)
|
|
311
|
+
:normalizeDashboardVisibility(previous.visibility)
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function effectiveDashboardVisibility(definitions=[],visibility={}){
|
|
316
|
+
definitions=normalizeDashboardDefinitions(definitions);
|
|
317
|
+
visibility=normalizeDashboardVisibility(visibility);
|
|
318
|
+
return Object.fromEntries(
|
|
319
|
+
definitions.map(
|
|
320
|
+
definition=>[
|
|
321
|
+
definition.key,
|
|
322
|
+
typeof visibility[definition.key]==='boolean'
|
|
323
|
+
?visibility[definition.key]
|
|
324
|
+
:definition.defaultVisible
|
|
325
|
+
]
|
|
326
|
+
)
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const VOICE_LABELS=Object.freeze({
|
|
331
|
+
complete:'Complete Transcription',
|
|
332
|
+
description:'Record one or more segments. Each segment is transcribed after you press Stop.',
|
|
333
|
+
empty:'Your transcription will appear here after you stop recording.',
|
|
334
|
+
start:'Start',
|
|
335
|
+
stop:'Stop',
|
|
336
|
+
transcription:'Voice transcription'
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
const VOICE_MESSAGES=Object.freeze({
|
|
340
|
+
complete:'Complete.',
|
|
341
|
+
completeError:'Unable to complete this transcription.',
|
|
342
|
+
completing:'Completing transcription...',
|
|
343
|
+
emptyAudio:'No audio was captured. Try recording again.',
|
|
344
|
+
interrupted:'Recording was interrupted. Your completed transcription is still available.',
|
|
345
|
+
noSpeech:'No speech was transcribed. You can try another segment.',
|
|
346
|
+
ready:'Ready.',
|
|
347
|
+
recording:'Recording...',
|
|
348
|
+
recordingEnded:'Recording ended. Transcribing captured audio...',
|
|
349
|
+
requesting:'Requesting microphone access...',
|
|
350
|
+
saved:'Transcription saved. Record another segment or complete.',
|
|
351
|
+
saveError:'Transcribed, but unable to save.',
|
|
352
|
+
saving:'Saving transcription...',
|
|
353
|
+
startError:'Unable to start recording. Check microphone permission and try again.',
|
|
354
|
+
transcribed:'Transcription added. Record another segment or complete.',
|
|
355
|
+
transcribeError:'Unable to transcribe this recording.',
|
|
356
|
+
transcribing:'Transcribing this segment...',
|
|
357
|
+
unsupported:'Audio recording is not supported by this browser.'
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
function normalizeVoiceOptions(input={},previous={}){
|
|
361
|
+
input=record(input,'Voice transcription options');
|
|
362
|
+
previous=record(previous,'Previous voice transcription options');
|
|
363
|
+
const previousLabels=stringRecord(
|
|
364
|
+
previous.labels,
|
|
365
|
+
VOICE_LABELS,
|
|
366
|
+
'Previous voice labels'
|
|
367
|
+
);
|
|
368
|
+
const labels=stringRecord(input.labels,previousLabels,'Voice labels');
|
|
369
|
+
const aliases={
|
|
370
|
+
completeLabel:'complete',
|
|
371
|
+
description:'description',
|
|
372
|
+
emptyLabel:'empty',
|
|
373
|
+
startLabel:'start',
|
|
374
|
+
stopLabel:'stop',
|
|
375
|
+
transcriptionLabel:'transcription'
|
|
376
|
+
};
|
|
377
|
+
for(const [source,target] of Object.entries(aliases)){
|
|
378
|
+
if(typeof input[source]==='string'){
|
|
379
|
+
labels[target]=input[source];
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const constraints=option(input,previous,'mediaConstraints',{audio:true});
|
|
384
|
+
if(!constraints||typeof constraints!=='object'||Array.isArray(constraints)){
|
|
385
|
+
throw new TypeError('mediaConstraints must be an object');
|
|
386
|
+
}
|
|
387
|
+
if(!own(constraints,'audio')||constraints.audio===false){
|
|
388
|
+
throw new TypeError('mediaConstraints.audio must request audio');
|
|
389
|
+
}
|
|
390
|
+
const mimeTypes=option(
|
|
391
|
+
input,
|
|
392
|
+
previous,
|
|
393
|
+
'mimeTypes',
|
|
394
|
+
['audio/webm;codecs=opus','audio/mp4','audio/webm']
|
|
395
|
+
);
|
|
396
|
+
if(!Array.isArray(mimeTypes)){
|
|
397
|
+
throw new TypeError('mimeTypes must be an array');
|
|
398
|
+
}
|
|
399
|
+
if(mimeTypes.some(value=>typeof value!=='string')){
|
|
400
|
+
throw new TypeError('mimeTypes must contain only strings');
|
|
401
|
+
}
|
|
402
|
+
const separator=option(input,previous,'separator','\n\n');
|
|
403
|
+
if(typeof separator!=='string'){
|
|
404
|
+
throw new TypeError('separator must be a string');
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return {
|
|
408
|
+
labels,
|
|
409
|
+
messages:stringRecord(
|
|
410
|
+
input.messages,
|
|
411
|
+
stringRecord(
|
|
412
|
+
previous.messages,
|
|
413
|
+
VOICE_MESSAGES,
|
|
414
|
+
'Previous voice messages'
|
|
415
|
+
),
|
|
416
|
+
'Voice messages'
|
|
417
|
+
),
|
|
418
|
+
mediaConstraints:{...constraints},
|
|
419
|
+
mimeTypes:[...new Set(mimeTypes.map(value=>value.trim()).filter(Boolean))],
|
|
420
|
+
persist:option(input,previous,'persist',true)!==false,
|
|
421
|
+
transcribe:optionalCallback(input,previous,['transcribe']),
|
|
422
|
+
onSave:optionalCallback(input,previous,['onSave','save'],'onSave'),
|
|
423
|
+
onComplete:optionalCallback(input,previous,['onComplete','complete'],'onComplete'),
|
|
424
|
+
separator,
|
|
425
|
+
initialValue:text(option(input,previous,'initialValue',''),'',true)
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function appendTranscription(current='',segment='',separator='\n\n'){
|
|
430
|
+
current=text(current,'',true).trim();
|
|
431
|
+
segment=text(segment,'',true).trim();
|
|
432
|
+
if(!segment){
|
|
433
|
+
return current;
|
|
434
|
+
}
|
|
435
|
+
return current?`${current}${separator}${segment}`:segment;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
const MARKDOWN_FORMATS=Object.freeze([
|
|
439
|
+
Object.freeze({id:'heading',label:'Heading',title:'Heading',prefix:'## ',placeholder:'Heading'}),
|
|
440
|
+
Object.freeze({id:'bold',label:'B',title:'Bold',before:'**',after:'**',placeholder:'bold text'}),
|
|
441
|
+
Object.freeze({id:'italic',label:'I',title:'Italic',before:'_',after:'_',placeholder:'italic text'}),
|
|
442
|
+
Object.freeze({id:'strike',label:'S',title:'Strikethrough',before:'~~',after:'~~',placeholder:'strikethrough text'}),
|
|
443
|
+
Object.freeze({id:'code',label:'Code',title:'Inline code',before:'`',after:'`',placeholder:'code'}),
|
|
444
|
+
Object.freeze({id:'link',label:'Link',title:'Link',before:'[',after:'](https://)',placeholder:'link text'}),
|
|
445
|
+
Object.freeze({id:'quote',label:'Quote',title:'Quote',prefix:'> ',placeholder:'Quote'}),
|
|
446
|
+
Object.freeze({id:'list',label:'List',title:'Bulleted list',prefix:'- ',placeholder:'List item'})
|
|
447
|
+
]);
|
|
448
|
+
|
|
449
|
+
const MARKDOWN_LABELS=Object.freeze({
|
|
450
|
+
bodyPlaceholder:'Write in Markdown...',
|
|
451
|
+
emptyError:'Write content before saving.',
|
|
452
|
+
preview:'Markdown preview',
|
|
453
|
+
save:'Save',
|
|
454
|
+
saveError:'Unable to save.',
|
|
455
|
+
saved:'Saved.',
|
|
456
|
+
saving:'Saving...',
|
|
457
|
+
titlePlaceholder:'Title (optional)',
|
|
458
|
+
toolbar:'Markdown formatting',
|
|
459
|
+
unavailable:'Saving is unavailable.'
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
function normalizeMarkdownFormats(values=MARKDOWN_FORMATS){
|
|
463
|
+
if(!Array.isArray(values)){
|
|
464
|
+
throw new TypeError('Markdown formats must be an array');
|
|
465
|
+
}
|
|
466
|
+
const ids=new Set();
|
|
467
|
+
return values.map(
|
|
468
|
+
(value,index)=>{
|
|
469
|
+
value=record(value,`Markdown format ${index}`);
|
|
470
|
+
const id=string(value.id,'');
|
|
471
|
+
if(!/^[a-z][a-z0-9-]{0,31}$/.test(id)||ids.has(id)){
|
|
472
|
+
throw new Error('Markdown format ids must be unique lowercase identifiers');
|
|
473
|
+
}
|
|
474
|
+
ids.add(id);
|
|
475
|
+
const prefix=text(value.prefix,'',true);
|
|
476
|
+
const before=text(value.before,'',true);
|
|
477
|
+
const after=text(value.after,'',true);
|
|
478
|
+
if(!prefix&&!before&&!after){
|
|
479
|
+
throw new Error(`Markdown format ${id} must define a prefix or wrapper`);
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
id,
|
|
483
|
+
label:text(value.label??id,id),
|
|
484
|
+
title:text(value.title??value.label??id,id),
|
|
485
|
+
prefix,
|
|
486
|
+
before,
|
|
487
|
+
after,
|
|
488
|
+
placeholder:text(value.placeholder??value.label??id,id)
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function normalizeMarkdownOptions(input={},previous={}){
|
|
495
|
+
input=record(input,'Markdown editor options');
|
|
496
|
+
previous=record(previous,'Previous markdown editor options');
|
|
497
|
+
const previousLabels=stringRecord(
|
|
498
|
+
previous.labels,
|
|
499
|
+
MARKDOWN_LABELS,
|
|
500
|
+
'Previous markdown labels'
|
|
501
|
+
);
|
|
502
|
+
const labels=stringRecord(input.labels,previousLabels,'Markdown labels');
|
|
503
|
+
const aliases={
|
|
504
|
+
bodyPlaceholder:'bodyPlaceholder',
|
|
505
|
+
previewLabel:'preview',
|
|
506
|
+
saveLabel:'save',
|
|
507
|
+
titlePlaceholder:'titlePlaceholder',
|
|
508
|
+
toolbarLabel:'toolbar'
|
|
509
|
+
};
|
|
510
|
+
for(const [source,target] of Object.entries(aliases)){
|
|
511
|
+
if(typeof input[source]==='string'){
|
|
512
|
+
labels[target]=input[source];
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
return {
|
|
517
|
+
labels,
|
|
518
|
+
formats:normalizeMarkdownFormats(option(input,previous,'formats',MARKDOWN_FORMATS)),
|
|
519
|
+
showTitle:option(input,previous,'showTitle',true)!==false,
|
|
520
|
+
showPreview:option(input,previous,'showPreview',true)!==false,
|
|
521
|
+
showToolbar:option(input,previous,'showToolbar',true)!==false,
|
|
522
|
+
showSave:option(input,previous,'showSave',true)!==false,
|
|
523
|
+
readOnly:option(input,previous,'readOnly',false)===true,
|
|
524
|
+
clearOnSave:option(input,previous,'clearOnSave',true)!==false,
|
|
525
|
+
onSave:optionalCallback(input,previous,['onSave','save'],'onSave'),
|
|
526
|
+
onChange:optionalCallback(input,previous,['onChange']),
|
|
527
|
+
initialValue:text(option(input,previous,'initialValue',''),'',true),
|
|
528
|
+
initialTitle:text(option(input,previous,'initialTitle',''),'',true)
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
function applyMarkdownFormat(value='',selectionStart=0,selectionEnd=selectionStart,format={}){
|
|
533
|
+
value=text(value,'',true);
|
|
534
|
+
format=normalizeMarkdownFormats([format])[0];
|
|
535
|
+
const rawStart=Number(selectionStart);
|
|
536
|
+
const rawEnd=Number(selectionEnd);
|
|
537
|
+
const start=Math.max(
|
|
538
|
+
0,
|
|
539
|
+
Math.min(value.length,Number.isFinite(rawStart)?rawStart:0)
|
|
540
|
+
);
|
|
541
|
+
const end=Math.max(
|
|
542
|
+
start,
|
|
543
|
+
Math.min(value.length,Number.isFinite(rawEnd)?rawEnd:start)
|
|
544
|
+
);
|
|
545
|
+
const selected=value.slice(start,end);
|
|
546
|
+
const content=selected||format.placeholder;
|
|
547
|
+
let replacement='';
|
|
548
|
+
let nextStart=start;
|
|
549
|
+
let nextEnd=start;
|
|
550
|
+
|
|
551
|
+
if(format.prefix){
|
|
552
|
+
replacement=content.split(/\r?\n/).map(line=>format.prefix+line).join('\n');
|
|
553
|
+
nextStart=start+format.prefix.length;
|
|
554
|
+
nextEnd=start+replacement.length;
|
|
555
|
+
}else{
|
|
556
|
+
replacement=format.before+content+format.after;
|
|
557
|
+
nextStart=start+format.before.length;
|
|
558
|
+
nextEnd=nextStart+content.length;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
return {
|
|
562
|
+
value:value.slice(0,start)+replacement+value.slice(end),
|
|
563
|
+
selectionStart:nextStart,
|
|
564
|
+
selectionEnd:nextEnd
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
export {
|
|
569
|
+
CHART_LABELS,
|
|
570
|
+
DASHBOARD_LABELS,
|
|
571
|
+
MARKDOWN_FORMATS,
|
|
572
|
+
MARKDOWN_LABELS,
|
|
573
|
+
VOICE_LABELS,
|
|
574
|
+
VOICE_MESSAGES,
|
|
575
|
+
appendTranscription,
|
|
576
|
+
applyMarkdownFormat,
|
|
577
|
+
effectiveDashboardVisibility,
|
|
578
|
+
normalizeChartOptions,
|
|
579
|
+
normalizeChartRows,
|
|
580
|
+
normalizeDashboardDefinitions,
|
|
581
|
+
normalizeDashboardOptions,
|
|
582
|
+
normalizeDashboardVisibility,
|
|
583
|
+
normalizeMarkdownFormats,
|
|
584
|
+
normalizeMarkdownOptions,
|
|
585
|
+
normalizeVoiceOptions
|
|
586
|
+
};
|