faces-cli 1.7.5 → 1.7.7
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/dist/commands/chat/chat.js +8 -0
- package/dist/commands/face/get.js +2 -0
- package/dist/commands/face/list.js +2 -0
- package/dist/commands/{voiceprint/get.d.ts → face/lock.d.ts} +2 -2
- package/dist/commands/face/lock.js +34 -0
- package/dist/commands/{voiceprint/revert.d.ts → face/unlock.d.ts} +2 -2
- package/dist/commands/face/unlock.js +34 -0
- package/dist/utils.d.ts +0 -15
- package/dist/utils.js +0 -75
- package/oclif.manifest.json +793 -1579
- package/package.json +1 -1
- package/dist/commands/billing/quota.d.ts +0 -10
- package/dist/commands/billing/quota.js +0 -12
- package/dist/commands/billing/subscription.d.ts +0 -10
- package/dist/commands/billing/subscription.js +0 -24
- package/dist/commands/face/upload.d.ts +0 -17
- package/dist/commands/face/upload.js +0 -66
- package/dist/commands/voiceprint/build-status.d.ts +0 -14
- package/dist/commands/voiceprint/build-status.js +0 -46
- package/dist/commands/voiceprint/build.d.ts +0 -23
- package/dist/commands/voiceprint/build.js +0 -109
- package/dist/commands/voiceprint/get.js +0 -47
- package/dist/commands/voiceprint/refine-status.d.ts +0 -14
- package/dist/commands/voiceprint/refine-status.js +0 -43
- package/dist/commands/voiceprint/refine.d.ts +0 -23
- package/dist/commands/voiceprint/refine.js +0 -88
- package/dist/commands/voiceprint/revert.js +0 -36
- package/dist/commands/voiceprint/score-status.d.ts +0 -14
- package/dist/commands/voiceprint/score-status.js +0 -46
- package/dist/commands/voiceprint/score.d.ts +0 -24
- package/dist/commands/voiceprint/score.js +0 -114
- package/dist/commands/voiceprint/upload.d.ts +0 -17
- package/dist/commands/voiceprint/upload.js +0 -66
- package/dist/commands/voiceprint/versions.d.ts +0 -14
- package/dist/commands/voiceprint/versions.js +0 -44
- package/dist/voiceprint.d.ts +0 -28
- package/dist/voiceprint.js +0 -55
|
@@ -195,6 +195,14 @@ export default class ChatChat extends BaseCommand {
|
|
|
195
195
|
};
|
|
196
196
|
if (flags.system)
|
|
197
197
|
payload.instructions = flags.system;
|
|
198
|
+
// Responses names the output cap `max_output_tokens`, not `max_tokens`.
|
|
199
|
+
// `temperature` is accepted per-model (gpt-5.1/5.2/5.4 yes; gpt-5.5/5.6-*/o3
|
|
200
|
+
// no) with no capability flag to query, so we always send what the user asked
|
|
201
|
+
// for — the backend strips the param and retries when a model 400s on it.
|
|
202
|
+
if (flags['max-tokens'])
|
|
203
|
+
payload.max_output_tokens = flags['max-tokens'];
|
|
204
|
+
if (flags.temperature !== undefined)
|
|
205
|
+
payload.temperature = Number.parseFloat(flags.temperature);
|
|
198
206
|
if (flags['oauth-only'])
|
|
199
207
|
payload.oauth_only = true;
|
|
200
208
|
if (flags.stream) {
|
|
@@ -39,6 +39,8 @@ export default class FaceGet extends BaseCommand {
|
|
|
39
39
|
this.log(`name: ${f.name}`);
|
|
40
40
|
this.log(`owned_by: ${f.owned_by}`);
|
|
41
41
|
this.log(`created: ${new Date(f.created * 1000).toISOString().slice(0, 10)}`);
|
|
42
|
+
if (f.read_only)
|
|
43
|
+
this.log('read only');
|
|
42
44
|
if (f.formula) {
|
|
43
45
|
this.log(`formula: ${f.formula}`);
|
|
44
46
|
this.log(`type: composite`);
|
|
@@ -102,6 +102,8 @@ export default class FaceList extends BaseCommand {
|
|
|
102
102
|
}
|
|
103
103
|
if (f.published)
|
|
104
104
|
suffix += ' [public · requires @model]';
|
|
105
|
+
if (f.read_only)
|
|
106
|
+
suffix += ' [read only]';
|
|
105
107
|
this.log(`${handle(f).padEnd(handleWidth)} ${f.name.padEnd(nameWidth)}${suffix}`);
|
|
106
108
|
}
|
|
107
109
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base.js';
|
|
2
|
-
export default class
|
|
2
|
+
export default class FaceLock extends BaseCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static flags: {
|
|
@@ -8,7 +8,7 @@ export default class VoiceprintGet extends BaseCommand {
|
|
|
8
8
|
'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
9
|
};
|
|
10
10
|
static args: {
|
|
11
|
-
|
|
11
|
+
face_id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
12
12
|
};
|
|
13
13
|
run(): Promise<unknown>;
|
|
14
14
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
import { FacesAPIError } from '../../client.js';
|
|
4
|
+
export default class FaceLock extends BaseCommand {
|
|
5
|
+
static description = 'Lock a face (read-only). A locked face still reads and chats normally, but it — and everything it owns (documents, threads, voiceprint) — cannot be changed until unlocked.';
|
|
6
|
+
static examples = ['<%= config.bin %> <%= command.id %> socrates'];
|
|
7
|
+
static flags = {
|
|
8
|
+
...BaseCommand.baseFlags,
|
|
9
|
+
};
|
|
10
|
+
static args = {
|
|
11
|
+
face_id: Args.string({ description: 'Face alias', required: true }),
|
|
12
|
+
};
|
|
13
|
+
async run() {
|
|
14
|
+
const { args, flags } = await this.parse(FaceLock);
|
|
15
|
+
const client = this.makeClient(flags);
|
|
16
|
+
let data;
|
|
17
|
+
try {
|
|
18
|
+
data = await client.patch(`/v1/faces/${args.face_id}/lock`, { body: { read_only: true } });
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
if (err instanceof FacesAPIError)
|
|
22
|
+
this.error(`Error (${err.statusCode}): ${err.message}`);
|
|
23
|
+
throw err;
|
|
24
|
+
}
|
|
25
|
+
if (!this.jsonEnabled()) {
|
|
26
|
+
const res = data;
|
|
27
|
+
this.log(`Locked '${res.alias ?? args.face_id}' — read only.`);
|
|
28
|
+
const affected = res.affected ?? [];
|
|
29
|
+
if (affected.length > 0)
|
|
30
|
+
this.log(`Affected: ${affected.join(', ')}`);
|
|
31
|
+
}
|
|
32
|
+
return data;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base.js';
|
|
2
|
-
export default class
|
|
2
|
+
export default class FaceUnlock extends BaseCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static flags: {
|
|
@@ -8,7 +8,7 @@ export default class VoiceprintRevert extends BaseCommand {
|
|
|
8
8
|
'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
9
|
};
|
|
10
10
|
static args: {
|
|
11
|
-
|
|
11
|
+
face_id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
12
12
|
};
|
|
13
13
|
run(): Promise<unknown>;
|
|
14
14
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
import { FacesAPIError } from '../../client.js';
|
|
4
|
+
export default class FaceUnlock extends BaseCommand {
|
|
5
|
+
static description = 'Unlock a face (make it writable again). Thaws the face and everything it owns (documents, threads, voiceprint).';
|
|
6
|
+
static examples = ['<%= config.bin %> <%= command.id %> socrates'];
|
|
7
|
+
static flags = {
|
|
8
|
+
...BaseCommand.baseFlags,
|
|
9
|
+
};
|
|
10
|
+
static args = {
|
|
11
|
+
face_id: Args.string({ description: 'Face alias', required: true }),
|
|
12
|
+
};
|
|
13
|
+
async run() {
|
|
14
|
+
const { args, flags } = await this.parse(FaceUnlock);
|
|
15
|
+
const client = this.makeClient(flags);
|
|
16
|
+
let data;
|
|
17
|
+
try {
|
|
18
|
+
data = await client.patch(`/v1/faces/${args.face_id}/lock`, { body: { read_only: false } });
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
if (err instanceof FacesAPIError)
|
|
22
|
+
this.error(`Error (${err.statusCode}): ${err.message}`);
|
|
23
|
+
throw err;
|
|
24
|
+
}
|
|
25
|
+
if (!this.jsonEnabled()) {
|
|
26
|
+
const res = data;
|
|
27
|
+
this.log(`Unlocked '${res.alias ?? args.face_id}' — writable.`);
|
|
28
|
+
const affected = res.affected ?? [];
|
|
29
|
+
if (affected.length > 0)
|
|
30
|
+
this.log(`Affected: ${affected.join(', ')}`);
|
|
31
|
+
}
|
|
32
|
+
return data;
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,20 +1,5 @@
|
|
|
1
1
|
/** Max length of a face's profile_addendum (per-face system prompt). Mirrors the backend. */
|
|
2
2
|
export declare const PROFILE_ADDENDUM_MAX_CHARS = 100000;
|
|
3
|
-
export interface VoiceprintEmail {
|
|
4
|
-
id: string;
|
|
5
|
-
text: string;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* Load voiceprint writing samples from a JSON/JSONL file or a directory.
|
|
9
|
-
*
|
|
10
|
-
* - `file`: a JSON array of `{id?, text}` objects or plain strings, OR JSONL
|
|
11
|
-
* (one such value per line). The format is auto-detected.
|
|
12
|
-
* - `dir`: one sample per non-hidden file; `id` is the filename (sans extension),
|
|
13
|
-
* `text` is the file contents. Files are sorted by name; empty files are skipped.
|
|
14
|
-
*
|
|
15
|
-
* Throws on a missing path, malformed content, or no usable samples.
|
|
16
|
-
*/
|
|
17
|
-
export declare function loadVoiceprintEmails(file: string | undefined, dir: string | undefined): VoiceprintEmail[];
|
|
18
3
|
/**
|
|
19
4
|
* Resolve a face's profile_addendum from the `--profile-addendum` / `--profile-addendum-file`
|
|
20
5
|
* flags. Returns undefined when neither is given (field left unchanged). Throws on a missing
|
package/dist/utils.js
CHANGED
|
@@ -1,81 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
/** Max length of a face's profile_addendum (per-face system prompt). Mirrors the backend. */
|
|
4
3
|
export const PROFILE_ADDENDUM_MAX_CHARS = 100_000;
|
|
5
|
-
function itemToEmail(item, i, where) {
|
|
6
|
-
if (typeof item === 'string')
|
|
7
|
-
return { id: `m${i + 1}`, text: item };
|
|
8
|
-
if (item && typeof item === 'object' && typeof item.text === 'string') {
|
|
9
|
-
const obj = item;
|
|
10
|
-
return { id: obj.id !== undefined ? String(obj.id) : `m${i + 1}`, text: obj.text };
|
|
11
|
-
}
|
|
12
|
-
throw new Error(`${where} must be a string or an object with a "text" field`);
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Load voiceprint writing samples from a JSON/JSONL file or a directory.
|
|
16
|
-
*
|
|
17
|
-
* - `file`: a JSON array of `{id?, text}` objects or plain strings, OR JSONL
|
|
18
|
-
* (one such value per line). The format is auto-detected.
|
|
19
|
-
* - `dir`: one sample per non-hidden file; `id` is the filename (sans extension),
|
|
20
|
-
* `text` is the file contents. Files are sorted by name; empty files are skipped.
|
|
21
|
-
*
|
|
22
|
-
* Throws on a missing path, malformed content, or no usable samples.
|
|
23
|
-
*/
|
|
24
|
-
export function loadVoiceprintEmails(file, dir) {
|
|
25
|
-
if (dir !== undefined) {
|
|
26
|
-
if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory())
|
|
27
|
-
throw new Error(`Directory not found: ${dir}`);
|
|
28
|
-
const emails = [];
|
|
29
|
-
const names = fs.readdirSync(dir).filter((n) => !n.startsWith('.')).sort();
|
|
30
|
-
for (const name of names) {
|
|
31
|
-
const full = path.join(dir, name);
|
|
32
|
-
if (!fs.statSync(full).isFile())
|
|
33
|
-
continue;
|
|
34
|
-
const text = fs.readFileSync(full, 'utf8').trim();
|
|
35
|
-
if (!text)
|
|
36
|
-
continue;
|
|
37
|
-
emails.push({ id: name.replace(/\.[^.]+$/, ''), text });
|
|
38
|
-
}
|
|
39
|
-
if (emails.length === 0)
|
|
40
|
-
throw new Error(`No usable files found in ${dir}`);
|
|
41
|
-
return emails;
|
|
42
|
-
}
|
|
43
|
-
if (file !== undefined) {
|
|
44
|
-
if (!fs.existsSync(file))
|
|
45
|
-
throw new Error(`File not found: ${file}`);
|
|
46
|
-
const raw = fs.readFileSync(file, 'utf8');
|
|
47
|
-
// Try a single JSON array first; fall back to JSONL (one value per line).
|
|
48
|
-
let items;
|
|
49
|
-
let asArray;
|
|
50
|
-
try {
|
|
51
|
-
asArray = JSON.parse(raw);
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
asArray = undefined;
|
|
55
|
-
}
|
|
56
|
-
if (Array.isArray(asArray)) {
|
|
57
|
-
items = asArray;
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
const lines = raw.split('\n').map((l) => l.trim()).filter(Boolean);
|
|
61
|
-
if (lines.length === 0)
|
|
62
|
-
throw new Error(`${file} contains no samples`);
|
|
63
|
-
items = lines.map((line, i) => {
|
|
64
|
-
try {
|
|
65
|
-
return JSON.parse(line);
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
throw new Error(`${file} is neither a JSON array nor valid JSONL (line ${i + 1} did not parse)`);
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
const emails = items.map((item, i) => itemToEmail(item, i, `${file}[${i}]`));
|
|
73
|
-
if (emails.length === 0)
|
|
74
|
-
throw new Error(`${file} contains no samples`);
|
|
75
|
-
return emails;
|
|
76
|
-
}
|
|
77
|
-
throw new Error('Provide --emails <file> or --emails-dir <dir>');
|
|
78
|
-
}
|
|
79
4
|
/**
|
|
80
5
|
* Resolve a face's profile_addendum from the `--profile-addendum` / `--profile-addendum-file`
|
|
81
6
|
* flags. Returns undefined when neither is given (field left unchanged). Throws on a missing
|