create-aura-appliance 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +42 -0
  2. package/dist/bin.d.ts +3 -0
  3. package/dist/bin.d.ts.map +1 -0
  4. package/dist/bin.js +5 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/cli.d.ts +30 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +200 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/config-file.d.ts +12 -0
  11. package/dist/config-file.d.ts.map +1 -0
  12. package/dist/config-file.js +50 -0
  13. package/dist/config-file.js.map +1 -0
  14. package/dist/i18n.d.ts +7 -0
  15. package/dist/i18n.d.ts.map +1 -0
  16. package/dist/i18n.js +10 -0
  17. package/dist/i18n.js.map +1 -0
  18. package/dist/local.d.ts +7 -0
  19. package/dist/local.d.ts.map +1 -0
  20. package/dist/local.js +110 -0
  21. package/dist/local.js.map +1 -0
  22. package/dist/messages/en.d.ts +61 -0
  23. package/dist/messages/en.d.ts.map +1 -0
  24. package/dist/messages/en.js +61 -0
  25. package/dist/messages/en.js.map +1 -0
  26. package/dist/messages/it.d.ts +3 -0
  27. package/dist/messages/it.d.ts.map +1 -0
  28. package/dist/messages/it.js +61 -0
  29. package/dist/messages/it.js.map +1 -0
  30. package/dist/modelroute.d.ts +20 -0
  31. package/dist/modelroute.d.ts.map +1 -0
  32. package/dist/modelroute.js +67 -0
  33. package/dist/modelroute.js.map +1 -0
  34. package/dist/preflight-floors.d.ts +4 -0
  35. package/dist/preflight-floors.d.ts.map +1 -0
  36. package/dist/preflight-floors.js +9 -0
  37. package/dist/preflight-floors.js.map +1 -0
  38. package/dist/preflight.d.ts +8 -0
  39. package/dist/preflight.d.ts.map +1 -0
  40. package/dist/preflight.js +53 -0
  41. package/dist/preflight.js.map +1 -0
  42. package/dist/process.d.ts +39 -0
  43. package/dist/process.d.ts.map +1 -0
  44. package/dist/process.js +115 -0
  45. package/dist/process.js.map +1 -0
  46. package/dist/prompts.d.ts +37 -0
  47. package/dist/prompts.d.ts.map +1 -0
  48. package/dist/prompts.js +123 -0
  49. package/dist/prompts.js.map +1 -0
  50. package/dist/remote.d.ts +10 -0
  51. package/dist/remote.d.ts.map +1 -0
  52. package/dist/remote.js +268 -0
  53. package/dist/remote.js.map +1 -0
  54. package/dist/types.d.ts +23 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +2 -0
  57. package/dist/types.js.map +1 -0
  58. package/dist/validation.d.ts +12 -0
  59. package/dist/validation.d.ts.map +1 -0
  60. package/dist/validation.js +88 -0
  61. package/dist/validation.js.map +1 -0
  62. package/install-appliance.run +908 -1
  63. package/package.json +45 -0
package/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # create-aura-appliance
2
+
3
+ Interactive installer for an [Aura](https://github.com/chetto1983/Aura) appliance — on this
4
+ machine, or on another one over SSH.
5
+
6
+ ```bash
7
+ npx create-aura-appliance # asks whether to install here or remotely
8
+ npx create-aura-appliance --mode remote
9
+ ```
10
+
11
+ ## What it does
12
+
13
+ The wizard collects the target and the model route, writes an installer config, and then
14
+ runs the appliance installer. The installer is **carried inside this package** as a
15
+ self-extracting archive: nothing is fetched from a source host at install time, so the
16
+ payload you run is the payload npm delivered.
17
+
18
+ It probes the machine that will actually run Aura, not the one you are typing on — over SSH
19
+ in remote mode. That is what decides the embedding runtime: with an NVIDIA GPU it selects
20
+ the CUDA llama.cpp image and offloads every layer, without one it selects the CPU image and
21
+ sets `AURA_EMBED_NGL=0`. You are not asked.
22
+
23
+ Installs made from this package track the `edge` channel: the appliance images carry the
24
+ moving `:edge` tag, Docker is set to always re-pull them, and a systemd timer applies new
25
+ images as they are published — so the box keeps itself current without you returning to it.
26
+
27
+ ## Requirements
28
+
29
+ On the machine running this wizard: Node.js >= 22.13.
30
+
31
+ On the target: Linux (local installs may also be macOS), `x86_64` or `arm64`, at least
32
+ 4 CPU cores, 14 GiB of usable RAM, 20 GiB of free disk, `sudo`, `curl` and `openssl`, and
33
+ network reach to `ghcr.io`, `get.docker.com` and `huggingface.co`. The hardware floors are
34
+ checked before anything is copied, and again by the installer itself.
35
+
36
+ The RAM floor is measured against `MemTotal`, which is installed RAM minus firmware, kernel
37
+ and integrated-GPU reservations — a 16 GB machine reports well under 16 GiB, which is why
38
+ the floor is where it is.
39
+
40
+ ## License
41
+
42
+ MIT
package/dist/bin.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
package/dist/bin.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from './cli.js';
3
+ const exitCode = await runCli(process.argv.slice(2));
4
+ process.exitCode = exitCode;
5
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ import type { TemporaryFile } from './config-file.js';
2
+ import { createTranslator } from './i18n.js';
3
+ import type { MessageKey } from './i18n.js';
4
+ import type { PromptPort, TargetSelection } from './prompts.js';
5
+ import type { CommandRunner } from './process.js';
6
+ import type { InstallMode, InstallSettings, RemoteTarget } from './types.js';
7
+ type Writer = (message: string) => void;
8
+ type TargetCollector = (prompt: PromptPort, t: ReturnType<typeof createTranslator>, requestedMode?: InstallMode) => Promise<TargetSelection>;
9
+ type SettingsCollector = (prompt: PromptPort, t: ReturnType<typeof createTranslator>, installDir: string, probeRunner: CommandRunner | undefined) => Promise<InstallSettings | null>;
10
+ type ConfigCreator = (settings: InstallSettings) => Promise<TemporaryFile>;
11
+ type LocalInstaller = (runner: CommandRunner, config: TemporaryFile, settings: InstallSettings) => Promise<void>;
12
+ type RemoteInstaller = (runner: CommandRunner, target: RemoteTarget, config: TemporaryFile, settings: InstallSettings) => Promise<void>;
13
+ export interface CliDependencies {
14
+ locale?: string;
15
+ version?: string;
16
+ platform?: NodeJS.Platform;
17
+ prompt?: PromptPort;
18
+ runner?: CommandRunner;
19
+ collectTarget?: TargetCollector;
20
+ collectSettings?: SettingsCollector;
21
+ createConfig?: ConfigCreator;
22
+ installLocal?: LocalInstaller;
23
+ installRemote?: RemoteInstaller;
24
+ write?: Writer;
25
+ writeError?: Writer;
26
+ }
27
+ export declare const TRANSLATED_ERROR_CODES: Readonly<Record<string, MessageKey>>;
28
+ export declare function runCli(argv: readonly string[], dependencies?: CliDependencies): Promise<number>;
29
+ export {};
30
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAgB,MAAM,WAAW,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAG5C,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG7E,KAAK,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AACxC,KAAK,eAAe,GAAG,CACrB,MAAM,EAAE,UAAU,EAClB,CAAC,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EACtC,aAAa,CAAC,EAAE,WAAW,KACxB,OAAO,CAAC,eAAe,CAAC,CAAC;AAC9B,KAAK,iBAAiB,GAAG,CACvB,MAAM,EAAE,UAAU,EAClB,CAAC,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EACtC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,aAAa,GAAG,SAAS,KACnC,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;AACrC,KAAK,aAAa,GAAG,CAAC,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;AAC3E,KAAK,cAAc,GAAG,CACpB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,eAAe,KACtB,OAAO,CAAC,IAAI,CAAC,CAAC;AACnB,KAAK,eAAe,GAAG,CACrB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,eAAe,KACtB,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IAIjB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC,eAAe,CAAC,EAAE,iBAAiB,CAAC;IACpC,YAAY,CAAC,EAAE,aAAa,CAAC;IAK7B,YAAY,CAAC,EAAE,cAAc,CAAC;IAC9B,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAYD,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAsBvE,CAAC;AA0CF,wBAAsB,MAAM,CAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,YAAY,GAAE,eAAoB,GACjC,OAAO,CAAC,MAAM,CAAC,CAiIjB"}
package/dist/cli.js ADDED
@@ -0,0 +1,200 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { createTemporaryInstallConfig } from './config-file.js';
3
+ import { createTranslator, detectLocale } from './i18n.js';
4
+ import { installLocal, preflightLocal, resolveInstallerArtifact } from './local.js';
5
+ import { collectSettings, collectTarget, inquirerPrompt } from './prompts.js';
6
+ import { ProcessRunner } from './process.js';
7
+ import { createSshProbeRunner, installRemote, preflightRemote } from './remote.js';
8
+ import { ValidationError } from './validation.js';
9
+ // Exported so cli.test.ts can assert, in one place, that every mapped code resolves to a
10
+ // real message in both catalogues and that every preflight.ts error code is mapped (F3,
11
+ // review round 1: six of these had neither a map entry nor a catalogue key, so
12
+ // errorMessage() fell through to the raw thrown string and an operator on an unsupported
13
+ // architecture read "unsupportedArchitecture:riscv64" literally).
14
+ export const TRANSLATED_ERROR_CODES = {
15
+ invalidHost: 'invalidHost',
16
+ invalidPort: 'invalidPort',
17
+ invalidUsername: 'invalidUsername',
18
+ invalidInstallDir: 'invalidInstallDir',
19
+ invalidBaseUrl: 'invalidBaseUrl',
20
+ invalidModelId: 'invalidModelId',
21
+ unsupportedArchitecture: 'unsupportedArchitecture',
22
+ invalidDiskAvailability: 'invalidDiskAvailability',
23
+ insufficientDiskSpace: 'insufficientDiskSpace',
24
+ invalidCpuCount: 'invalidCpuCount',
25
+ insufficientCpuCores: 'insufficientCpuCores',
26
+ invalidMemoryAvailability: 'invalidMemoryAvailability',
27
+ insufficientMemory: 'insufficientMemory',
28
+ cleanupFailed: 'cleanupFailed',
29
+ // Task 6: local.ts's preflightLocal now throws these, and installLocal's real default
30
+ // (below) throws the artifact one when Task 7's bundled asset is absent.
31
+ unsupportedLocalPlatform: 'unsupportedLocalPlatform',
32
+ installerArtifactMissing: 'installerArtifactMissing',
33
+ // Task 6: remote.ts's preflightRemote now throws these two.
34
+ invalidRemotePreflightOutput: 'invalidRemotePreflightOutput',
35
+ unsupportedRemoteClientPlatform: 'unsupportedRemoteClientPlatform',
36
+ };
37
+ function parseArguments(argv) {
38
+ if (argv.length === 0)
39
+ return { action: 'install' };
40
+ if (argv.length === 1 && argv[0] === '--help')
41
+ return { action: 'help' };
42
+ if (argv.length === 1 && argv[0] === '--version')
43
+ return { action: 'version' };
44
+ if (argv.length === 2
45
+ && argv[0] === '--mode'
46
+ && (argv[1] === 'local' || argv[1] === 'remote')) {
47
+ return { action: 'install', mode: argv[1] };
48
+ }
49
+ return { action: 'invalid' };
50
+ }
51
+ function packageVersion() {
52
+ const contents = readFileSync(new URL('../package.json', import.meta.url), 'utf8');
53
+ const parsed = JSON.parse(contents);
54
+ if (typeof parsed !== 'object'
55
+ || parsed === null
56
+ || !('version' in parsed)
57
+ || typeof parsed.version !== 'string') {
58
+ throw new Error('invalidPackageVersion');
59
+ }
60
+ return parsed.version;
61
+ }
62
+ function errorMessage(error, t) {
63
+ if (!(error instanceof Error))
64
+ return String(error);
65
+ const rawCode = error instanceof ValidationError ? error.code : error.message;
66
+ const code = rawCode.split(':', 1)[0] ?? rawCode;
67
+ const key = TRANSLATED_ERROR_CODES[code];
68
+ return key ? t(key) : error.message;
69
+ }
70
+ function isPromptCancellation(error) {
71
+ return error instanceof Error && error.name === 'ExitPromptError';
72
+ }
73
+ export async function runCli(argv, dependencies = {}) {
74
+ const locale = detectLocale(dependencies.locale ?? Intl.DateTimeFormat().resolvedOptions().locale);
75
+ const t = createTranslator(locale);
76
+ const write = dependencies.write ?? ((message) => process.stdout.write(`${message}\n`));
77
+ const writeError = dependencies.writeError ?? ((message) => process.stderr.write(`${message}\n`));
78
+ const parsed = parseArguments(argv);
79
+ if (parsed.action === 'invalid') {
80
+ writeError(t('usageError'));
81
+ return 2;
82
+ }
83
+ if (parsed.action === 'help') {
84
+ write([
85
+ t('cliDescription'),
86
+ '',
87
+ t('helpUsage'),
88
+ t('helpMode'),
89
+ t('helpHelp'),
90
+ t('helpVersion'),
91
+ ].join('\n'));
92
+ return 0;
93
+ }
94
+ if (parsed.action === 'version') {
95
+ write(dependencies.version ?? packageVersion());
96
+ return 0;
97
+ }
98
+ const prompt = dependencies.prompt ?? inquirerPrompt;
99
+ const runner = dependencies.runner ?? new ProcessRunner();
100
+ const targetCollector = dependencies.collectTarget ?? collectTarget;
101
+ const settingsCollector = dependencies.collectSettings ?? collectSettings;
102
+ const configCreator = dependencies.createConfig ?? createTemporaryInstallConfig;
103
+ // R5/R6: the real installer runs the bundled makeself artifact (Task 7 packages it beside
104
+ // this module); resolving it here, once, keeps local.ts/remote.ts's own exported
105
+ // installLocal/installRemote matching the reference's ported (runner, artifact, config,
106
+ // settings) shape while cli.ts's injected defaults keep the 4-/5-arg shape the rest of this
107
+ // file already declares.
108
+ const localInstaller = dependencies.installLocal ?? (async (installRunner, installConfig, installSettings) => {
109
+ const artifact = await resolveInstallerArtifact();
110
+ await installLocal(installRunner, artifact, installConfig, installSettings);
111
+ });
112
+ const remoteInstaller = dependencies.installRemote ?? (async (installRunner, installTarget, installConfig, installSettings) => {
113
+ const artifact = await resolveInstallerArtifact();
114
+ // Matches the reference cli.ts's own default wiring: a best-effort cleanup failure is a
115
+ // warning, not a fatal error, and which of the two cleanup steps produced it does not
116
+ // change what the operator needs to do (re-run is safe either way) -- so one generic
117
+ // message covers both, exactly like cleanupWarning already does for the config file.
118
+ await installRemote(installRunner, installTarget, artifact, installConfig, installSettings, undefined, () => writeError(t('cleanupWarning')));
119
+ });
120
+ let config;
121
+ let operationError;
122
+ let installed = false;
123
+ try {
124
+ const target = await targetCollector(prompt, t, parsed.mode);
125
+ write(t('phasePreflight'));
126
+ // R1: the wizard runs on the operator's laptop, but in remote mode the install lands on
127
+ // a different machine. local mode passes the real runner -- the probed machine IS the
128
+ // target. R2 (Task 6, closing this out): remote mode used to pass undefined here --
129
+ // probing the laptop and presenting the answer as if it were the target's would have been
130
+ // worse than not probing -- but now wraps the runner over SSH (createSshProbeRunner) so
131
+ // collectSettings's GPU/Ollama probes reach the real target. Nothing in collectSettings or
132
+ // modelroute.ts needed to change: the seam was built for exactly this swap.
133
+ let probeRunner;
134
+ if (target.mode === 'remote') {
135
+ if (!target.remote)
136
+ throw new Error('invalidRemoteTarget');
137
+ const preflight = await preflightRemote(runner, target.remote, target.installDir, dependencies.platform);
138
+ write(t('remoteTargetSummary', {
139
+ user: target.remote.username,
140
+ host: target.remote.host,
141
+ port: target.remote.port,
142
+ }));
143
+ if (preflight.existingInstall)
144
+ write(t('existingInstall'));
145
+ probeRunner = createSshProbeRunner(runner, target.remote);
146
+ }
147
+ else {
148
+ // R1 (carried Task 5 debt, closed): the hardware/command/host gate that used to live
149
+ // here as a small local-only runLocalPreflight now lives in local.ts's preflightLocal,
150
+ // merged with the REQUIRED_COMMANDS/REQUIRED_HOSTS/existing-install checks Task 6 ports
151
+ // from the reference -- one gate, not two copies of it.
152
+ const preflight = await preflightLocal(runner, target.installDir, dependencies.platform);
153
+ write(t('localTargetSummary'));
154
+ if (preflight.existingInstall)
155
+ write(t('existingInstall'));
156
+ probeRunner = runner;
157
+ }
158
+ const settings = await settingsCollector(prompt, t, target.installDir, probeRunner);
159
+ if (settings === null) {
160
+ write(t('cancelled'));
161
+ return 0;
162
+ }
163
+ config = await configCreator(settings);
164
+ write(t('phaseInstall'));
165
+ if (target.mode === 'remote') {
166
+ if (!target.remote)
167
+ throw new Error('invalidRemoteTarget');
168
+ await remoteInstaller(runner, target.remote, config, settings);
169
+ }
170
+ else {
171
+ await localInstaller(runner, config, settings);
172
+ }
173
+ installed = true;
174
+ }
175
+ catch (error) {
176
+ if (isPromptCancellation(error) && !config) {
177
+ write(t('cancelled'));
178
+ return 0;
179
+ }
180
+ operationError = error;
181
+ }
182
+ if (config) {
183
+ write(t('phaseCleanup'));
184
+ try {
185
+ await config.cleanup();
186
+ }
187
+ catch {
188
+ writeError(t('cleanupWarning'));
189
+ operationError ??= new Error('cleanupFailed');
190
+ }
191
+ }
192
+ if (operationError !== undefined) {
193
+ writeError(errorMessage(operationError, t));
194
+ return 1;
195
+ }
196
+ if (installed)
197
+ write(t('installComplete'));
198
+ return 0;
199
+ }
200
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { InstallSettings } from './types.js';
2
+ export interface TemporaryFile {
3
+ path: string;
4
+ cleanup: () => Promise<void>;
5
+ }
6
+ export interface TemporaryInstallConfig extends TemporaryFile {
7
+ path: string;
8
+ directory: string;
9
+ }
10
+ export declare function serializeInstallConfig(settings: InstallSettings): string;
11
+ export declare function createTemporaryInstallConfig(settings: InstallSettings, tempRoot?: string): Promise<TemporaryInstallConfig>;
12
+ //# sourceMappingURL=config-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-file.d.ts","sourceRoot":"","sources":["../src/config-file.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAaD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAgBxE;AAED,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,eAAe,EACzB,QAAQ,SAAW,GAClB,OAAO,CAAC,sBAAsB,CAAC,CAkBjC"}
@@ -0,0 +1,50 @@
1
+ import { chmod, mkdtemp, rm, writeFile } from 'node:fs/promises';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { assertNoLineBreak } from './validation.js';
5
+ // install.sh's parse_install_config decodes every *_base64 value and only then re-checks
6
+ // it for a line break (scripts/install.sh:296-304), because a newline that survived would
7
+ // make set_env_value write a second .env line -- install.sh's own reader takes the first
8
+ // occurrence, docker compose takes the last, so the installer and the running appliance
9
+ // would end up trusting different values. Asserting here catches the same fault on the
10
+ // machine running the wizard, before the config file crosses to the install target.
11
+ function encode(value) {
12
+ assertNoLineBreak(value, 'invalidConfigValue');
13
+ return Buffer.from(value, 'utf8').toString('base64');
14
+ }
15
+ export function serializeInstallConfig(settings) {
16
+ return [
17
+ 'format=1',
18
+ `install_dir_base64=${encode(settings.installDir)}`,
19
+ // appliance and gvisor are the two install.sh reads RAW; base64-ing them would make
20
+ // its literal `= "true"` comparison false and silently produce a non-appliance install.
21
+ `appliance=${settings.appliance ? 'true' : 'false'}`,
22
+ `gvisor=${settings.gvisor ? 'true' : 'false'}`,
23
+ `llm_provider_base64=${encode(settings.llmProvider)}`,
24
+ `llm_base_url_base64=${encode(settings.llmBaseUrl)}`,
25
+ `llm_model_base64=${encode(settings.llmModel)}`,
26
+ `openrouter_api_key_base64=${encode(settings.openrouterApiKey ?? '')}`,
27
+ `embed_image_base64=${encode(settings.embedImage)}`,
28
+ `embed_ngl_base64=${encode(settings.embedNgl)}`,
29
+ '',
30
+ ].join('\n');
31
+ }
32
+ export async function createTemporaryInstallConfig(settings, tempRoot = tmpdir()) {
33
+ const directory = await mkdtemp(join(tempRoot, 'create-aura-'));
34
+ const path = join(directory, 'install.conf');
35
+ try {
36
+ await chmod(directory, 0o700);
37
+ await writeFile(path, serializeInstallConfig(settings), { encoding: 'utf8', mode: 0o600 });
38
+ await chmod(path, 0o600);
39
+ }
40
+ catch (error) {
41
+ await rm(directory, { recursive: true, force: true });
42
+ throw error;
43
+ }
44
+ return {
45
+ path,
46
+ directory,
47
+ cleanup: async () => rm(directory, { recursive: true, force: true }),
48
+ };
49
+ }
50
+ //# sourceMappingURL=config-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-file.js","sourceRoot":"","sources":["../src/config-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAYpD,yFAAyF;AACzF,0FAA0F;AAC1F,yFAAyF;AACzF,wFAAwF;AACxF,uFAAuF;AACvF,oFAAoF;AACpF,SAAS,MAAM,CAAC,KAAa;IAC3B,iBAAiB,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAyB;IAC9D,OAAO;QACL,UAAU;QACV,sBAAsB,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;QACnD,oFAAoF;QACpF,wFAAwF;QACxF,aAAa,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE;QACpD,UAAU,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE;QAC9C,uBAAuB,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrD,uBAAuB,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;QACpD,oBAAoB,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAC/C,6BAA6B,MAAM,CAAC,QAAQ,CAAC,gBAAgB,IAAI,EAAE,CAAC,EAAE;QACtE,sBAAsB,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;QACnD,oBAAoB,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAC/C,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,QAAyB,EACzB,QAAQ,GAAG,MAAM,EAAE;IAEnB,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAE7C,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC9B,MAAM,SAAS,CAAC,IAAI,EAAE,sBAAsB,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3F,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,MAAM,KAAK,CAAC;IACd,CAAC;IAED,OAAO;QACL,IAAI;QACJ,SAAS;QACT,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;KACrE,CAAC;AACJ,CAAC"}
package/dist/i18n.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { en } from './messages/en.js';
2
+ export type Locale = 'en' | 'it';
3
+ export type MessageKey = keyof typeof en;
4
+ export type Translator = (key: MessageKey, values?: Readonly<Record<string, string | number>>) => string;
5
+ export declare function detectLocale(locale?: string): Locale;
6
+ export declare function createTranslator(locale: Locale): Translator;
7
+ //# sourceMappingURL=i18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAGtC,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;AACjC,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,EAAE,CAAC;AACzC,MAAM,MAAM,UAAU,GAAG,CACvB,GAAG,EAAE,UAAU,EACf,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,KAC/C,MAAM,CAAC;AAIZ,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAK3D"}
package/dist/i18n.js ADDED
@@ -0,0 +1,10 @@
1
+ import { en } from './messages/en.js';
2
+ import { it } from './messages/it.js';
3
+ const catalogs = { en, it };
4
+ export function detectLocale(locale) {
5
+ return locale?.replace('_', '-').toLowerCase().startsWith('it') ? 'it' : 'en';
6
+ }
7
+ export function createTranslator(locale) {
8
+ return (key, values = {}) => catalogs[locale][key].replace(/\{([a-zA-Z][a-zA-Z0-9]*)\}/g, (token, name) => name in values ? String(values[name]) : token);
9
+ }
10
+ //# sourceMappingURL=i18n.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAStC,MAAM,QAAQ,GAA+C,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;AAExE,MAAM,UAAU,YAAY,CAAC,MAAe;IAC1C,OAAO,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CACxD,6BAA6B,EAC7B,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CACvE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { TemporaryFile } from './config-file.js';
2
+ import type { CommandRunner } from './process.js';
3
+ import type { InstallSettings, PreflightResult } from './types.js';
4
+ export declare function preflightLocal(runner: CommandRunner, installDir: string, platform?: NodeJS.Platform): Promise<PreflightResult>;
5
+ export declare function resolveInstallerArtifact(): Promise<TemporaryFile>;
6
+ export declare function installLocal(runner: CommandRunner, artifact: TemporaryFile, config: TemporaryFile, settings: InstallSettings): Promise<void>;
7
+ //# sourceMappingURL=local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../src/local.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAkDnE,wBAAsB,cAAc,CAClC,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,OAAO,CAAC,eAAe,CAAC,CA0C1B;AAQD,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,aAAa,CAAC,CAQvE;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CAUf"}
package/dist/local.js ADDED
@@ -0,0 +1,110 @@
1
+ import { access } from 'node:fs/promises';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { assertSufficientCpuCores, assertSufficientDiskSpace, assertSufficientMemory, normalizeArchitecture, } from './preflight.js';
4
+ // R4 (Task 6 controller ruling): derived from scripts/install.sh, not copied from the
5
+ // reference's ['apt-get', 'systemctl', 'sudo', 'curl'].
6
+ // sudo -- installLocal below always runs the artifact as `sudo bash ...`; if the sudo
7
+ // binary itself is missing, that top-level command fails outright, and this
8
+ // check catches it before a secret-bearing config file is even written.
9
+ // curl -- install.sh's ensure_embed_model (scripts/install.sh:371-395) sends an
10
+ // unconditional HEAD request to size the embedding model on EVERY run, model
11
+ // already present or not; curl is never optional.
12
+ // openssl -- write_env_if_missing and ensure_internal_env_secrets (scripts/install.sh:465,
13
+ // 536) each call `command -v openssl` themselves and exit 1 if it is absent, on
14
+ // a fresh install AND on every re-run.
15
+ // apt-get and systemctl are dropped: apt-get would refuse the macOS target install.sh:216-226
16
+ // explicitly supports via Docker Desktop, and systemctl only gates --appliance
17
+ // (scripts/install.sh:691-719), a choice collectSettings makes AFTER this preflight runs --
18
+ // gating on it here would refuse a machine a non-appliance install would have accepted.
19
+ // docker itself is deliberately NOT required: install_docker (scripts/install.sh:198-236)
20
+ // self-installs it via curl+sudo on Linux when absent, so requiring it up front would refuse
21
+ // a fresh box the installer would have provisioned on its own.
22
+ const REQUIRED_COMMANDS = ['sudo', 'curl', 'openssl'];
23
+ // R3 (Task 6 controller ruling): raw.githubusercontent.com comes OUT -- the npm package
24
+ // carries the payload (spec decision 5), so install.sh's download_file reads
25
+ // AURA_PAYLOAD_DIR and never touches RAW_BASE; requiring that host would re-assert a trust
26
+ // path this design deliberately removed. huggingface.co goes IN: install.sh:357 fetches
27
+ // embeddinggemma-300M-Q8_0.gguf from there, the one pinned artifact in the whole product,
28
+ // and ensure_embed_model's HEAD probe against it is unconditional (see curl, above).
29
+ const REQUIRED_HOSTS = [
30
+ 'https://ghcr.io',
31
+ 'https://get.docker.com',
32
+ 'https://huggingface.co',
33
+ ];
34
+ // install.sh:126-135's ram_kib(): Linux reads /proc/meminfo's MemTotal (already KiB) directly;
35
+ // Darwin has no /proc, so it converts `sysctl -n hw.memsize` (bytes) to KiB; any other
36
+ // platform echoes 0, which then FAILS assertSufficientMemory's floor rather than skipping the
37
+ // gate -- install.sh refuses a machine it cannot measure, and this must too.
38
+ const RAM_KIB_SCRIPT = 'OS="$(uname -s)"; if [ "$OS" = "Linux" ] && [ -r /proc/meminfo ]; then '
39
+ + "awk '/MemTotal:/ {print $2}' /proc/meminfo; elif [ \"$OS\" = \"Darwin\" ]; then "
40
+ + 'bytes="$(sysctl -n hw.memsize 2>/dev/null || echo 0)"; echo $((bytes / 1024)); else echo 0; fi';
41
+ // install.sh:137-144's disk_free_kib(): the install directory does not exist yet on a first
42
+ // install, so it walks up to the nearest existing parent before measuring -- df on '/' when
43
+ // the real target is a separately-mounted /opt (the appliance default install dir is
44
+ // /opt/aura) would report free space on the wrong filesystem. $1 is the install dir, passed
45
+ // positionally: a throwaway program-name placeholder occupies $0.
46
+ const DISK_FREE_KIB_SCRIPT = 'probe="$1"; while [ ! -e "$probe" ] && [ "$probe" != "/" ]; do '
47
+ + 'probe="$(dirname "$probe")"; done; df -Pk "$probe" | awk \'NR==2 {print $4}\'';
48
+ export async function preflightLocal(runner, installDir, platform = process.platform) {
49
+ // install.sh:81-88, :216-230 supports Linux and macOS (via Docker Desktop); anything else
50
+ // has no install.sh path to run at all and belongs in remote mode instead.
51
+ if (platform !== 'linux' && platform !== 'darwin')
52
+ throw new Error('unsupportedLocalPlatform');
53
+ for (const command of REQUIRED_COMMANDS) {
54
+ await runner.run('sh', [
55
+ '-c',
56
+ 'command -v "$1" >/dev/null 2>&1',
57
+ 'create-aura',
58
+ command,
59
+ ]);
60
+ }
61
+ const architecture = normalizeArchitecture((await runner.run('uname', ['-m'])).stdout);
62
+ // install.sh:118-124's cpu_count() branches on OS only because getconf might be absent;
63
+ // it ships on every Linux distribution and on macOS, so this one call already covers both
64
+ // platforms without branching -- `nproc` would be Linux-only and refuse a Mac install.sh
65
+ // itself accepts.
66
+ assertSufficientCpuCores((await runner.run('getconf', ['_NPROCESSORS_ONLN'])).stdout);
67
+ assertSufficientMemory((await runner.run('sh', ['-c', RAM_KIB_SCRIPT])).stdout);
68
+ assertSufficientDiskSpace((await runner.run('sh', [
69
+ '-c',
70
+ DISK_FREE_KIB_SCRIPT,
71
+ 'create-aura',
72
+ installDir,
73
+ ])).stdout);
74
+ // install.sh writes compose.yaml (not docker-compose.yml) directly under INSTALL_DIR
75
+ // (scripts/install.sh:767); that is Aura's own re-run marker, not the reference's.
76
+ const existingInstall = (await runner.run('sh', [
77
+ '-c',
78
+ 'if test -f "$1/compose.yaml"; then printf "true\\n"; else printf "false\\n"; fi',
79
+ 'create-aura',
80
+ installDir,
81
+ ])).stdout.trim() === 'true';
82
+ for (const host of REQUIRED_HOSTS) {
83
+ await runner.run('curl', ['-fsS', '-o', '/dev/null', '-m', '10', host]);
84
+ }
85
+ return { architecture, existingInstall };
86
+ }
87
+ // R5 (Task 6 controller ruling): Task 7 packages packages/create-aura/install-appliance.run
88
+ // beside this module. Resolved via import.meta.url rather than a hardcoded relative path so
89
+ // it is correct BOTH from src/ under vitest and from dist/ when published -- both sit one
90
+ // level under the package root. Until Task 7 lands the file is genuinely absent here; this
91
+ // must fail with a clear, named error rather than let a missing artifact become a skipped
92
+ // step or (worse) a silent no-op install.
93
+ export async function resolveInstallerArtifact() {
94
+ const path = fileURLToPath(new URL('../install-appliance.run', import.meta.url));
95
+ try {
96
+ await access(path);
97
+ }
98
+ catch {
99
+ throw new Error('installerArtifactMissing');
100
+ }
101
+ return { path, cleanup: async () => { } };
102
+ }
103
+ export async function installLocal(runner, artifact, config, settings) {
104
+ // R6 (Task 6 controller ruling): makeself's runtime header parses argv against its OWN
105
+ // flag set before it execs the embedded script, so `artifact --config X` dies with
106
+ // "Unrecognized flag" and install.sh never runs. `--` tells the header to stop parsing and
107
+ // hand everything after it to install.sh untouched.
108
+ await runner.run('sudo', ['bash', artifact.path, '--', '--config', config.path], { redactions: [settings.openrouterApiKey] });
109
+ }
110
+ //# sourceMappingURL=local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../src/local.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ export declare const en: {
2
+ readonly cliDescription: "Install or update the Aura appliance, locally or over SSH";
3
+ readonly helpUsage: "Usage: create-aura [--mode local|remote] [--help] [--version]";
4
+ readonly helpMode: " --mode local|remote Skip only the installation mode question";
5
+ readonly helpHelp: " --help Show this help";
6
+ readonly helpVersion: " --version Show the package version";
7
+ readonly usageError: "Invalid arguments. Use --help to see the supported options.";
8
+ readonly modeQuestion: "Where do you want to install Aura?";
9
+ readonly modeLocal: "This Linux device";
10
+ readonly modeRemote: "A remote Linux device over SSH";
11
+ readonly remoteHost: "Target hostname or IP address";
12
+ readonly remotePort: "SSH port";
13
+ readonly remoteUsername: "SSH username";
14
+ readonly installDir: "Installation directory";
15
+ readonly confirmInstall: "Apply this installation?";
16
+ readonly existingInstall: "Existing installation detected; configuration and data will be preserved.";
17
+ readonly remoteTargetSummary: "Target: {user}@{host}:{port}";
18
+ readonly localTargetSummary: "Target: this Linux device";
19
+ readonly phasePreflight: "Preflight checks";
20
+ readonly phaseTransfer: "Transfer secure configuration";
21
+ readonly phaseInstall: "Install Aura";
22
+ readonly phaseCleanup: "Remove temporary files";
23
+ readonly installComplete: "Aura is starting.";
24
+ readonly cancelled: "Installation cancelled before making changes.";
25
+ readonly unsupportedLocalPlatform: "Local mode requires Linux or macOS with Docker. Use remote mode otherwise.";
26
+ readonly installerArtifactMissing: "The bundled installer artifact is missing from this package.";
27
+ readonly invalidHost: "Enter a valid hostname or IP address.";
28
+ readonly invalidPort: "Enter a port between 1 and 65535.";
29
+ readonly invalidUsername: "Enter a valid Linux username.";
30
+ readonly invalidInstallDir: "Enter an absolute Linux path other than /.";
31
+ readonly invalidBaseUrl: "Enter a valid http or https URL.";
32
+ readonly invalidModelId: "Enter a valid model identifier.";
33
+ readonly missingCommand: "Required command not found: {command}";
34
+ readonly preflightFailed: "Preflight failed: {reason}";
35
+ readonly insufficientDiskSpace: "Not enough free disk space on the installation target.";
36
+ readonly unsupportedArchitecture: "This CPU architecture is not supported by Aura.";
37
+ readonly invalidDiskAvailability: "Could not determine the available disk space on the installation target.";
38
+ readonly invalidCpuCount: "Could not determine the number of CPU cores on the installation target.";
39
+ readonly insufficientCpuCores: "Not enough CPU cores on the installation target.";
40
+ readonly invalidMemoryAvailability: "Could not determine the available memory on the installation target.";
41
+ readonly insufficientMemory: "Not enough memory on the installation target.";
42
+ readonly cleanupWarning: "Warning: a temporary file could not be removed.";
43
+ readonly cleanupFailed: "Temporary-file cleanup failed.";
44
+ readonly invalidRemotePreflightOutput: "The remote preflight returned an invalid response.";
45
+ readonly unsupportedRemoteClientPlatform: "Remote mode requires Windows or Linux.";
46
+ readonly installFailed: "Installation failed during {phase}. It is safe to run the wizard again.";
47
+ readonly applianceQuestion: "Install as a self-starting appliance (systemd service that starts Aura on boot)?";
48
+ readonly gvisorQuestion: "Enable gVisor sandboxing for stronger container isolation (Linux with a Debian/Ubuntu package manager only)?";
49
+ readonly modelRouteQuestion: "Which model route should Aura use?";
50
+ readonly modelRouteOpenrouter: "OpenRouter (cloud API)";
51
+ readonly modelRouteOllama: "Ollama (local or remote server)";
52
+ readonly openrouterBaseUrl: "OpenRouter API base URL";
53
+ readonly openrouterApiKey: "OpenRouter API key";
54
+ readonly openrouterModel: "OpenRouter model id (e.g. vendor/model-name)";
55
+ readonly ollamaBaseUrl: "Ollama base URL";
56
+ readonly ollamaModelSelect: "Choose an installed Ollama model";
57
+ readonly ollamaModelManualEntry: "Enter the Ollama model id to use";
58
+ readonly ollamaModelUnreachable: "Could not reach that Ollama endpoint from here. Enter the model id you want to use";
59
+ readonly gpuQuestion: "Does the target machine have an NVIDIA GPU you want to use for embeddings?";
60
+ };
61
+ //# sourceMappingURL=en.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/messages/en.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2DL,CAAC"}