@nac3/forge-cli 0.2.0-alpha.1 → 0.2.0-alpha.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"voice.d.ts","sourceRoot":"","sources":["../../src/commands/voice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkE3D"}
1
+ {"version":3,"file":"voice.d.ts","sourceRoot":"","sources":["../../src/commands/voice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqE3D"}
@@ -1,5 +1,6 @@
1
1
  import { readVoiceConfig, writeVoiceConfig, matchConfiguredWakeWord } from '../voice/config.js';
2
2
  import { DEFAULT_WAKE_ALIASES, mergeAliases } from '../voice/wake.js';
3
+ import { registerVoiceSetupCommand } from './voice_setup.js';
3
4
  function splitCsv(s) {
4
5
  return s.split(',').map((x) => x.trim()).filter((x) => x.length > 0);
5
6
  }
@@ -64,6 +65,8 @@ export function registerVoiceCommand(program) {
64
65
  if (!r.hit)
65
66
  process.exitCode = 1;
66
67
  });
68
+ /* `yf voice setup` -- BYOK provider keys + sync to mobile. */
69
+ registerVoiceSetupCommand(voice);
67
70
  void config;
68
71
  }
69
72
  //# sourceMappingURL=voice.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"voice.js","sourceRoot":"","sources":["../../src/commands/voice.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAChG,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEtE,SAAS,QAAQ,CAAC,CAAS;IACzB,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,kCAAkC,CAAC,CAAC;IAEvF,MAAM,MAAM,GAAG,KAAK;SACjB,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,0DAA0D,CAAC;SACvE,MAAM,CAAC,QAAQ,EAAE,0BAA0B,CAAC;SAC5C,MAAM,CAAC,kBAAkB,EAAE,gDAAgD,CAAC;SAC5E,MAAM,CAAC,cAAc,EAAE,oCAAoC,CAAC;SAC5D,MAAM,CAAC,oBAAoB,EAAE,yBAAyB,CAAC;SACvD,MAAM,CAAC,SAAS,EAAE,0CAA0C,CAAC;SAC7D,MAAM,CAAC,KAAK,EAAE,IAGd,EAAE,EAAE;QACH,IAAI,GAAG,GAAG,MAAM,eAAe,EAAE,CAAC;QAClC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,GAAG,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,kBAAkB,EAAE,EAAE,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC;YACnE,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;YAC/C,OAAO;QACT,CAAC;QACD,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC/B,GAAG,CAAC,kBAAkB,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAChD,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,kBAAkB,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;YAC5D,GAAG,CAAC,kBAAkB,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;YAClC,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YAChD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAChE,CAAC;YACD,GAAG,CAAC,iBAAiB,GAAG,CAAC,CAAC;YAC1B,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QACD,IAAI,OAAO;YAAE,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAEzC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;gBACzB,eAAe,EAAE,oBAAoB;gBACrC,UAAU,EAAE,GAAG,CAAC,kBAAkB;gBAClC,MAAM;gBACN,YAAY,EAAE,GAAG,CAAC,iBAAiB;aACpC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACf,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,KAAK;SACF,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,8CAA8C,CAAC;SAC3D,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,EAAE;QAC/B,MAAM,CAAC,GAAG,MAAM,uBAAuB,CAAC,MAAM,CAAC,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACxC,IAAI,CAAC,CAAC,CAAC,GAAG;YAAE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEL,KAAK,MAAM,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"voice.js","sourceRoot":"","sources":["../../src/commands/voice.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * `yf voice setup` -- interactive BYOK provider configuration.
3
+ *
4
+ * The user chooses one or more providers (OpenAI / Google /
5
+ * ElevenLabs), pastes the API keys, and this command:
6
+ *
7
+ * 1. Reads the current local provider keys from disk
8
+ * (~/.yujin-forge/provider_keys.json), if any.
9
+ * 2. Merges the new values on top.
10
+ * 3. Encrypts the merged payload with the SERVER_API_KEY
11
+ * from the vault (the same secret used for HMAC signing).
12
+ * 4. POSTs the encrypted blob to /v1/keys-sync/<handle> so
13
+ * the user's mobile + other paired devices pull it.
14
+ * 5. Writes the plaintext locally so subsequent voice calls
15
+ * can read it without re-prompting.
16
+ *
17
+ * Server never sees plaintext -- only the ciphertext blob.
18
+ *
19
+ * Subcommands:
20
+ * yf voice setup Interactive prompts.
21
+ * yf voice setup --show Print current local config (keys masked).
22
+ * yf voice setup --pull Pull the server copy + overwrite local.
23
+ * yf voice setup --provider openai --key sk-xxx
24
+ * Non-interactive single-provider set.
25
+ *
26
+ * ASCII-only.
27
+ */
28
+ import type { Command } from 'commander';
29
+ export interface VoiceSetupOptions {
30
+ show?: boolean;
31
+ pull?: boolean;
32
+ provider?: string;
33
+ key?: string;
34
+ }
35
+ export declare function registerVoiceSetupCommand(parent: Command): void;
36
+ export declare function runVoiceSetup(opts: VoiceSetupOptions): Promise<void>;
37
+ //# sourceMappingURL=voice_setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice_setup.d.ts","sourceRoot":"","sources":["../../src/commands/voice_setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8HzC,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAU/D;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuK1E"}
@@ -0,0 +1,308 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
+ import prompts from 'prompts';
5
+ import { c, header } from '../ui/colors.js';
6
+ import { Vault } from '../vault/store.js';
7
+ import { configDir } from '../license/index.js';
8
+ import { readLicense } from '../core/polar.js';
9
+ import { signBearer, HITO4_BASE_URL } from '../license/hito4_client.js';
10
+ import { encryptUserKeys, decryptUserKeys, envelopeToBlob, envelopeFromBlob, } from '../core/keys_envelope.js';
11
+ const VAULT_SECRET_SLOT = 'yf_server_api_key';
12
+ const LOCAL_KEYS_FILE = 'provider_keys.json';
13
+ function localKeysPath() {
14
+ const home = process.env.HOME || process.env.USERPROFILE || os.homedir();
15
+ return path.join(home, '.yujin-forge', LOCAL_KEYS_FILE);
16
+ }
17
+ async function readLocalKeys() {
18
+ try {
19
+ const raw = await fs.readFile(localKeysPath(), 'utf-8');
20
+ const parsed = JSON.parse(raw);
21
+ if (parsed && parsed.v === 1)
22
+ return parsed;
23
+ }
24
+ catch { /* missing or malformed -- treat as empty */ }
25
+ return { v: 1, updated_at: '1970-01-01T00:00:00Z' };
26
+ }
27
+ async function writeLocalKeys(payload) {
28
+ const p = localKeysPath();
29
+ await fs.mkdir(path.dirname(p), { recursive: true });
30
+ const tmp = p + '.tmp';
31
+ await fs.writeFile(tmp, JSON.stringify(payload, null, 2), 'utf-8');
32
+ await fs.rename(tmp, p);
33
+ }
34
+ function maskKey(k) {
35
+ if (!k)
36
+ return '(none)';
37
+ if (k.length <= 8)
38
+ return '****';
39
+ return k.slice(0, 4) + '...' + k.slice(-4);
40
+ }
41
+ async function loadServerSecret() {
42
+ const vault = await Vault.open({ configDir: configDir() });
43
+ if (!vault.has(VAULT_SECRET_SLOT)) {
44
+ throw new Error('voice setup: vault slot "' + VAULT_SECRET_SLOT + '" is empty. '
45
+ + 'Run `yf vault set ' + VAULT_SECRET_SLOT + '` with the value '
46
+ + 'provided at signup (or your tenant admin) before configuring '
47
+ + 'voice providers.');
48
+ }
49
+ return vault.get(VAULT_SECRET_SLOT);
50
+ }
51
+ async function loadUserHandle() {
52
+ const lic = await readLicense();
53
+ if (!lic.user_handle) {
54
+ throw new Error('voice setup: no user_handle on the local license cache. '
55
+ + 'Run `yf license activate --user-handle <you@example.com>` first.');
56
+ }
57
+ return lic.user_handle;
58
+ }
59
+ async function pushToServer(payload) {
60
+ const secret = await loadServerSecret();
61
+ const handle = await loadUserHandle();
62
+ const env = await encryptUserKeys(payload, secret);
63
+ const blob = envelopeToBlob(env);
64
+ const bearer = signBearer(secret, handle);
65
+ const url = HITO4_BASE_URL.replace(/\/+$/, '') + '/v1/keys-sync/' + encodeURIComponent(handle);
66
+ const r = await fetch(url, {
67
+ method: 'POST',
68
+ headers: {
69
+ Authorization: 'Bearer ' + bearer,
70
+ 'content-type': 'application/json',
71
+ },
72
+ body: JSON.stringify({ blob, ts: payload.updated_at }),
73
+ });
74
+ if (!r.ok) {
75
+ let detail = '';
76
+ try {
77
+ detail = await r.text();
78
+ }
79
+ catch { /* */ }
80
+ throw new Error('voice setup: server push failed (HTTP ' + r.status + '): ' + detail.slice(0, 200));
81
+ }
82
+ }
83
+ async function pullFromServer() {
84
+ const secret = await loadServerSecret();
85
+ const handle = await loadUserHandle();
86
+ const bearer = signBearer(secret, handle);
87
+ const url = HITO4_BASE_URL.replace(/\/+$/, '') + '/v1/keys-sync/' + encodeURIComponent(handle);
88
+ const r = await fetch(url, {
89
+ method: 'GET',
90
+ headers: { Authorization: 'Bearer ' + bearer },
91
+ });
92
+ if (!r.ok) {
93
+ let detail = '';
94
+ try {
95
+ detail = await r.text();
96
+ }
97
+ catch { /* */ }
98
+ throw new Error('voice setup: server pull failed (HTTP ' + r.status + '): ' + detail.slice(0, 200));
99
+ }
100
+ const body = await r.json();
101
+ if (!body.blob)
102
+ return null;
103
+ const env = envelopeFromBlob(body.blob);
104
+ return decryptUserKeys(env, secret);
105
+ }
106
+ function printCurrent(p) {
107
+ header('Yujin Forge -- voice setup (current local)');
108
+ console.log('');
109
+ console.log(' OpenAI API key: ' + c.dim(maskKey(p.openai_api_key)));
110
+ console.log(' Google STT key: ' + c.dim(maskKey(p.google_stt_key)));
111
+ console.log(' Google TTS key: ' + c.dim(maskKey(p.google_tts_key)));
112
+ console.log(' ElevenLabs API key: ' + c.dim(maskKey(p.elevenlabs_api_key)));
113
+ console.log('');
114
+ console.log(' STT preference: ' + c.brand(p.stt_provider_preference ?? '(not set)'));
115
+ console.log(' TTS preference: ' + c.brand(p.tts_provider_preference ?? '(not set)'));
116
+ console.log(' STT language: ' + (p.stt_language ?? c.dim('(default)')));
117
+ console.log(' TTS voice: ' + (p.tts_voice ?? c.dim('(default)')));
118
+ console.log(' Last updated: ' + c.dim(p.updated_at));
119
+ }
120
+ export function registerVoiceSetupCommand(parent) {
121
+ parent
122
+ .command('setup')
123
+ .description('Configure voice provider API keys (OpenAI / Google / ElevenLabs). '
124
+ + 'Encrypts + syncs to your other devices automatically.')
125
+ .option('--show', 'print current local config (keys masked)')
126
+ .option('--pull', 'pull the server copy + overwrite local')
127
+ .option('--provider <name>', 'non-interactive: set this provider')
128
+ .option('--key <value>', 'non-interactive: the API key value for --provider')
129
+ .action(async (opts) => { await runVoiceSetup(opts); });
130
+ }
131
+ export async function runVoiceSetup(opts) {
132
+ /* --show: print current + exit. */
133
+ if (opts.show) {
134
+ const current = await readLocalKeys();
135
+ printCurrent(current);
136
+ return;
137
+ }
138
+ /* --pull: server -> local. */
139
+ if (opts.pull) {
140
+ let pulled;
141
+ try {
142
+ pulled = await pullFromServer();
143
+ }
144
+ catch (err) {
145
+ console.error(c.error(err instanceof Error ? err.message : String(err)));
146
+ process.exitCode = 1;
147
+ return;
148
+ }
149
+ if (!pulled) {
150
+ console.log(c.dim('Server has no provider keys for this user yet.'));
151
+ return;
152
+ }
153
+ await writeLocalKeys(pulled);
154
+ header('Yujin Forge -- voice setup (pulled from server)');
155
+ console.log('');
156
+ printCurrent(pulled);
157
+ return;
158
+ }
159
+ /* --provider / --key: non-interactive single set. */
160
+ if (opts.provider || opts.key) {
161
+ if (!opts.provider || !opts.key) {
162
+ console.error(c.error('--provider and --key must be used together.'));
163
+ process.exitCode = 1;
164
+ return;
165
+ }
166
+ const merged = await readLocalKeys();
167
+ const ts = new Date().toISOString();
168
+ const p = opts.provider.toLowerCase();
169
+ if (p === 'openai')
170
+ merged.openai_api_key = opts.key;
171
+ else if (p === 'google-stt')
172
+ merged.google_stt_key = opts.key;
173
+ else if (p === 'google-tts')
174
+ merged.google_tts_key = opts.key;
175
+ else if (p === 'elevenlabs')
176
+ merged.elevenlabs_api_key = opts.key;
177
+ else {
178
+ console.error(c.error('--provider must be one of: openai, google-stt, google-tts, elevenlabs'));
179
+ process.exitCode = 1;
180
+ return;
181
+ }
182
+ merged.updated_at = ts;
183
+ try {
184
+ await pushToServer(merged);
185
+ await writeLocalKeys(merged);
186
+ header('Yujin Forge -- voice setup (saved)');
187
+ console.log('');
188
+ printCurrent(merged);
189
+ }
190
+ catch (err) {
191
+ console.error(c.error(err instanceof Error ? err.message : String(err)));
192
+ process.exitCode = 1;
193
+ }
194
+ return;
195
+ }
196
+ /* Interactive flow. */
197
+ const current = await readLocalKeys();
198
+ header('Yujin Forge -- voice setup');
199
+ console.log('');
200
+ console.log(c.dim('Configure the API keys for your chosen voice providers. The keys are'));
201
+ console.log(c.dim('encrypted with your account secret + synced to your mobile + other'));
202
+ console.log(c.dim('paired devices automatically. The server never sees plaintext.'));
203
+ console.log('');
204
+ console.log(c.dim('Press Enter on any field to keep its current value.'));
205
+ console.log('');
206
+ const answers = await prompts([
207
+ {
208
+ type: 'multiselect',
209
+ name: 'providers',
210
+ message: 'Which providers do you want to configure?',
211
+ choices: [
212
+ { title: 'OpenAI (Whisper for STT + tts-1 for TTS)', value: 'openai' },
213
+ { title: 'Google Cloud (Speech-to-Text + Text-to-Speech)', value: 'google' },
214
+ { title: 'ElevenLabs (TTS only -- higher quality voice)', value: 'elevenlabs' },
215
+ ],
216
+ min: 1,
217
+ hint: 'Space to select, Enter to confirm.',
218
+ },
219
+ ]);
220
+ if (!answers.providers || answers.providers.length === 0) {
221
+ console.log(c.dim('No providers selected. Aborting.'));
222
+ return;
223
+ }
224
+ const merged = { ...current };
225
+ if (answers.providers.includes('openai')) {
226
+ const r = await prompts({
227
+ type: 'password',
228
+ name: 'k',
229
+ message: 'OpenAI API key (sk-...). Current: ' + maskKey(current.openai_api_key),
230
+ });
231
+ if (r.k)
232
+ merged.openai_api_key = r.k;
233
+ }
234
+ if (answers.providers.includes('google')) {
235
+ const sttR = await prompts({
236
+ type: 'password',
237
+ name: 'k',
238
+ message: 'Google Cloud Speech-to-Text API key. Current: ' + maskKey(current.google_stt_key),
239
+ });
240
+ if (sttR.k)
241
+ merged.google_stt_key = sttR.k;
242
+ const ttsR = await prompts({
243
+ type: 'password',
244
+ name: 'k',
245
+ message: 'Google Cloud Text-to-Speech API key (can be same as STT). Current: ' + maskKey(current.google_tts_key),
246
+ });
247
+ if (ttsR.k)
248
+ merged.google_tts_key = ttsR.k;
249
+ }
250
+ if (answers.providers.includes('elevenlabs')) {
251
+ const r = await prompts({
252
+ type: 'password',
253
+ name: 'k',
254
+ message: 'ElevenLabs API key. Current: ' + maskKey(current.elevenlabs_api_key),
255
+ });
256
+ if (r.k)
257
+ merged.elevenlabs_api_key = r.k;
258
+ }
259
+ /* Preferences (which provider to USE for each direction). */
260
+ const sttCandidates = [];
261
+ if (merged.openai_api_key)
262
+ sttCandidates.push({ title: 'OpenAI (Whisper)', value: 'openai' });
263
+ if (merged.google_stt_key)
264
+ sttCandidates.push({ title: 'Google', value: 'google' });
265
+ if (sttCandidates.length > 0) {
266
+ const pref = await prompts({
267
+ type: 'select',
268
+ name: 'p',
269
+ message: 'Preferred STT provider',
270
+ choices: sttCandidates,
271
+ initial: 0,
272
+ });
273
+ if (pref.p)
274
+ merged.stt_provider_preference = pref.p;
275
+ }
276
+ const ttsCandidates = [];
277
+ if (merged.openai_api_key)
278
+ ttsCandidates.push({ title: 'OpenAI (tts-1)', value: 'openai' });
279
+ if (merged.google_tts_key)
280
+ ttsCandidates.push({ title: 'Google', value: 'google' });
281
+ if (merged.elevenlabs_api_key)
282
+ ttsCandidates.push({ title: 'ElevenLabs', value: 'elevenlabs' });
283
+ if (ttsCandidates.length > 0) {
284
+ const pref = await prompts({
285
+ type: 'select',
286
+ name: 'p',
287
+ message: 'Preferred TTS provider',
288
+ choices: ttsCandidates,
289
+ initial: 0,
290
+ });
291
+ if (pref.p)
292
+ merged.tts_provider_preference = pref.p;
293
+ }
294
+ merged.updated_at = new Date().toISOString();
295
+ try {
296
+ await pushToServer(merged);
297
+ await writeLocalKeys(merged);
298
+ console.log('');
299
+ console.log(c.success('Voice config saved + synced.'));
300
+ console.log('');
301
+ printCurrent(merged);
302
+ }
303
+ catch (err) {
304
+ console.error(c.error(err instanceof Error ? err.message : String(err)));
305
+ process.exitCode = 1;
306
+ }
307
+ }
308
+ //# sourceMappingURL=voice_setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice_setup.js","sourceRoot":"","sources":["../../src/commands/voice_setup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * BYOK key sync envelope -- CLI side.
3
+ *
4
+ * Mirrors packages/nac3-rn/src/keys_envelope.ts byte-for-byte
5
+ * on the crypto helpers + plaintext schema. The mobile side
6
+ * lives in the nac3-rn package; this copy is for the CLI which
7
+ * cannot import out-of-rootDir.
8
+ *
9
+ * Drift between the two sides is caught by
10
+ * tests/keys-envelope-cross-impl.test.ts which encrypts on one
11
+ * side + decrypts on the other.
12
+ *
13
+ * ASCII-only. WebCrypto only (Node 20+ / Workers / RN).
14
+ */
15
+ export interface ProviderKeysPlaintext {
16
+ v: 1;
17
+ openai_api_key?: string;
18
+ google_stt_key?: string;
19
+ google_tts_key?: string;
20
+ elevenlabs_api_key?: string;
21
+ stt_provider_preference?: 'openai' | 'google';
22
+ tts_provider_preference?: 'openai' | 'google' | 'elevenlabs';
23
+ stt_language?: string;
24
+ tts_voice?: string;
25
+ updated_at: string;
26
+ }
27
+ export interface KeysEnvelope {
28
+ v: 1;
29
+ salt: string;
30
+ iv: string;
31
+ ct: string;
32
+ }
33
+ export declare class KeysEnvelopeError extends Error {
34
+ readonly kind: 'malformed' | 'bad_secret';
35
+ constructor(kind: 'malformed' | 'bad_secret');
36
+ }
37
+ export declare function encryptUserKeys(payload: ProviderKeysPlaintext, serverApiKey: string): Promise<KeysEnvelope>;
38
+ export declare function decryptUserKeys(envelope: KeysEnvelope, serverApiKey: string): Promise<ProviderKeysPlaintext>;
39
+ export declare function envelopeToBlob(env: KeysEnvelope): string;
40
+ export declare function envelopeFromBlob(blob: string): KeysEnvelope;
41
+ //# sourceMappingURL=keys_envelope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys_envelope.d.ts","sourceRoot":"","sources":["../../src/core/keys_envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAWH,MAAM,WAAW,qBAAqB;IACpC,CAAC,EAAE,CAAC,CAAC;IACL,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,uBAAuB,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC9C,uBAAuB,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,YAAY,CAAC;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,CAAC,CAAC;IACL,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAwCD,qBAAa,iBAAkB,SAAQ,KAAK;aACd,IAAI,EAAE,WAAW,GAAG,YAAY;gBAAhC,IAAI,EAAE,WAAW,GAAG,YAAY;CAG7D;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,qBAAqB,EAC9B,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,YAAY,CAAC,CAYvB;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,qBAAqB,CAAC,CA2BhC;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAKxD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAe3D"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * BYOK key sync envelope -- CLI side.
3
+ *
4
+ * Mirrors packages/nac3-rn/src/keys_envelope.ts byte-for-byte
5
+ * on the crypto helpers + plaintext schema. The mobile side
6
+ * lives in the nac3-rn package; this copy is for the CLI which
7
+ * cannot import out-of-rootDir.
8
+ *
9
+ * Drift between the two sides is caught by
10
+ * tests/keys-envelope-cross-impl.test.ts which encrypts on one
11
+ * side + decrypts on the other.
12
+ *
13
+ * ASCII-only. WebCrypto only (Node 20+ / Workers / RN).
14
+ */
15
+ const ENC = new TextEncoder();
16
+ const DEC = new TextDecoder();
17
+ const PBKDF2_ITERS = 200_000;
18
+ const KEY_BITS = 256;
19
+ const IV_BYTES = 12;
20
+ const SALT_BYTES = 16;
21
+ const CONTEXT_TAG = 'yf-keys-sync-v1';
22
+ function bufToHex(buf) {
23
+ const view = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
24
+ let hex = '';
25
+ for (let i = 0; i < view.length; i++)
26
+ hex += view[i].toString(16).padStart(2, '0');
27
+ return hex;
28
+ }
29
+ function hexToBytes(hex) {
30
+ if (hex.length % 2 !== 0)
31
+ throw new Error('keys envelope: hex string has odd length');
32
+ const out = new Uint8Array(hex.length / 2);
33
+ for (let i = 0; i < out.length; i++) {
34
+ const byte = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
35
+ if (Number.isNaN(byte))
36
+ throw new Error('keys envelope: invalid hex');
37
+ out[i] = byte;
38
+ }
39
+ return out;
40
+ }
41
+ function randomBytes(n) {
42
+ const out = new Uint8Array(n);
43
+ crypto.getRandomValues(out);
44
+ return out;
45
+ }
46
+ async function deriveKey(secret, salt) {
47
+ const taggedSecret = secret + ':' + CONTEXT_TAG;
48
+ const baseKey = await crypto.subtle.importKey('raw', ENC.encode(taggedSecret), { name: 'PBKDF2' }, false, ['deriveKey']);
49
+ return crypto.subtle.deriveKey({ name: 'PBKDF2', salt: salt, iterations: PBKDF2_ITERS, hash: 'SHA-256' }, baseKey, { name: 'AES-GCM', length: KEY_BITS }, false, ['encrypt', 'decrypt']);
50
+ }
51
+ export class KeysEnvelopeError extends Error {
52
+ kind;
53
+ constructor(kind) {
54
+ super('keys envelope: ' + kind);
55
+ this.kind = kind;
56
+ }
57
+ }
58
+ export async function encryptUserKeys(payload, serverApiKey) {
59
+ const salt = randomBytes(SALT_BYTES);
60
+ const iv = randomBytes(IV_BYTES);
61
+ const key = await deriveKey(serverApiKey, salt);
62
+ const plain = ENC.encode(JSON.stringify(payload));
63
+ const ct = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, plain);
64
+ return {
65
+ v: 1,
66
+ salt: bufToHex(salt),
67
+ iv: bufToHex(iv),
68
+ ct: bufToHex(new Uint8Array(ct)),
69
+ };
70
+ }
71
+ export async function decryptUserKeys(envelope, serverApiKey) {
72
+ if (envelope.v !== 1)
73
+ throw new KeysEnvelopeError('malformed');
74
+ let salt;
75
+ let iv;
76
+ let ct;
77
+ try {
78
+ salt = hexToBytes(envelope.salt);
79
+ iv = hexToBytes(envelope.iv);
80
+ ct = hexToBytes(envelope.ct);
81
+ }
82
+ catch {
83
+ throw new KeysEnvelopeError('malformed');
84
+ }
85
+ const key = await deriveKey(serverApiKey, salt);
86
+ let plain;
87
+ try {
88
+ plain = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, ct);
89
+ }
90
+ catch {
91
+ throw new KeysEnvelopeError('bad_secret');
92
+ }
93
+ let parsed;
94
+ try {
95
+ parsed = JSON.parse(DEC.decode(plain));
96
+ }
97
+ catch {
98
+ throw new KeysEnvelopeError('malformed');
99
+ }
100
+ if (parsed.v !== 1 || !parsed.updated_at) {
101
+ throw new KeysEnvelopeError('malformed');
102
+ }
103
+ return parsed;
104
+ }
105
+ export function envelopeToBlob(env) {
106
+ const json = JSON.stringify(env);
107
+ let bin = '';
108
+ for (let i = 0; i < json.length; i++)
109
+ bin += String.fromCharCode(json.charCodeAt(i) & 0xff);
110
+ return btoa(bin);
111
+ }
112
+ export function envelopeFromBlob(blob) {
113
+ let json;
114
+ try {
115
+ const bin = atob(blob);
116
+ json = '';
117
+ for (let i = 0; i < bin.length; i++)
118
+ json += String.fromCharCode(bin.charCodeAt(i));
119
+ }
120
+ catch {
121
+ throw new KeysEnvelopeError('malformed');
122
+ }
123
+ let parsed;
124
+ try {
125
+ parsed = JSON.parse(json);
126
+ }
127
+ catch {
128
+ throw new KeysEnvelopeError('malformed');
129
+ }
130
+ if (!parsed || typeof parsed !== 'object' || parsed.v !== 1) {
131
+ throw new KeysEnvelopeError('malformed');
132
+ }
133
+ return parsed;
134
+ }
135
+ //# sourceMappingURL=keys_envelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys_envelope.js","sourceRoot":"","sources":["../../src/core/keys_envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;AAC9B,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;AAE9B,MAAM,YAAY,GAAG,OAAO,CAAC;AAC7B,MAAM,QAAQ,GAAG,GAAG,CAAC;AACrB,MAAM,QAAQ,GAAG,EAAE,CAAC;AACpB,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,WAAW,GAAG,iBAAiB,CAAC;AAsBtC,SAAS,QAAQ,CAAC,GAA6B;IAC7C,MAAM,IAAI,GAAG,GAAG,YAAY,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IACnE,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACtF,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QACtE,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,WAAW,CAAC,CAAS;IAC5B,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IAC9B,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,MAAc,EAAE,IAAgB;IACvD,MAAM,YAAY,GAAG,MAAM,GAAG,GAAG,GAAG,WAAW,CAAC;IAChD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAC3C,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,WAAW,CAAC,CAC1E,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAC5B,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAoB,EAAE,UAAU,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,EACzF,OAAO,EACP,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,EACrC,KAAK,EACL,CAAC,SAAS,EAAE,SAAS,CAAC,CACvB,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACd;IAA5B,YAA4B,IAAgC;QAC1D,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;QADN,SAAI,GAAJ,IAAI,CAA4B;IAE5D,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAA8B,EAC9B,YAAoB;IAEpB,MAAM,IAAI,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACrC,MAAM,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACjC,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAClD,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC5E,OAAO;QACL,CAAC,EAAE,CAAC;QACJ,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;QACpB,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC;QAChB,EAAE,EAAE,QAAQ,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;KACjC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAsB,EACtB,YAAoB;IAEpB,IAAI,QAAQ,CAAC,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC/D,IAAI,IAAgB,CAAC;IAAC,IAAI,EAAc,CAAC;IAAC,IAAI,EAAc,CAAC;IAC7D,IAAI,CAAC;QACH,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjC,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC7B,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAChD,IAAI,KAAkB,CAAC;IACvB,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,iBAAiB,CAAC,YAAY,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,MAA6B,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAA0B,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACzC,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAiB;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5F,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,IAAI,GAAG,EAAE,CAAC;QACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE;YAAE,IAAI,IAAI,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAAC,CAAC;IACtF,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAK,MAAuB,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9E,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,MAAsB,CAAC;AAChC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nac3/forge-cli",
3
- "version": "0.2.0-alpha.1",
3
+ "version": "0.2.0-alpha.2",
4
4
  "description": "Yujin Forge -- voice-first NAC-3 React development framework. CLI + chat panel + spec ingest + 10-format document reader + voice loop.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Pablo Kuschnirof <pablo@rpaforce.com>",
@@ -36,6 +36,7 @@
36
36
  "node-html-parser": "6.1.13",
37
37
  "pdfjs-dist": "^4.10.38",
38
38
  "prompts": "2.4.2",
39
+ "typescript": "5.7.2",
39
40
  "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
40
41
  },
41
42
  "devDependencies": {
@@ -45,7 +46,6 @@
45
46
  "pixelmatch": "^7.2.0",
46
47
  "pngjs": "^7.0.0",
47
48
  "tsx": "4.19.2",
48
- "typescript": "5.7.2",
49
49
  "vitest": "2.1.8"
50
50
  },
51
51
  "engines": {