@usenaive-sdk/cli 0.12.0 → 0.12.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/README.md +22 -0
- package/dist/client.d.ts +26 -1
- package/dist/client.js +167 -5
- package/dist/client.js.map +1 -1
- package/dist/commands/aeo.js +13 -6
- package/dist/commands/aeo.js.map +1 -1
- package/dist/commands/auth.d.ts +30 -0
- package/dist/commands/auth.js +400 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/billing.js +9 -9
- package/dist/commands/billing.js.map +1 -1
- package/dist/commands/brain.d.ts +2 -0
- package/dist/commands/brain.js +509 -0
- package/dist/commands/brain.js.map +1 -0
- package/dist/commands/browser.js +28 -1
- package/dist/commands/browser.js.map +1 -1
- package/dist/commands/clone.d.ts +2 -0
- package/dist/commands/clone.js +199 -0
- package/dist/commands/clone.js.map +1 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +36 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/env.d.ts +3 -3
- package/dist/commands/env.js +68 -4
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/images.js +2 -2
- package/dist/commands/init.js +38 -23
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/keys.js +26 -3
- package/dist/commands/keys.js.map +1 -1
- package/dist/commands/loops.d.ts +2 -0
- package/dist/commands/loops.js +260 -0
- package/dist/commands/loops.js.map +1 -0
- package/dist/commands/mobile.d.ts +2 -0
- package/dist/commands/mobile.js +341 -0
- package/dist/commands/mobile.js.map +1 -0
- package/dist/commands/payments.d.ts +2 -0
- package/dist/commands/payments.js +131 -0
- package/dist/commands/payments.js.map +1 -0
- package/dist/commands/phone.js +77 -2
- package/dist/commands/phone.js.map +1 -1
- package/dist/commands/register.js +4 -4
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/up.js +14 -4
- package/dist/commands/up.js.map +1 -1
- package/dist/commands/usage.js +4 -4
- package/dist/commands/video.js +94 -273
- package/dist/commands/video.js.map +1 -1
- package/dist/commands/voice.d.ts +2 -0
- package/dist/commands/voice.js +516 -0
- package/dist/commands/voice.js.map +1 -0
- package/dist/commands/wallet.d.ts +2 -0
- package/dist/commands/wallet.js +244 -0
- package/dist/commands/wallet.js.map +1 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.js +35 -6
- package/dist/config.js.map +1 -1
- package/dist/index.js +70 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/unknown-command.d.ts +17 -0
- package/dist/lib/unknown-command.js +19 -0
- package/dist/lib/unknown-command.js.map +1 -0
- package/dist/lib/version-check.d.ts +26 -0
- package/dist/lib/version-check.js +21 -0
- package/dist/lib/version-check.js.map +1 -0
- package/dist/output.d.ts +20 -5
- package/dist/output.js +150 -5
- package/dist/output.js.map +1 -1
- package/dist/prompt.d.ts +17 -0
- package/dist/prompt.js +70 -0
- package/dist/prompt.js.map +1 -0
- package/package.json +10 -5
- package/dist/commands/billing-client.d.ts +0 -2
- package/dist/commands/billing-client.js +0 -271
- package/dist/commands/billing-client.js.map +0 -1
- package/dist/commands/crm-app.d.ts +0 -2
- package/dist/commands/crm-app.js +0 -306
- package/dist/commands/crm-app.js.map +0 -1
- package/dist/commands/crm.d.ts +0 -2
- package/dist/commands/crm.js +0 -319
- package/dist/commands/crm.js.map +0 -1
- package/dist/commands/integrations.d.ts +0 -2
- package/dist/commands/integrations.js +0 -199
- package/dist/commands/integrations.js.map +0 -1
- package/dist/commands/operators.d.ts +0 -11
- package/dist/commands/operators.js +0 -120
- package/dist/commands/operators.js.map +0 -1
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { writeFileSync, readFileSync, statSync } from "node:fs";
|
|
3
|
+
import { resolve, basename } from "node:path";
|
|
4
|
+
import { apiRequest, sessionRequest, handleApiError } from "../client.js";
|
|
5
|
+
import { loadConfig } from "../config.js";
|
|
6
|
+
import { agentOutput, agentError, isInteractive } from "../output.js";
|
|
7
|
+
import { ask, confirm, confirmExact, select, affirm } from "../prompt.js";
|
|
8
|
+
// Human-only voice lifecycle (clone/revoke) goes through the session-cookie surface
|
|
9
|
+
// (/v1/voice-admin) via sessionRequest — never the agent key. The synthesis surface
|
|
10
|
+
// (say/list/status → /v1/voice) stays agent-token-only via apiRequest.
|
|
11
|
+
const VALID_CONSENT_TYPES = ["self", "third_party_attested", "third_party_verified"];
|
|
12
|
+
// The ToS version the CLI records when the user accepts via --accept-tos. Bump when the
|
|
13
|
+
// voice-cloning Terms of Service text changes (the server stores this as the liability basis).
|
|
14
|
+
const VOICE_TOS_VERSION = "voice-clone-tos-2026-06-01";
|
|
15
|
+
// NOTE: placeholder URL — point this at the real published Voice Cloning ToS before shipping.
|
|
16
|
+
const VOICE_TOS_URL = "https://usenaive.ai/legal/voice-cloning";
|
|
17
|
+
const MAX_SAMPLE_BYTES = 25 * 1024 * 1024;
|
|
18
|
+
const WAIT_INTERVAL_MS = 10_000;
|
|
19
|
+
const WAIT_TIMEOUT_MS = 10 * 60 * 1000;
|
|
20
|
+
const WAIT_WARN_MS = 2 * 60 * 1000;
|
|
21
|
+
// Agent-surface voice commands only. Voice CREATION/cloning is human-only and lives in
|
|
22
|
+
// the Studio UI — the CLI authenticates with an agent key, which the creation API
|
|
23
|
+
// rejects by design. `create` is a stub that points there.
|
|
24
|
+
// Interactive clone setup. ONLY called when flags are missing AND the caller is an interactive
|
|
25
|
+
// human (isInteractive() = opt-in human mode + TTY stdin) — never for agents/pty callers. It
|
|
26
|
+
// POPULATES `opts` (consent type, attestation, i-affirm, tier, …) and then the normal flag gates
|
|
27
|
+
// + consent-object construction run unchanged — so a wizard clone and a flag clone post an IDENTICAL
|
|
28
|
+
// consent body. Returns false on cancel/timeout. Never asks for a secret.
|
|
29
|
+
async function runCloneWizard(opts) {
|
|
30
|
+
process.stdout.write("\nLet's set up your voice clone.\n");
|
|
31
|
+
const whose = await select("Whose voice is this?", [
|
|
32
|
+
{ value: "self", label: "Mine (my own voice)" },
|
|
33
|
+
{ value: "third", label: "Someone else's" },
|
|
34
|
+
]);
|
|
35
|
+
if (whose === null)
|
|
36
|
+
return false;
|
|
37
|
+
const name = await ask("Name this voice", { default: typeof opts.name === "string" ? opts.name : undefined });
|
|
38
|
+
if (!name)
|
|
39
|
+
return false;
|
|
40
|
+
opts.name = name;
|
|
41
|
+
if (whose === "self") {
|
|
42
|
+
const cfg = loadConfig();
|
|
43
|
+
opts.consentType = "self";
|
|
44
|
+
opts.consenterName = (await ask("Your name (for the consent record)", { default: cfg.user_email ?? "me" })) ?? "me";
|
|
45
|
+
opts.attestation = `I, ${opts.consenterName}, consent to cloning my own voice for use on the Naive platform.`;
|
|
46
|
+
process.stdout.write(`\nThis clones YOUR OWN voice. By proceeding you consent to it and accept the Voice Cloning\n` +
|
|
47
|
+
`Terms of Service (${VOICE_TOS_VERSION}): ${VOICE_TOS_URL}\n`);
|
|
48
|
+
opts.iAffirm = true;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
const consenter = await ask("Whose voice is it? (their full name)");
|
|
52
|
+
if (!consenter)
|
|
53
|
+
return false;
|
|
54
|
+
opts.consenterName = consenter;
|
|
55
|
+
// Full disclosure — getting consent is the USER's responsibility. We inform clearly; they decide.
|
|
56
|
+
process.stdout.write(`\n⚠ Cloning someone else's voice — YOUR responsibility.\n` +
|
|
57
|
+
` By proceeding you confirm ALL of the following:\n` +
|
|
58
|
+
` • You have ${consenter}'s permission and the legal right to clone their voice.\n` +
|
|
59
|
+
` • Obtaining that consent is YOUR responsibility — Naive records your affirmation\n` +
|
|
60
|
+
` (your identity + a timestamp) as the basis, and you are liable for any misuse or\n` +
|
|
61
|
+
` missing consent.\n` +
|
|
62
|
+
` • You accept the Voice Cloning Terms of Service (${VOICE_TOS_VERSION}): ${VOICE_TOS_URL}\n`);
|
|
63
|
+
// ElevenLabs (the only provider) requires the voice OWNER to confirm by email —
|
|
64
|
+
// self-affirmed third-party clones (attested) are not permitted. So a third-party
|
|
65
|
+
// clone is always verified. This is NOT up to the user: it's the provider's OEM rule,
|
|
66
|
+
// server-enforced too.
|
|
67
|
+
process.stdout.write(`\n Note: the voice provider requires ${consenter} to confirm by email before the clone runs.\n`);
|
|
68
|
+
opts.consentType = "third_party_verified";
|
|
69
|
+
const email = await ask(`${consenter}'s email (for the confirmation link)`);
|
|
70
|
+
if (!email)
|
|
71
|
+
return false;
|
|
72
|
+
opts.consenterEmail = email;
|
|
73
|
+
opts.attestation = `I affirm ${consenter} authorized me to clone their voice for use on the Naive platform; ${consenter} will confirm by email.`;
|
|
74
|
+
opts.iAffirm = true;
|
|
75
|
+
}
|
|
76
|
+
process.stdout.write(`\nReady: clone "${opts.name}" (ElevenLabs), consent: ${opts.consentType}.\n`);
|
|
77
|
+
process.stdout.write(`You affirm: "${opts.attestation}"\n`);
|
|
78
|
+
return affirm("Proceed");
|
|
79
|
+
}
|
|
80
|
+
export const voiceCmd = new Command("voice").description("Synthesize speech in your cloned voices (agent surface)");
|
|
81
|
+
voiceCmd
|
|
82
|
+
.command("say")
|
|
83
|
+
.description("Generate speech in a voice you own")
|
|
84
|
+
.requiredOption("--voice <id>", "Voice id (see `naive voice list`)")
|
|
85
|
+
.requiredOption("--text <text>", "Text to speak (max 5000 chars)")
|
|
86
|
+
.option("--use <use>", "Declared use (must be within the voice's authorized uses)")
|
|
87
|
+
.option("--out <file>", "Download the audio to this file instead of printing the URL")
|
|
88
|
+
.action(async (opts) => {
|
|
89
|
+
// Cost transparency — interactive humans only. Agents never incur the extra balance round-trip
|
|
90
|
+
// (the estimate is advisory; the server is authoritative on actual spend).
|
|
91
|
+
if (isInteractive()) {
|
|
92
|
+
const charCount = opts.text.length;
|
|
93
|
+
let balanceNote = "";
|
|
94
|
+
try {
|
|
95
|
+
const st = await apiRequest("GET", "/v1/status");
|
|
96
|
+
const bal = st.data?.credits?.balance;
|
|
97
|
+
if (typeof bal === "number")
|
|
98
|
+
balanceNote = ` You have ${bal} credits.`;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
/* best-effort — show the char count regardless */
|
|
102
|
+
}
|
|
103
|
+
const ok = await confirm(`Synthesize ~${charCount} characters in voice ${opts.voice}?${balanceNote}`);
|
|
104
|
+
if (!ok) {
|
|
105
|
+
agentError({
|
|
106
|
+
action: "voice.say",
|
|
107
|
+
error: { code: "cancelled", message: "Cancelled — no credits spent." },
|
|
108
|
+
recovery_steps: [{ command: "naive voice say --voice <id> --text <text>", description: "Run again when ready" }],
|
|
109
|
+
});
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const resp = await apiRequest("POST", "/v1/voice/synthesize", {
|
|
114
|
+
voice_id: opts.voice,
|
|
115
|
+
text: opts.text,
|
|
116
|
+
...(opts.use && { use: opts.use }),
|
|
117
|
+
});
|
|
118
|
+
handleApiError("voice.say", resp);
|
|
119
|
+
const data = resp.data;
|
|
120
|
+
if (opts.out) {
|
|
121
|
+
// --out path is operator-supplied; we never derive it from server values
|
|
122
|
+
const dest = resolve(process.cwd(), opts.out);
|
|
123
|
+
const audio = await fetch(data.url);
|
|
124
|
+
if (!audio.ok) {
|
|
125
|
+
agentOutput({
|
|
126
|
+
action: "voice.say",
|
|
127
|
+
result: { synthesis_id: data.synthesis_id, url: data.url, downloaded: false, http_status: audio.status },
|
|
128
|
+
next_steps: [{ command: `curl -o ${opts.out} "<url>"`, description: "Download manually; the URL may have expired" }],
|
|
129
|
+
hints: ["Synthesis succeeded but the audio download failed — the presigned URL may have expired (24h)."],
|
|
130
|
+
});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
writeFileSync(dest, Buffer.from(await audio.arrayBuffer()));
|
|
134
|
+
agentOutput({
|
|
135
|
+
action: "voice.say",
|
|
136
|
+
result: { synthesis_id: data.synthesis_id, saved_to: dest, credits: data.credits, char_count: data.char_count },
|
|
137
|
+
next_steps: [{ command: `naive voice status ${data.synthesis_id}`, description: "Check this synthesis" }],
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
agentOutput({
|
|
142
|
+
action: "voice.say",
|
|
143
|
+
result: data,
|
|
144
|
+
next_steps: [
|
|
145
|
+
{ command: "naive email send --attach <url>", description: "Attach the audio to an email", when: "Sending the audio to someone" },
|
|
146
|
+
{ command: `naive voice status ${data.synthesis_id}`, description: "Check this synthesis" },
|
|
147
|
+
],
|
|
148
|
+
hints: ["The audio URL is presigned and expires in 24h. Re-run `say` if it lapses."],
|
|
149
|
+
related_commands: ["naive voice list"],
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
voiceCmd
|
|
153
|
+
.command("list")
|
|
154
|
+
.description("List voices available to you")
|
|
155
|
+
.action(async () => {
|
|
156
|
+
const resp = await apiRequest("GET", "/v1/voice/voices");
|
|
157
|
+
handleApiError("voice.list", resp);
|
|
158
|
+
agentOutput({
|
|
159
|
+
action: "voice.list",
|
|
160
|
+
result: resp.data,
|
|
161
|
+
next_steps: [{ command: "naive voice say --voice <id> --text <text>", description: "Synthesize speech in a voice" }],
|
|
162
|
+
related_commands: ["naive voice say"],
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
voiceCmd
|
|
166
|
+
.command("status")
|
|
167
|
+
.description("Get the status of a past synthesis")
|
|
168
|
+
.argument("<synthesis_id>", "synthesis_id from a `say` response")
|
|
169
|
+
.action(async (synthesisId) => {
|
|
170
|
+
const resp = await apiRequest("GET", `/v1/voice/synthesis/${encodeURIComponent(synthesisId)}`);
|
|
171
|
+
handleApiError("voice.status", resp);
|
|
172
|
+
agentOutput({
|
|
173
|
+
action: "voice.status",
|
|
174
|
+
result: resp.data,
|
|
175
|
+
next_steps: [{ command: "naive voice list", description: "List your voices" }],
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
voiceCmd
|
|
179
|
+
.command("clone")
|
|
180
|
+
.description("(Human-only) Clone a voice from an audio sample — requires `naive auth session-login`")
|
|
181
|
+
.argument("<file>", "Audio sample (mp3/wav/m4a/webm, <=25MB) of the voice to clone")
|
|
182
|
+
// NOT requiredOption: when these are missing AND a human is driving, the interactive wizard
|
|
183
|
+
// collects them; when missing non-interactively, the action's structured gates error cleanly.
|
|
184
|
+
// (requiredOption would let commander reject before the action, making the wizard unreachable.)
|
|
185
|
+
.option("--name <name>", "Display name for the voice")
|
|
186
|
+
.option("--consent-type <type>", "self | third_party_attested | third_party_verified")
|
|
187
|
+
.option("--consenter-name <name>", "Name of the person who consented")
|
|
188
|
+
.option("--attestation <text>", "The consent affirmation text you are recording")
|
|
189
|
+
.option("--i-affirm", "Required: you affirm you have the right to clone this voice")
|
|
190
|
+
.option("--consenter-email <email>", "Consenter email (REQUIRED for third-party consent)")
|
|
191
|
+
.option("--authorized-uses <list>", "Comma-separated allowed uses, e.g. email,video")
|
|
192
|
+
.option("--scope <scope>", "company | agent", "company")
|
|
193
|
+
.option("--agent-id <id>", "Agent id (required when --scope agent)")
|
|
194
|
+
.option("--profile-id <id>", "Resume an existing draft profile instead of creating one")
|
|
195
|
+
.option("--accept-tos", "Required for third_party_attested: you accept the voice-cloning Terms of Service")
|
|
196
|
+
.option("--wait", "Poll until the clone is ready (10s interval, 10m timeout)")
|
|
197
|
+
.addHelpText("after", `
|
|
198
|
+
Voice synthesis runs on ElevenLabs (the only provider).
|
|
199
|
+
|
|
200
|
+
Consent types (the legal spine — you attest, the platform records):
|
|
201
|
+
- self → your own voice. Live immediately.
|
|
202
|
+
- third_party_verified → someone else's voice; the OWNER confirms via an emailed link
|
|
203
|
+
(--consenter-email) before the clone is kicked. REQUIRED for
|
|
204
|
+
any third-party clone (the provider requires verified consent).
|
|
205
|
+
- third_party_attested → no longer permitted (the provider requires verified owner consent).
|
|
206
|
+
|
|
207
|
+
Examples:
|
|
208
|
+
$ naive auth session-login --email me@co.com --password ...
|
|
209
|
+
$ naive voice clone me.m4a --name "My Voice" --consent-type self --i-affirm \\
|
|
210
|
+
--consenter-name "Me" --attestation "I consent to cloning my own voice" --wait
|
|
211
|
+
`)
|
|
212
|
+
.action(async (file, opts) => {
|
|
213
|
+
// Interactive wizard ONLY when required flags are missing AND a human is driving (opt-in human
|
|
214
|
+
// mode + TTY stdin). Flag-check runs FIRST so a non-interactive caller (agent/pty/script) missing
|
|
215
|
+
// flags falls straight through to the structured error gates below — never the wizard, never a hang.
|
|
216
|
+
const cloneFlagsMissing = !opts.iAffirm || !opts.name || !opts.consentType || !opts.consenterName || !opts.attestation;
|
|
217
|
+
if (cloneFlagsMissing && isInteractive()) {
|
|
218
|
+
const ok = await runCloneWizard(opts);
|
|
219
|
+
if (!ok) {
|
|
220
|
+
agentError({
|
|
221
|
+
action: "voice.clone",
|
|
222
|
+
error: { code: "cancelled", message: "Clone setup cancelled — nothing was created." },
|
|
223
|
+
recovery_steps: [
|
|
224
|
+
{ command: `naive voice clone ${file} --name "<name>" --consent-type self --i-affirm --consenter-name "<name>" --attestation "..."`, description: "Provide the details as flags instead" },
|
|
225
|
+
],
|
|
226
|
+
});
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// ── Gate G3: no silent consent ──────────────────────────────────────────────
|
|
231
|
+
if (!opts.iAffirm) {
|
|
232
|
+
agentError({
|
|
233
|
+
action: "voice.clone",
|
|
234
|
+
error: { code: "invalid_input", message: "You must pass --i-affirm to confirm you have the right to clone this voice." },
|
|
235
|
+
recovery_steps: [{ command: "naive voice clone <file> ... --i-affirm", description: "Re-run with the affirmation flag" }],
|
|
236
|
+
});
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (!opts.name || !opts.consenterName || !opts.attestation) {
|
|
240
|
+
const missing = [!opts.name && "--name", !opts.consenterName && "--consenter-name", !opts.attestation && "--attestation"]
|
|
241
|
+
.filter(Boolean)
|
|
242
|
+
.join(", ");
|
|
243
|
+
agentError({
|
|
244
|
+
action: "voice.clone",
|
|
245
|
+
error: { code: "invalid_input", message: `Missing required: ${missing}. Run interactively for a guided wizard, or pass all flags.` },
|
|
246
|
+
recovery_steps: [{ command: `naive voice clone ${file} --name "<name>" --consent-type self --i-affirm --consenter-name "<name>" --attestation "..."`, description: "Provide the missing flags" }],
|
|
247
|
+
});
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (!VALID_CONSENT_TYPES.includes(opts.consentType)) {
|
|
251
|
+
agentError({
|
|
252
|
+
action: "voice.clone",
|
|
253
|
+
error: { code: "invalid_input", message: `--consent-type must be one of: ${VALID_CONSENT_TYPES.join(", ")}` },
|
|
254
|
+
recovery_steps: [{ command: "naive voice clone <file> ... --consent-type self", description: "Use a valid consent type" }],
|
|
255
|
+
});
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
const isSelf = opts.consentType === "self";
|
|
259
|
+
// Email round-trip is the VERIFIED tier only. Attested goes live on attestation + ToS.
|
|
260
|
+
if (opts.consentType === "third_party_verified" && !opts.consenterEmail) {
|
|
261
|
+
agentError({
|
|
262
|
+
action: "voice.clone",
|
|
263
|
+
error: { code: "invalid_input", message: "Verified third-party consent requires --consenter-email for the owner confirmation round-trip." },
|
|
264
|
+
recovery_steps: [{ command: "naive voice clone <file> ... --consent-type third_party_verified --consenter-email person@example.com", description: "Provide the owner's email" }],
|
|
265
|
+
});
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (opts.consentType === "third_party_attested" && !opts.acceptTos) {
|
|
269
|
+
agentError({
|
|
270
|
+
action: "voice.clone",
|
|
271
|
+
error: { code: "invalid_input", message: "Attested consent requires --accept-tos (you accept the voice-cloning Terms of Service and carry the liability)." },
|
|
272
|
+
recovery_steps: [{ command: "naive voice clone <file> ... --consent-type third_party_attested --accept-tos", description: "Accept the ToS so the attestation is recorded" }],
|
|
273
|
+
});
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
if (isSelf && opts.consenterEmail) {
|
|
277
|
+
const cfg = loadConfig();
|
|
278
|
+
if (cfg.user_email && opts.consenterEmail.toLowerCase() !== cfg.user_email.toLowerCase()) {
|
|
279
|
+
agentError({
|
|
280
|
+
action: "voice.clone",
|
|
281
|
+
error: { code: "forbidden", message: "Self consent must be for the logged-in user; the emails differ." },
|
|
282
|
+
recovery_steps: [{ command: "naive voice clone <file> ... --consent-type third_party_attested --consenter-email " + opts.consenterEmail, description: "Use third-party consent for someone else" }],
|
|
283
|
+
});
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
// ── File checks (size pre-check for a clean error before sending) ────────────
|
|
288
|
+
const filePath = resolve(process.cwd(), file);
|
|
289
|
+
let size;
|
|
290
|
+
try {
|
|
291
|
+
size = statSync(filePath).size;
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
agentError({
|
|
295
|
+
action: "voice.clone",
|
|
296
|
+
error: { code: "invalid_input", message: `Audio file not found: ${filePath}` },
|
|
297
|
+
recovery_steps: [{ command: "naive voice clone /path/to/sample.m4a ...", description: "Point at an existing audio file" }],
|
|
298
|
+
});
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (size > MAX_SAMPLE_BYTES) {
|
|
302
|
+
agentError({
|
|
303
|
+
action: "voice.clone",
|
|
304
|
+
error: { code: "invalid_input", message: `Sample is ${(size / 1048576).toFixed(1)}MB; max is 25MB.` },
|
|
305
|
+
recovery_steps: [{ command: "# trim or compress the audio to <=25MB", description: "Shorten the clip" }],
|
|
306
|
+
});
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
// ── Step 1: profile + consent (or resume) ───────────────────────────────────
|
|
310
|
+
let profileId = opts.profileId;
|
|
311
|
+
if (!profileId) {
|
|
312
|
+
// G4: don't spawn a duplicate draft — surface an existing one to resume.
|
|
313
|
+
const listResp = await sessionRequest("GET", "/v1/voice-admin/profiles");
|
|
314
|
+
handleApiError("voice.clone", listResp);
|
|
315
|
+
const existing = (listResp.data.profiles ?? [])
|
|
316
|
+
.find((p) => p.displayName === opts.name && p.status === "draft");
|
|
317
|
+
if (existing) {
|
|
318
|
+
agentError({
|
|
319
|
+
action: "voice.clone",
|
|
320
|
+
error: { code: "duplicate_draft", message: `A draft voice named "${opts.name}" already exists (${existing.id}).`, hint: "Resume it or choose a different name." },
|
|
321
|
+
recovery_steps: [
|
|
322
|
+
{ command: `naive voice clone ${file} --profile-id ${existing.id} --name "${opts.name}" --consent-type ${opts.consentType} --consenter-name "${opts.consenterName}" --attestation "..." --i-affirm`, description: "Resume the existing draft" },
|
|
323
|
+
{ command: `naive voice clone ${file} --name "<different name>" ...`, description: "Start fresh under a new name" },
|
|
324
|
+
],
|
|
325
|
+
});
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const consent = {
|
|
329
|
+
consent_type: opts.consentType,
|
|
330
|
+
consenter_name: opts.consenterName,
|
|
331
|
+
attestation_text: opts.attestation,
|
|
332
|
+
};
|
|
333
|
+
if (opts.consenterEmail)
|
|
334
|
+
consent.consenting_email = opts.consenterEmail;
|
|
335
|
+
if (opts.authorizedUses) {
|
|
336
|
+
consent.authorized_uses = String(opts.authorizedUses).split(",").map((s) => s.trim()).filter(Boolean);
|
|
337
|
+
}
|
|
338
|
+
// Attested: record the accepted ToS version (the liability basis the server requires).
|
|
339
|
+
if (opts.consentType === "third_party_attested")
|
|
340
|
+
consent.tos_version = VOICE_TOS_VERSION;
|
|
341
|
+
const createResp = await sessionRequest("POST", "/v1/voice-admin/profiles", {
|
|
342
|
+
body: {
|
|
343
|
+
display_name: opts.name,
|
|
344
|
+
scope: opts.scope,
|
|
345
|
+
...(opts.agentId && { agent_id: opts.agentId }),
|
|
346
|
+
consent,
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
|
+
handleApiError("voice.clone", createResp);
|
|
350
|
+
profileId = createResp.data.profile_id;
|
|
351
|
+
}
|
|
352
|
+
// ── Step 2: upload the sample ───────────────────────────────────────────────
|
|
353
|
+
// The server validates the sample by file extension (filename), not content type,
|
|
354
|
+
// so we don't set one (matches media.ts; providers sniff the codec bytes anyway).
|
|
355
|
+
const bytes = readFileSync(filePath);
|
|
356
|
+
const form = new FormData();
|
|
357
|
+
form.append("file", new Blob([new Uint8Array(bytes)]), basename(filePath));
|
|
358
|
+
const sampleResp = await sessionRequest("POST", `/v1/voice-admin/profiles/${profileId}/samples`, {
|
|
359
|
+
multipart: form,
|
|
360
|
+
});
|
|
361
|
+
handleApiError("voice.clone", sampleResp);
|
|
362
|
+
const sampleId = sampleResp.data.sample_id;
|
|
363
|
+
// ── Step 3: VERIFIED tier stops here — clone can't kick until the owner confirms.
|
|
364
|
+
// (self + attested are live at creation and fall through to Step 4.)
|
|
365
|
+
if (opts.consentType === "third_party_verified") {
|
|
366
|
+
agentOutput({
|
|
367
|
+
action: "voice.clone",
|
|
368
|
+
result: {
|
|
369
|
+
profile_id: profileId,
|
|
370
|
+
sample_id: sampleId,
|
|
371
|
+
consent_type: opts.consentType,
|
|
372
|
+
status: "awaiting_consent_confirmation",
|
|
373
|
+
},
|
|
374
|
+
next_steps: [
|
|
375
|
+
{ command: `# ${opts.consenterEmail} must confirm consent before the clone can be kicked`, description: "Owner confirmation round-trip" },
|
|
376
|
+
{ command: "naive voice list", description: "Once confirmed + cloned, the voice appears as ready" },
|
|
377
|
+
],
|
|
378
|
+
hints: ["Verified consent must be confirmed by the owner before cloning starts. --wait has no effect until then."],
|
|
379
|
+
});
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
// ── Step 4: kick the clone (self + attested are live now) ────────────────────
|
|
383
|
+
const cloneResp = await sessionRequest("POST", `/v1/voice-admin/profiles/${profileId}/clone`, {
|
|
384
|
+
headers: { "Idempotency-Key": `clone-${profileId}` },
|
|
385
|
+
});
|
|
386
|
+
let jobId;
|
|
387
|
+
if (cloneResp.status >= 400) {
|
|
388
|
+
// A timeout-then-retry can hit an already-kicked profile — treat as "already kicked".
|
|
389
|
+
const code = cloneResp.data?.error?.code;
|
|
390
|
+
if (code !== "duplicate_request") {
|
|
391
|
+
handleApiError("voice.clone", cloneResp);
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
jobId = cloneResp.data.job_id;
|
|
397
|
+
}
|
|
398
|
+
// ── Step 5: optional wait ───────────────────────────────────────────────────
|
|
399
|
+
if (!opts.wait) {
|
|
400
|
+
agentOutput({
|
|
401
|
+
action: "voice.clone",
|
|
402
|
+
result: { profile_id: profileId, sample_id: sampleId, job_id: jobId, status: "pending" },
|
|
403
|
+
next_steps: [
|
|
404
|
+
{ command: `naive voice clone ${file} --profile-id ${profileId} --name "${opts.name}" --consent-type self --consenter-name "${opts.consenterName}" --attestation "..." --i-affirm --wait`, description: "Wait for the clone to finish" },
|
|
405
|
+
{ command: "naive voice list", description: "Check when status becomes ready" },
|
|
406
|
+
],
|
|
407
|
+
hints: ["Clone kicked — it runs asynchronously. Poll with --wait or `naive voice list`."],
|
|
408
|
+
});
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
const outcome = await pollUntilReady(profileId);
|
|
412
|
+
if (outcome === "ready") {
|
|
413
|
+
agentOutput({
|
|
414
|
+
action: "voice.clone",
|
|
415
|
+
result: { profile_id: profileId, status: "ready" },
|
|
416
|
+
next_steps: [{ command: `naive voice say --voice ${profileId} --text "Hello"`, description: "Synthesize speech in the new voice" }],
|
|
417
|
+
hints: ["Voice cloned and ready."],
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
else if (outcome === "failed") {
|
|
421
|
+
agentError({
|
|
422
|
+
action: "voice.clone",
|
|
423
|
+
error: { code: "clone_failed", message: "The clone job failed.", hint: "Check the sample audio quality and retry." },
|
|
424
|
+
recovery_steps: [{ command: `naive voice clone ${file} --profile-id ${profileId} ... --wait`, description: "Retry on the same profile" }],
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
// timeout — NOT a failure; the clone may still complete.
|
|
429
|
+
agentOutput({
|
|
430
|
+
action: "voice.clone",
|
|
431
|
+
result: { profile_id: profileId, status: "pending", note: "timed_out_waiting" },
|
|
432
|
+
next_steps: [{ command: "naive voice list", description: "Check status later — the clone may still complete" }],
|
|
433
|
+
hints: ["Still processing after 10m. This is not a failure; check back with `naive voice list`."],
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
voiceCmd
|
|
438
|
+
.command("revoke")
|
|
439
|
+
.alias("delete")
|
|
440
|
+
.description("(Human-only) Revoke/delete a voice — IRREVERSIBLY erases it + its audio. Requires `naive auth session-login`")
|
|
441
|
+
.argument("<id>", "Voice profile id")
|
|
442
|
+
.option("--reason <text>", "Reason recorded on the consent record", "revoked via CLI")
|
|
443
|
+
.option("--yes", "Confirm the irreversible erasure (REQUIRED for non-interactive use)")
|
|
444
|
+
.action(async (id, opts) => {
|
|
445
|
+
// Destructive-op guard (fail-safe): revoke is irreversible biometric erasure (samples + synth
|
|
446
|
+
// audio + provider voice). Never erase without an explicit signal.
|
|
447
|
+
if (!opts.yes) {
|
|
448
|
+
if (isInteractive()) {
|
|
449
|
+
// Type-to-confirm (GitHub-delete pattern). Resolve the display name so it's meaningful.
|
|
450
|
+
let name = id;
|
|
451
|
+
try {
|
|
452
|
+
const r = await sessionRequest("GET", `/v1/voice-admin/profiles/${id}`);
|
|
453
|
+
const n = r.data?.profile?.displayName;
|
|
454
|
+
if (n)
|
|
455
|
+
name = n;
|
|
456
|
+
}
|
|
457
|
+
catch {
|
|
458
|
+
/* fall back to id */
|
|
459
|
+
}
|
|
460
|
+
process.stdout.write(`\n⚠ This permanently erases the voice "${name}" and all its audio. This cannot be undone.\n`);
|
|
461
|
+
if (!(await confirmExact(`Type the voice name (${name}) to confirm`, name))) {
|
|
462
|
+
agentError({
|
|
463
|
+
action: "voice.revoke",
|
|
464
|
+
error: { code: "cancelled", message: "Name did not match — nothing was deleted." },
|
|
465
|
+
recovery_steps: [{ command: `naive voice revoke ${id}`, description: "Try again" }],
|
|
466
|
+
});
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
471
|
+
// Non-interactive + no --yes → FAIL SAFE. Do not silently erase biometric data.
|
|
472
|
+
agentError({
|
|
473
|
+
action: "voice.revoke",
|
|
474
|
+
error: {
|
|
475
|
+
code: "confirmation_required",
|
|
476
|
+
message: "Revoking permanently erases this voice and its audio (irreversible). Re-run with --yes to confirm in a non-interactive context.",
|
|
477
|
+
},
|
|
478
|
+
recovery_steps: [{ command: `naive voice revoke ${id} --yes`, description: "Confirm the irreversible erasure" }],
|
|
479
|
+
});
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
const resp = await sessionRequest("POST", `/v1/voice-admin/profiles/${id}/revoke`, {
|
|
484
|
+
body: { reason: opts.reason },
|
|
485
|
+
});
|
|
486
|
+
handleApiError("voice.revoke", resp);
|
|
487
|
+
agentOutput({
|
|
488
|
+
action: "voice.revoke",
|
|
489
|
+
result: { voice_id: id, status: "revoked" },
|
|
490
|
+
next_steps: [{ command: "naive voice list", description: "Confirm the voice is no longer available" }],
|
|
491
|
+
hints: ["Voice revoked. In-flight streams are aborted and synthesis is blocked immediately."],
|
|
492
|
+
});
|
|
493
|
+
});
|
|
494
|
+
/** Poll a profile until ready/failed, bounded by WAIT_TIMEOUT_MS. Returns the outcome. */
|
|
495
|
+
async function pollUntilReady(profileId) {
|
|
496
|
+
const start = Date.now();
|
|
497
|
+
let warned = false;
|
|
498
|
+
for (;;) {
|
|
499
|
+
const r = await sessionRequest("GET", `/v1/voice-admin/profiles/${profileId}`);
|
|
500
|
+
handleApiError("voice.clone", r);
|
|
501
|
+
const status = r.data.profile?.status;
|
|
502
|
+
if (status === "ready")
|
|
503
|
+
return "ready";
|
|
504
|
+
if (status === "failed")
|
|
505
|
+
return "failed";
|
|
506
|
+
const elapsed = Date.now() - start;
|
|
507
|
+
if (elapsed >= WAIT_TIMEOUT_MS)
|
|
508
|
+
return "timeout";
|
|
509
|
+
if (!warned && elapsed >= WAIT_WARN_MS) {
|
|
510
|
+
console.error("Still cloning after 2m — verify the API clone worker (startVoiceSchedulers) is running.");
|
|
511
|
+
warned = true;
|
|
512
|
+
}
|
|
513
|
+
await new Promise((res) => setTimeout(res, WAIT_INTERVAL_MS));
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
//# sourceMappingURL=voice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice.js","sourceRoot":"","sources":["../../src/commands/voice.ts"],"names":[],"mappings":"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"}
|