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
package/src/cli/main.mjs
ADDED
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import {createReporter} from '../events.mjs';
|
|
3
|
+
import {executeOperation} from '../toolchain.mjs';
|
|
4
|
+
import {ArcaneError,ERROR_CODES,normalizeError} from '../errors.mjs';
|
|
5
|
+
import {CLI_NAME,SDK_NAME,SDK_VERSION,OUTPUT_MODES} from '../constants.mjs';
|
|
6
|
+
import {loadArcaneNativeProvider} from '../native-provider-loader.mjs';
|
|
7
|
+
import {APP_BUNDLE_EXTENSION} from '../release-bundle.mjs';
|
|
8
|
+
|
|
9
|
+
const VALUE_OPTIONS=new Set([
|
|
10
|
+
'path',
|
|
11
|
+
'display-name',
|
|
12
|
+
'workspace',
|
|
13
|
+
'app',
|
|
14
|
+
'arcane-root',
|
|
15
|
+
'host',
|
|
16
|
+
'port',
|
|
17
|
+
'target',
|
|
18
|
+
'format',
|
|
19
|
+
'signing',
|
|
20
|
+
'output-root',
|
|
21
|
+
'scope',
|
|
22
|
+
'test-file',
|
|
23
|
+
'artifact',
|
|
24
|
+
'output'
|
|
25
|
+
]);
|
|
26
|
+
const FLAG_OPTIONS=new Set([
|
|
27
|
+
'git',
|
|
28
|
+
'skip-tests',
|
|
29
|
+
'dry-run',
|
|
30
|
+
'require-local-ai',
|
|
31
|
+
'overwrite',
|
|
32
|
+
'help',
|
|
33
|
+
'version'
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
export const HELP_TEXT=`Arcane OS application SDK ${SDK_VERSION}
|
|
37
|
+
|
|
38
|
+
Usage:
|
|
39
|
+
${CLI_NAME} new <id> [--path <directory>] [--display-name <name>] [--target <target>] [--git]
|
|
40
|
+
${CLI_NAME} init [id] [--workspace <directory>] [--display-name <name>] [--target <target>]
|
|
41
|
+
${CLI_NAME} doctor [--workspace <directory>] [--arcane-root <directory>]
|
|
42
|
+
${CLI_NAME} dev [--app <id>] [--host 127.0.0.1] [--port 8000]
|
|
43
|
+
${CLI_NAME} test [--app <id>] [--scope app]
|
|
44
|
+
${CLI_NAME} test --scope shared --test-file <repo-relative.test.mjs>
|
|
45
|
+
${CLI_NAME} check [--app <id>] [--scope app] [--skip-tests]
|
|
46
|
+
${CLI_NAME} check --scope shared
|
|
47
|
+
${CLI_NAME} package [--app <id>] [--dry-run]
|
|
48
|
+
${CLI_NAME} verify [--app <id>]
|
|
49
|
+
${CLI_NAME} bundle [--app <id>] [--artifact <file>${APP_BUNDLE_EXTENSION}] [--overwrite]
|
|
50
|
+
${CLI_NAME} verify-bundle <file${APP_BUNDLE_EXTENSION}>
|
|
51
|
+
${CLI_NAME} native-doctor --target <native-target> --arcane-root <directory>
|
|
52
|
+
${CLI_NAME} native-prepare --target <native-target> --arcane-root <directory>
|
|
53
|
+
${CLI_NAME} build --target <target> [--arcane-root <directory>] [--output-root <directory>] [--format <format>] [--signing <mode>]
|
|
54
|
+
${CLI_NAME} run [--target <target>] [--app <id>] [--arcane-root <directory>] [--output-root <directory>] [--format <format>] [--signing <mode>]
|
|
55
|
+
${CLI_NAME} update-check
|
|
56
|
+
${CLI_NAME} targets
|
|
57
|
+
${CLI_NAME} repo status|pull|push
|
|
58
|
+
|
|
59
|
+
Global:
|
|
60
|
+
--workspace <directory> Select an external or integrated Arcane workspace.
|
|
61
|
+
--output human|json|ndjson Select output framing (default: human).
|
|
62
|
+
--help Show this help.
|
|
63
|
+
--version Show the SDK version.
|
|
64
|
+
|
|
65
|
+
The npm package is ${SDK_NAME}. Both the ${CLI_NAME} and arcane-os executables
|
|
66
|
+
invoke this same headless toolchain. Every native operation requires one explicit
|
|
67
|
+
--arcane-root. Available providers build portable directories, Windows x64 EXE
|
|
68
|
+
bundles, Linux x64 or ARM64 DEBs, and development-signed Android APKs.`;
|
|
69
|
+
|
|
70
|
+
function usage(message){
|
|
71
|
+
throw new ArcaneError(ERROR_CODES.usage,message);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function normalizeOptionName(value){
|
|
75
|
+
if(value==='-h')return 'help';
|
|
76
|
+
if(value==='-v')return 'version';
|
|
77
|
+
return value.startsWith('--')?value.slice(2):value;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function extractOutput(argv){
|
|
81
|
+
const remaining=[];
|
|
82
|
+
let output='human';
|
|
83
|
+
for(let index=0;index<argv.length;index+=1){
|
|
84
|
+
const argument=argv[index];
|
|
85
|
+
if(argument==='--output'){
|
|
86
|
+
output=argv[index+1];
|
|
87
|
+
index+=1;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if(argument.startsWith('--output=')){
|
|
91
|
+
output=argument.slice('--output='.length);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
remaining.push(argument);
|
|
95
|
+
}
|
|
96
|
+
if(!OUTPUT_MODES.includes(output)){
|
|
97
|
+
usage(`Invalid --output value: ${String(output)}. Expected human, json, or ndjson.`);
|
|
98
|
+
}
|
|
99
|
+
return {output,remaining};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function parseCliArguments(argv){
|
|
103
|
+
const values={};
|
|
104
|
+
const flags=new Set();
|
|
105
|
+
const positionals=[];
|
|
106
|
+
for(let index=0;index<argv.length;index+=1){
|
|
107
|
+
const argument=argv[index];
|
|
108
|
+
if(argument==='--'){
|
|
109
|
+
positionals.push(...argv.slice(index+1));
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
if(argument.startsWith('-')){
|
|
113
|
+
const equal=argument.indexOf('=');
|
|
114
|
+
const rawName=equal===-1?argument:argument.slice(0,equal);
|
|
115
|
+
const name=normalizeOptionName(rawName);
|
|
116
|
+
if(FLAG_OPTIONS.has(name)){
|
|
117
|
+
if(equal!==-1){
|
|
118
|
+
usage(`Option --${name} does not accept a value.`);
|
|
119
|
+
}
|
|
120
|
+
flags.add(name);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if(!VALUE_OPTIONS.has(name)){
|
|
124
|
+
usage(`Unknown option: ${argument}.`);
|
|
125
|
+
}
|
|
126
|
+
const value=equal===-1?argv[++index]:argument.slice(equal+1);
|
|
127
|
+
if(value===undefined||value===''||(equal===-1&&value.startsWith('-'))){
|
|
128
|
+
usage(`Option --${name} requires a value.`);
|
|
129
|
+
}
|
|
130
|
+
values[name]=value;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
positionals.push(argument);
|
|
134
|
+
}
|
|
135
|
+
return {values,flags,positionals};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function readPort(value,defaultValue){
|
|
139
|
+
if(value===undefined){
|
|
140
|
+
return defaultValue;
|
|
141
|
+
}
|
|
142
|
+
if(!/^\d+$/u.test(value)){
|
|
143
|
+
usage(`Invalid port: ${value}.`);
|
|
144
|
+
}
|
|
145
|
+
const port=Number(value);
|
|
146
|
+
if(!Number.isSafeInteger(port)||port<0||port>65535){
|
|
147
|
+
usage(`Invalid port: ${value}.`);
|
|
148
|
+
}
|
|
149
|
+
return port;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function readScope(value){
|
|
153
|
+
const scope=value??'app';
|
|
154
|
+
if(!['app','shared'].includes(scope)){
|
|
155
|
+
usage(`Invalid --scope value: ${String(scope)}. Expected app or shared.`);
|
|
156
|
+
}
|
|
157
|
+
return scope;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function inferredAppId(workspaceRoot){
|
|
161
|
+
const id=path.basename(workspaceRoot)
|
|
162
|
+
.normalize('NFKD')
|
|
163
|
+
.toLowerCase()
|
|
164
|
+
.replace(/[^a-z0-9]+/gu,'-')
|
|
165
|
+
.replace(/^-+|-+$/gu,'');
|
|
166
|
+
return id||'arcane-app';
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function noExtraPositionals(command,positionals,expected=0){
|
|
170
|
+
if(positionals.length>expected){
|
|
171
|
+
usage(`Unexpected argument for ${command}: ${positionals[expected]}.`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function operationOptions(command,parsed,cwd){
|
|
176
|
+
const {values,flags}=parsed;
|
|
177
|
+
const positionals=parsed.positionals.slice(1);
|
|
178
|
+
const workspaceRoot=path.resolve(cwd,values.workspace??'.');
|
|
179
|
+
const scope=readScope(values.scope);
|
|
180
|
+
const common={workspaceRoot,appId:values.app,scope};
|
|
181
|
+
if(scope==='shared'&&!['test','check'].includes(command)){
|
|
182
|
+
usage(`--scope shared is not supported by ${command}; shared development cannot package or build app output.`);
|
|
183
|
+
}
|
|
184
|
+
if(values['test-file']!==undefined&&command!=='test'){
|
|
185
|
+
usage('--test-file is supported only by test --scope shared.');
|
|
186
|
+
}
|
|
187
|
+
if(values.artifact!==undefined&&!['bundle','verify-bundle'].includes(command)){
|
|
188
|
+
usage('--artifact is supported only by bundle and verify-bundle.');
|
|
189
|
+
}
|
|
190
|
+
if(flags.has('overwrite')&&command!=='bundle'){
|
|
191
|
+
usage('--overwrite is supported only by bundle.');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if(command==='new'){
|
|
195
|
+
const appId=positionals[0];
|
|
196
|
+
if(!appId)usage('new requires an application id.');
|
|
197
|
+
noExtraPositionals(command,positionals,1);
|
|
198
|
+
return {
|
|
199
|
+
targetPath:path.resolve(cwd,values.path??appId),
|
|
200
|
+
appId,
|
|
201
|
+
displayName:values['display-name'],
|
|
202
|
+
target:values.target??'browser',
|
|
203
|
+
initializeGit:flags.has('git')
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
if(command==='init'){
|
|
207
|
+
noExtraPositionals(command,positionals,1);
|
|
208
|
+
return {
|
|
209
|
+
workspaceRoot,
|
|
210
|
+
appId:positionals[0]??values.app??inferredAppId(workspaceRoot),
|
|
211
|
+
displayName:values['display-name'],
|
|
212
|
+
target:values.target??'browser'
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
if(command==='doctor'){
|
|
216
|
+
noExtraPositionals(command,positionals);
|
|
217
|
+
return {
|
|
218
|
+
...common,
|
|
219
|
+
arcaneRoot:values['arcane-root']?path.resolve(cwd,values['arcane-root']):undefined,
|
|
220
|
+
requireLocalAI:flags.has('require-local-ai')
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
if(command==='dev'){
|
|
224
|
+
noExtraPositionals(command,positionals);
|
|
225
|
+
return {
|
|
226
|
+
...common,
|
|
227
|
+
host:values.host??'127.0.0.1',
|
|
228
|
+
port:readPort(values.port,8000)
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
if(command==='test'){
|
|
232
|
+
noExtraPositionals(command,positionals);
|
|
233
|
+
if(scope==='shared'){
|
|
234
|
+
if(values.app)usage('test --scope shared does not accept --app.');
|
|
235
|
+
if(!values['test-file']){
|
|
236
|
+
usage('test --scope shared requires --test-file <repo-relative.test.mjs>.');
|
|
237
|
+
}
|
|
238
|
+
}else if(values['test-file']){
|
|
239
|
+
usage('--test-file requires test --scope shared.');
|
|
240
|
+
}
|
|
241
|
+
return {...common,scope,testFile:values['test-file']};
|
|
242
|
+
}
|
|
243
|
+
if(command==='check'){
|
|
244
|
+
noExtraPositionals(command,positionals);
|
|
245
|
+
if(scope==='shared'){
|
|
246
|
+
if(values.app)usage('check --scope shared does not accept --app.');
|
|
247
|
+
if(flags.has('skip-tests'))usage('check --scope shared does not accept --skip-tests.');
|
|
248
|
+
}
|
|
249
|
+
return {...common,scope,skipTests:flags.has('skip-tests')};
|
|
250
|
+
}
|
|
251
|
+
if(command==='package'){
|
|
252
|
+
noExtraPositionals(command,positionals);
|
|
253
|
+
return {...common,dryRun:flags.has('dry-run')};
|
|
254
|
+
}
|
|
255
|
+
if(command==='verify'){
|
|
256
|
+
noExtraPositionals(command,positionals);
|
|
257
|
+
return common;
|
|
258
|
+
}
|
|
259
|
+
if(command==='bundle'){
|
|
260
|
+
noExtraPositionals(command,positionals);
|
|
261
|
+
return {
|
|
262
|
+
...common,
|
|
263
|
+
artifactPath:values.artifact?path.resolve(cwd,values.artifact):undefined,
|
|
264
|
+
overwrite:flags.has('overwrite')
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if(command==='verify-bundle'){
|
|
268
|
+
noExtraPositionals(command,positionals,1);
|
|
269
|
+
if(values.app)usage('verify-bundle does not accept --app.');
|
|
270
|
+
if(flags.has('overwrite'))usage('verify-bundle does not accept --overwrite.');
|
|
271
|
+
if(values.artifact&&positionals[0]){
|
|
272
|
+
usage('verify-bundle accepts either one file argument or --artifact, not both.');
|
|
273
|
+
}
|
|
274
|
+
const artifact=values.artifact??positionals[0];
|
|
275
|
+
if(!artifact)usage('verify-bundle requires one bundle file.');
|
|
276
|
+
return {artifactPath:path.resolve(cwd,artifact)};
|
|
277
|
+
}
|
|
278
|
+
if(command==='build'){
|
|
279
|
+
noExtraPositionals(command,positionals);
|
|
280
|
+
if(!values.target)usage('build requires --target <target>.');
|
|
281
|
+
return {
|
|
282
|
+
...common,
|
|
283
|
+
target:values.target,
|
|
284
|
+
arcaneRoot:values['arcane-root']?path.resolve(cwd,values['arcane-root']):undefined,
|
|
285
|
+
outputRoot:values['output-root']?path.resolve(cwd,values['output-root']):undefined,
|
|
286
|
+
format:values.format,
|
|
287
|
+
signing:values.signing,
|
|
288
|
+
dryRun:flags.has('dry-run')
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
if(command==='native-doctor'||command==='native-prepare'){
|
|
292
|
+
noExtraPositionals(command,positionals);
|
|
293
|
+
if(!values.target)usage(`${command} requires --target <native-target>.`);
|
|
294
|
+
return {
|
|
295
|
+
target:values.target,
|
|
296
|
+
arcaneRoot:values['arcane-root']?path.resolve(cwd,values['arcane-root']):undefined,
|
|
297
|
+
format:values.format,
|
|
298
|
+
signing:values.signing
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
if(command==='run'){
|
|
302
|
+
noExtraPositionals(command,positionals);
|
|
303
|
+
return {
|
|
304
|
+
...common,
|
|
305
|
+
target:values.target??'browser',
|
|
306
|
+
arcaneRoot:values['arcane-root']?path.resolve(cwd,values['arcane-root']):undefined,
|
|
307
|
+
outputRoot:values['output-root']?path.resolve(cwd,values['output-root']):undefined,
|
|
308
|
+
format:values.format,
|
|
309
|
+
signing:values.signing,
|
|
310
|
+
host:values.host??'127.0.0.1',
|
|
311
|
+
port:readPort(values.port,8000)
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
if(command==='targets'){
|
|
315
|
+
noExtraPositionals(command,positionals);
|
|
316
|
+
return {};
|
|
317
|
+
}
|
|
318
|
+
if(command==='update-check'){
|
|
319
|
+
noExtraPositionals(command,positionals);
|
|
320
|
+
return {};
|
|
321
|
+
}
|
|
322
|
+
if(command==='repo'){
|
|
323
|
+
noExtraPositionals(command,positionals,1);
|
|
324
|
+
const action=positionals[0];
|
|
325
|
+
if(!['status','pull','push'].includes(action)){
|
|
326
|
+
usage('repo requires exactly one action: status, pull, or push.');
|
|
327
|
+
}
|
|
328
|
+
return {...common,action};
|
|
329
|
+
}
|
|
330
|
+
usage(`Unknown command: ${command}. Run ${CLI_NAME} --help for usage.`);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const NATIVE_REQUESTS=Object.freeze({
|
|
334
|
+
'windows-x64':Object.freeze({
|
|
335
|
+
platform:'windows',architecture:'x64',defaultFormat:'exe',formats:new Set(['exe']),
|
|
336
|
+
defaultSigning:'unsigned-local-test',defaultProfileId:null,
|
|
337
|
+
signingModes:new Set(['unsigned-local-test'])
|
|
338
|
+
}),
|
|
339
|
+
'linux-x64':Object.freeze({
|
|
340
|
+
platform:'linux',architecture:'x64',defaultFormat:'deb',formats:new Set(['deb']),
|
|
341
|
+
defaultSigning:'unsigned-local-test',defaultProfileId:null,
|
|
342
|
+
signingModes:new Set(['unsigned-local-test'])
|
|
343
|
+
}),
|
|
344
|
+
'linux-arm64':Object.freeze({
|
|
345
|
+
platform:'linux',architecture:'arm64',defaultFormat:'deb',formats:new Set(['deb']),
|
|
346
|
+
defaultSigning:'unsigned-local-test',defaultProfileId:null,
|
|
347
|
+
signingModes:new Set(['unsigned-local-test'])
|
|
348
|
+
}),
|
|
349
|
+
'android-arm64':Object.freeze({
|
|
350
|
+
platform:'android',architecture:'arm64',defaultFormat:'apk',formats:new Set(['apk']),
|
|
351
|
+
defaultSigning:'development',defaultProfileId:'arcane-android-development-v1',
|
|
352
|
+
signingModes:new Set(['development'])
|
|
353
|
+
})
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
function portableRequestDefinition(){
|
|
357
|
+
const platform=process.platform==='win32'?'windows':process.platform;
|
|
358
|
+
const architecture=process.arch==='x64'?'x64':process.arch==='arm64'?'arm64':process.arch;
|
|
359
|
+
if(!['windows','linux'].includes(platform)||!['x64','arm64'].includes(architecture)){
|
|
360
|
+
throw new ArcaneError(
|
|
361
|
+
ERROR_CODES.targetUnavailable,
|
|
362
|
+
`The portable native provider does not support ${process.platform}/${process.arch}.`
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
return {
|
|
366
|
+
platform,
|
|
367
|
+
architecture,
|
|
368
|
+
defaultFormat:'portable',
|
|
369
|
+
formats:new Set(['portable']),
|
|
370
|
+
defaultSigning:'unsigned-local-test',
|
|
371
|
+
defaultProfileId:null,
|
|
372
|
+
signingModes:new Set(['unsigned-local-test'])
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export function createNativeTargetRequest({target,format,signing}={}){
|
|
377
|
+
const definition=target==='portable'?portableRequestDefinition():NATIVE_REQUESTS[target];
|
|
378
|
+
if(!definition){
|
|
379
|
+
usage(`Target ${String(target)} is not a registered native target.`);
|
|
380
|
+
}
|
|
381
|
+
const selectedFormat=format??definition.defaultFormat;
|
|
382
|
+
if(!definition.formats.has(selectedFormat)){
|
|
383
|
+
usage(
|
|
384
|
+
`Target ${target} does not support --format ${String(selectedFormat)}. `
|
|
385
|
+
+`Expected ${[...definition.formats].join(', ')}.`
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
const signingMode=signing??definition.defaultSigning;
|
|
389
|
+
if(!definition.signingModes.has(signingMode)){
|
|
390
|
+
usage(
|
|
391
|
+
`Target ${target} does not support --signing ${String(signingMode)}. `
|
|
392
|
+
+`Expected ${[...definition.signingModes].join(', ')}.`
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
return Object.freeze({
|
|
396
|
+
target,
|
|
397
|
+
platform:definition.platform,
|
|
398
|
+
architecture:definition.architecture,
|
|
399
|
+
format:selectedFormat,
|
|
400
|
+
signing:Object.freeze({mode:signingMode,profileId:definition.defaultProfileId})
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
async function pairNativeProvider(command,options,loadProvider,{signal,onEvent}={}){
|
|
405
|
+
const nativeOperation=(['build','run'].includes(command)&&options.target!=='browser')
|
|
406
|
+
||command==='native-doctor'
|
|
407
|
+
||command==='native-prepare';
|
|
408
|
+
if(!nativeOperation)return options;
|
|
409
|
+
if(options.target==='browser'){
|
|
410
|
+
usage(`${command} requires one native target.`);
|
|
411
|
+
}
|
|
412
|
+
const targetRequest=createNativeTargetRequest(options);
|
|
413
|
+
if(!options.arcaneRoot){
|
|
414
|
+
usage(`${command} for target ${options.target} requires --arcane-root <directory>.`);
|
|
415
|
+
}
|
|
416
|
+
const loaded=await loadProvider({
|
|
417
|
+
arcaneRoot:options.arcaneRoot,
|
|
418
|
+
target:options.target,
|
|
419
|
+
signal,
|
|
420
|
+
onEvent
|
|
421
|
+
});
|
|
422
|
+
return {
|
|
423
|
+
...options,
|
|
424
|
+
nativeBuilder:loaded.nativeBuilder,
|
|
425
|
+
providerGeneration:loaded.providerGeneration,
|
|
426
|
+
toolchainRoot:loaded.toolchainRoot,
|
|
427
|
+
targetRequest
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function commandFromArgs(args){
|
|
432
|
+
if(args.includes('--help')||args.includes('-h'))return 'help';
|
|
433
|
+
if(args.includes('--version')||args.includes('-v'))return 'version';
|
|
434
|
+
for(let index=0;index<args.length;index+=1){
|
|
435
|
+
const argument=args[index];
|
|
436
|
+
if(!argument.startsWith('-')){
|
|
437
|
+
return argument;
|
|
438
|
+
}
|
|
439
|
+
const equal=argument.indexOf('=');
|
|
440
|
+
const name=normalizeOptionName(equal===-1?argument:argument.slice(0,equal));
|
|
441
|
+
if(equal===-1&&VALUE_OPTIONS.has(name)){
|
|
442
|
+
index+=1;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return 'help';
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function serverSummary(result){
|
|
449
|
+
return {
|
|
450
|
+
target:result.target??'browser',
|
|
451
|
+
mode:result.mode,
|
|
452
|
+
appId:result.appId,
|
|
453
|
+
host:result.host,
|
|
454
|
+
port:result.port,
|
|
455
|
+
url:result.url,
|
|
456
|
+
...(result.verified?{verified:result.verified}:{})
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
async function waitForServer(result,signal,reporter){
|
|
461
|
+
reporter.emit('server.ready',serverSummary(result),`Development server ready at ${result.url}`);
|
|
462
|
+
if(result.lifecycle&&typeof result.lifecycle.then==='function'){
|
|
463
|
+
const abort=()=>{
|
|
464
|
+
void Promise.resolve().then(()=>result.close?.()).catch(()=>{});
|
|
465
|
+
};
|
|
466
|
+
signal.addEventListener('abort',abort,{once:true});
|
|
467
|
+
if(signal.aborted){
|
|
468
|
+
abort();
|
|
469
|
+
}
|
|
470
|
+
try{
|
|
471
|
+
await result.lifecycle;
|
|
472
|
+
}finally{
|
|
473
|
+
signal.removeEventListener('abort',abort);
|
|
474
|
+
}
|
|
475
|
+
}else{
|
|
476
|
+
await new Promise((resolve,reject)=>{
|
|
477
|
+
let settled=false;
|
|
478
|
+
const done=()=>{
|
|
479
|
+
if(settled)return;
|
|
480
|
+
settled=true;
|
|
481
|
+
signal.removeEventListener('abort',abort);
|
|
482
|
+
resolve();
|
|
483
|
+
};
|
|
484
|
+
const abort=()=>{
|
|
485
|
+
Promise.resolve(result.close?.()).then(done,reject);
|
|
486
|
+
};
|
|
487
|
+
signal.addEventListener('abort',abort,{once:true});
|
|
488
|
+
result.server?.once?.('close',done);
|
|
489
|
+
if(signal.aborted)abort();
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
if(signal.aborted){
|
|
493
|
+
throw new ArcaneError(ERROR_CODES.cancelled,'The Arcane server was stopped.',{
|
|
494
|
+
cause:signal.reason,
|
|
495
|
+
exitCode:130
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
return serverSummary(result);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
export async function runCli(argv=process.argv.slice(2),{
|
|
502
|
+
cwd=process.cwd(),
|
|
503
|
+
stdout=process.stdout,
|
|
504
|
+
stderr=process.stderr,
|
|
505
|
+
execute=executeOperation,
|
|
506
|
+
loadNativeProvider=loadArcaneNativeProvider,
|
|
507
|
+
controller=new AbortController()
|
|
508
|
+
}={}){
|
|
509
|
+
let reporter;
|
|
510
|
+
let command='help';
|
|
511
|
+
const onSignal=()=>controller.abort(new Error('Interrupted'));
|
|
512
|
+
try{
|
|
513
|
+
const extracted=extractOutput([...argv]);
|
|
514
|
+
command=commandFromArgs(extracted.remaining);
|
|
515
|
+
reporter=createReporter({command,output:extracted.output,stdout,stderr});
|
|
516
|
+
reporter.accept({argv:extracted.remaining});
|
|
517
|
+
process.once('SIGINT',onSignal);
|
|
518
|
+
process.once('SIGTERM',onSignal);
|
|
519
|
+
|
|
520
|
+
const parsed=parseCliArguments(extracted.remaining);
|
|
521
|
+
if(command==='help'||parsed.flags.has('help')){
|
|
522
|
+
reporter.complete(HELP_TEXT);
|
|
523
|
+
return 0;
|
|
524
|
+
}
|
|
525
|
+
if(command==='version'||parsed.flags.has('version')){
|
|
526
|
+
reporter.complete(SDK_VERSION);
|
|
527
|
+
return 0;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
const options=await pairNativeProvider(
|
|
531
|
+
command,
|
|
532
|
+
operationOptions(command,parsed,cwd),
|
|
533
|
+
loadNativeProvider,
|
|
534
|
+
{signal:controller.signal,onEvent:event=>reporter.forward(event)}
|
|
535
|
+
);
|
|
536
|
+
const result=await execute(command,{
|
|
537
|
+
...options,
|
|
538
|
+
signal:controller.signal,
|
|
539
|
+
onEvent:event=>reporter.forward(event)
|
|
540
|
+
});
|
|
541
|
+
const finalResult=(command==='dev'||(command==='run'&&(options.target??'browser')==='browser'))
|
|
542
|
+
?await waitForServer(result,controller.signal,reporter)
|
|
543
|
+
:result;
|
|
544
|
+
reporter.complete(finalResult);
|
|
545
|
+
return 0;
|
|
546
|
+
}catch(error){
|
|
547
|
+
const normalized=normalizeError(error);
|
|
548
|
+
if(!reporter){
|
|
549
|
+
stderr.write(`${normalized.code}: ${normalized.message}\n`);
|
|
550
|
+
}else{
|
|
551
|
+
if(!reporter.accepted){
|
|
552
|
+
reporter.accept();
|
|
553
|
+
}
|
|
554
|
+
reporter.reject(normalized);
|
|
555
|
+
}
|
|
556
|
+
return normalized.exitCode;
|
|
557
|
+
}finally{
|
|
558
|
+
process.removeListener('SIGINT',onSignal);
|
|
559
|
+
process.removeListener('SIGTERM',onSignal);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import {fileURLToPath} from 'node:url';
|
|
3
|
+
import packageDocument from '../package.json' with {type:'json'};
|
|
4
|
+
|
|
5
|
+
if(packageDocument.name!=='arcane-os'||typeof packageDocument.version!=='string'
|
|
6
|
+
||!/^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?$/u.test(packageDocument.version)){
|
|
7
|
+
throw new Error('The Arcane SDK package identity is invalid.');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const SDK_NAME=packageDocument.name;
|
|
11
|
+
export const CLI_NAME='arcane';
|
|
12
|
+
export const SDK_VERSION=packageDocument.version;
|
|
13
|
+
export const ARCANE_PROTOCOL='arcane/1';
|
|
14
|
+
export const CLI_EVENT_PROTOCOL='arcane-cli-events/1';
|
|
15
|
+
export const TARGET_ADAPTER_PROTOCOL='arcane-target-adapter/1';
|
|
16
|
+
export const ARCANE_MACHINE_BUNDLE_VERSION='0.8.12';
|
|
17
|
+
export const ARCANE_UPSTREAM_COMMIT='567ad110bf57a1c2d4a3daa22ae93716cc5f4d7e';
|
|
18
|
+
export const ARCANE_UPSTREAM_REPOSITORY='https://github.com/TheWizardNexus/ARCANE-OS.git';
|
|
19
|
+
|
|
20
|
+
export const SDK_ROOT=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..');
|
|
21
|
+
export const RUNTIME_ROOT=path.join(SDK_ROOT,'runtime');
|
|
22
|
+
|
|
23
|
+
export const OUTPUT_MODES=Object.freeze(['human','json','ndjson']);
|
|
24
|
+
export const TARGET_IDS=Object.freeze([
|
|
25
|
+
'browser',
|
|
26
|
+
'portable',
|
|
27
|
+
'windows-x64',
|
|
28
|
+
'linux-x64',
|
|
29
|
+
'linux-arm64',
|
|
30
|
+
'android-arm64'
|
|
31
|
+
]);
|