faces-cli 1.4.1 → 1.4.3

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.
@@ -72,7 +72,7 @@ export default class CompileImport extends BaseCommand {
72
72
  this.log(`label: ${thread.label}`);
73
73
  this.log(``);
74
74
  this.log(`Next step:`);
75
- this.log(` faces compile:thread:sync ${thread.thread_id}`);
75
+ this.log(` faces compile:thread:make ${thread.thread_id}`);
76
76
  }
77
77
  }
78
78
  return data;
@@ -0,0 +1,14 @@
1
+ import { BaseCommand } from '../../../base.js';
2
+ export default class CompileThreadMake extends BaseCommand {
3
+ static description: string;
4
+ static flags: {
5
+ timeout: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
6
+ 'base-url': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ 'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ };
10
+ static args: {
11
+ thread_id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
12
+ };
13
+ run(): Promise<unknown>;
14
+ }
@@ -0,0 +1,56 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { BaseCommand } from '../../../base.js';
3
+ import { FacesAPIError } from '../../../client.js';
4
+ import { pollCompileProgress } from '../../../poll.js';
5
+ export default class CompileThreadMake extends BaseCommand {
6
+ static description = 'Compile an existing thread (prepare + sync in one step)';
7
+ static flags = {
8
+ ...BaseCommand.baseFlags,
9
+ timeout: Flags.integer({ description: 'Compile timeout in seconds (default: 600)', default: 600 }),
10
+ };
11
+ static args = {
12
+ thread_id: Args.string({ description: 'Thread ID', required: true }),
13
+ };
14
+ async run() {
15
+ const { args, flags } = await this.parse(CompileThreadMake);
16
+ const client = this.makeClient(flags);
17
+ const json = this.jsonEnabled();
18
+ let makeResponse;
19
+ try {
20
+ makeResponse = await client.post(`/v1/compile/threads/${args.thread_id}/make`);
21
+ }
22
+ catch (err) {
23
+ if (err instanceof FacesAPIError)
24
+ this.error(`Error (${err.statusCode}): ${err.message}`);
25
+ throw err;
26
+ }
27
+ const chunksTotal = makeResponse.chunks_total;
28
+ if (!json)
29
+ process.stderr.write(`Compiling${chunksTotal ? ` (${chunksTotal} chunks)` : ''}:\n`);
30
+ let result;
31
+ try {
32
+ result = await pollCompileProgress(client, args.thread_id, {
33
+ timeoutMs: flags.timeout * 1000,
34
+ endpoint: `/v1/compile/threads/${args.thread_id}`,
35
+ onProgress: (p) => {
36
+ if (!json) {
37
+ const c = p.current_counts;
38
+ const counts = c ? `ε=${c.epsilon} β=${c.beta} δ=${c.delta} α=${c.alpha}` : '';
39
+ const phase = p.prepare_status === 'syncing' ? ' (syncing)' : '';
40
+ process.stderr.write(` [${p.chunks_completed ?? '?'}/${p.chunks_total ?? '?'}] ${counts}${phase}\n`);
41
+ }
42
+ },
43
+ });
44
+ }
45
+ catch (err) {
46
+ if (err instanceof Error)
47
+ this.error(err.message);
48
+ throw err;
49
+ }
50
+ if (!json)
51
+ process.stderr.write('Done.\n');
52
+ if (json)
53
+ this.log(JSON.stringify(result, null, 2));
54
+ return result;
55
+ }
56
+ }
@@ -4,6 +4,8 @@ export default class FaceUpload extends BaseCommand {
4
4
  static flags: {
5
5
  file: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
6
6
  kind: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ perspective: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
+ 'face-speaker': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
9
  'base-url': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
10
  token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
11
  'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
@@ -13,6 +13,14 @@ export default class FaceUpload extends BaseCommand {
13
13
  options: ['document', 'thread'],
14
14
  default: 'document',
15
15
  }),
16
+ perspective: Flags.string({
17
+ description: 'Perspective (document only)',
18
+ options: ['first-person', 'third-person'],
19
+ default: 'third-person',
20
+ }),
21
+ 'face-speaker': Flags.string({
22
+ description: 'Speaker name to map to the face (thread only). If omitted, first speaker is used.',
23
+ }),
16
24
  };
17
25
  static args = {
18
26
  face_id: Args.string({ description: 'Face ID or username', required: true }),
@@ -26,18 +34,33 @@ export default class FaceUpload extends BaseCommand {
26
34
  const fileBlob = new Blob([fs.readFileSync(flags.file)], { type: 'application/octet-stream' });
27
35
  const form = new FormData();
28
36
  form.append('file', fileBlob, filename);
29
- form.append('type', flags.kind);
37
+ // type, perspective, face_speaker are query params (not form fields)
38
+ const params = new URLSearchParams();
39
+ params.set('type', flags.kind);
40
+ params.set('perspective', flags.perspective);
41
+ if (flags['face-speaker'])
42
+ params.set('face_speaker', flags['face-speaker']);
30
43
  let data;
31
44
  try {
32
- data = await client.postForm(`/v1/faces/${args.face_id}/upload`, form);
45
+ data = await client.postForm(`/v1/faces/${args.face_id}/upload?${params}`, form);
33
46
  }
34
47
  catch (err) {
35
48
  if (err instanceof FacesAPIError)
36
49
  this.error(`Error (${err.statusCode}): ${err.message}`);
37
50
  throw err;
38
51
  }
39
- if (!this.jsonEnabled())
52
+ if (!this.jsonEnabled()) {
40
53
  this.printHuman(data);
54
+ const res = data;
55
+ if (flags.kind === 'thread' && res.thread_id) {
56
+ this.log(`\nNext step:`);
57
+ this.log(` faces compile:thread:make ${res.thread_id}`);
58
+ }
59
+ else if (flags.kind === 'document' && res.document_id) {
60
+ this.log(`\nNext step:`);
61
+ this.log(` faces compile:doc:make ${res.document_id}`);
62
+ }
63
+ }
41
64
  return data;
42
65
  }
43
66
  }
package/dist/poll.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Shared polling helper for document compile progress.
2
+ * Shared polling helper for compile progress (documents and threads).
3
3
  *
4
4
  * Works with both /make (preparing → syncing → synced) and
5
5
  * legacy /prepare (processing → ready) status flows.
@@ -20,11 +20,13 @@ export interface PollOptions {
20
20
  intervalMs?: number;
21
21
  timeoutMs?: number;
22
22
  onProgress?: (p: PollProgress) => void;
23
+ /** Override the GET endpoint path. Defaults to /v1/compile/documents/{id}. */
24
+ endpoint?: string;
23
25
  }
24
26
  /**
25
- * Poll GET /compile/documents/{docId} until a terminal status is reached.
27
+ * Poll a compile GET endpoint until a terminal status is reached.
26
28
  * Terminal statuses: "synced" (from /make), "ready" (from /prepare), "failed".
27
29
  * Returns the final GET response.
28
30
  * Throws on timeout or failure.
29
31
  */
30
- export declare function pollCompileProgress(client: FacesClient, docId: string, opts?: PollOptions): Promise<unknown>;
32
+ export declare function pollCompileProgress(client: FacesClient, id: string, opts?: PollOptions): Promise<unknown>;
package/dist/poll.js CHANGED
@@ -1,20 +1,21 @@
1
1
  /**
2
- * Poll GET /compile/documents/{docId} until a terminal status is reached.
2
+ * Poll a compile GET endpoint until a terminal status is reached.
3
3
  * Terminal statuses: "synced" (from /make), "ready" (from /prepare), "failed".
4
4
  * Returns the final GET response.
5
5
  * Throws on timeout or failure.
6
6
  */
7
- export async function pollCompileProgress(client, docId, opts = {}) {
7
+ export async function pollCompileProgress(client, id, opts = {}) {
8
8
  const interval = opts.intervalMs ?? 3000;
9
9
  const timeout = opts.timeoutMs ?? 600_000;
10
10
  const start = Date.now();
11
+ const endpoint = opts.endpoint ?? `/v1/compile/documents/${id}`;
11
12
  let lastChunks = -1;
12
13
  while (true) {
13
14
  if (Date.now() - start > timeout) {
14
15
  throw new Error(`Compile timed out after ${Math.round(timeout / 1000)}s`);
15
16
  }
16
17
  await sleep(interval);
17
- const data = await client.get(`/v1/compile/documents/${docId}`);
18
+ const data = await client.get(endpoint);
18
19
  const progress = {
19
20
  prepare_status: data.prepare_status ?? null,
20
21
  chunks_total: data.chunks_total ?? null,