utilitas 1999.1.56 → 1999.1.58

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/lib/gen.mjs CHANGED
@@ -1,8 +1,12 @@
1
- import { ensureString, need, throwError, tryUntil } from './utilitas.mjs';
2
- import { MIME_PNG, convert } from './storage.mjs';
1
+ import {
2
+ ensureString, log as _log, need, throwError, tryUntil,
3
+ } from './utilitas.mjs';
3
4
 
4
- const _NEED = ['OpenAI'];
5
+ import { convert, MIME_PNG } from './storage.mjs';
6
+ import { assertCommand, exec } from './shell.mjs';
5
7
 
8
+ const _NEED = ['OpenAI'];
9
+ const log = (cnt, opt) => _log(cnt, import.meta.url, { time: 1, ...opt || {} });
6
10
  const [
7
11
  clients, OPENAI, GEMINI, BASE64, BUFFER, ERROR_GENERATING, IMAGEN_MODEL,
8
12
  OPENAI_MODEL, VEO_MODEL,
@@ -13,8 +17,8 @@ const [
13
17
 
14
18
  const init = async (options) => {
15
19
  assert(
16
- options?.apiKey || (options?.projectId && options?.accessToken),
17
- 'API key or project ID (with access token) are required.'
20
+ options?.apiKey || (options?.credentials && options?.projectId),
21
+ 'API key or credentials are required.'
18
22
  );
19
23
  const provider = ensureString(options?.provider, { case: 'UP' });
20
24
  switch (provider) {
@@ -27,7 +31,7 @@ const init = async (options) => {
27
31
  clients[provider] = {
28
32
  apiKey: options.apiKey,
29
33
  projectId: options.projectId,
30
- accessToken: options.accessToken,
34
+ credentials: options.credentials,
31
35
  };
32
36
  break;
33
37
  default:
@@ -46,7 +50,7 @@ const extractVideo = async (data, options) => await convert(
46
50
 
47
51
  const generateImage = async (prompt, options) => {
48
52
  let provider = ensureString(options?.provider, { case: 'UP' });
49
- if (!provider && clients?.[GEMINI] && client.apiKey) { provider = GEMINI; }
53
+ if (!provider && clients?.[GEMINI]?.apiKey) { provider = GEMINI; }
50
54
  if (!provider && clients?.[OPENAI]) { provider = OPENAI; }
51
55
  const client = clients?.[provider];
52
56
  const n = options?.n || 4;
@@ -105,7 +109,20 @@ const generateImage = async (prompt, options) => {
105
109
  }
106
110
  };
107
111
 
108
- const getGeminiVideo = async (jobId) => {
112
+ const getGeminiAccessToken = async (credentials) => {
113
+ await assertCommand('gcloud');
114
+ const actResp = await exec(
115
+ `gcloud auth activate-service-account --key-file=${credentials}`,
116
+ { acceptError: true }
117
+ );
118
+ assert(actResp.includes('Activated service account credentials'),
119
+ 'Failed to activate service account credentials.', 500);
120
+ const tokResp = (await exec(`gcloud auth print-access-token`)).trim();
121
+ assert(tokResp, 'Failed to get access token.', 500);
122
+ return tokResp;
123
+ };
124
+
125
+ const getGeminiVideo = async (jobId, accessToken) => {
109
126
  const client = clients?.[GEMINI];
110
127
  assert(client, 'No available video generation provider.');
111
128
  const resp = await (await fetch(
@@ -114,26 +131,23 @@ const getGeminiVideo = async (jobId) => {
114
131
  + `${VEO_MODEL}:fetchPredictOperation`, {
115
132
  method: 'POST', headers: {
116
133
  'Content-Type': 'application/json',
117
- 'Authorization': `Bearer ${client.accessToken}`,
118
- },
119
- body: JSON.stringify({
120
- operationName: jobId,
121
- })
134
+ 'Authorization': `Bearer ${accessToken}`,
135
+ }, body: JSON.stringify({ operationName: jobId })
122
136
  })).json();
123
- assert(
124
- resp?.response?.videos?.length,
125
- `Waiting for Gemini video generation: \`${jobId}\`...`
126
- );
137
+ assert(resp?.response?.videos?.length,
138
+ 'Waiting for Gemini video generation: '
139
+ + jobId.replace(/^.*\/([^/]+)$/, '$1'));
127
140
  return resp?.response?.videos;
128
141
  };
129
142
 
130
143
  const generateVideo = async (prompt, options) => {
131
144
  let provider = ensureString(options?.provider, { case: 'UP' });
132
- if (!provider && clients?.[GEMINI] && client.accessToken) {
133
- provider = GEMINI;
134
- }
145
+ if (!provider
146
+ && clients?.[GEMINI]?.credentials
147
+ && clients?.[GEMINI]?.projectId) { provider = GEMINI; }
135
148
  const client = clients?.[provider];
136
149
  assert(client, 'No available video generation provider.');
150
+ const accessToken = await getGeminiAccessToken(client.credentials);
137
151
  prompt = ensureString(prompt);
138
152
  assert(prompt.length <= 4000,
139
153
  'Prompt must be less than 4000 characters.', 400);
@@ -149,7 +163,7 @@ const generateVideo = async (prompt, options) => {
149
163
  + `models/${VEO_MODEL}:predictLongRunning`, {
150
164
  method: 'POST', headers: {
151
165
  'Content-Type': 'application/json',
152
- 'Authorization': `Bearer ${client.accessToken}`,
166
+ 'Authorization': `Bearer ${accessToken}`,
153
167
  },
154
168
  body: JSON.stringify({
155
169
  instances: [{ prompt }], parameters: {
@@ -166,10 +180,9 @@ const generateVideo = async (prompt, options) => {
166
180
  resp?.error?.message || ERROR_GENERATING
167
181
  );
168
182
  if (options?.generateRaw) { return resp; }
169
- var videos = await tryUntil(
170
- async () => await getGeminiVideo(resp.name),
171
- { maxTry: 60 * 10, log: true }
172
- );
183
+ var videos = await tryUntil(async () => await getGeminiVideo(
184
+ resp.name, accessToken
185
+ ), { maxTry: 60 * 10, log });
173
186
  assert(videos?.length, 'Failed to generate Gemini video.');
174
187
  if (options?.videoRaw) { return videos; }
175
188
  return await Promise.all(videos.map(async x => ({
package/lib/manifest.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  const manifest = {
2
2
  "name": "utilitas",
3
3
  "description": "Just another common utility for JavaScript.",
4
- "version": "1999.1.56",
4
+ "version": "1999.1.58",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/Leask/utilitas",
7
7
  "main": "index.mjs",
package/lib/shell.mjs CHANGED
@@ -11,8 +11,10 @@ const exist = (bin) => { assertCommand(bin); return which(bin); };
11
11
  const exec = async (command, options = {}) => {
12
12
  assertCommand(command);
13
13
  const { stdout, stderr } = await pmsExec(command);
14
- assert(!stderr, stderr, 500);
15
- return stdout;
14
+ assert(options?.acceptError || !stderr, stderr, 500);
15
+ return options?.acceptError
16
+ ? [stdout, stderr].map(x => x.trim()).filter(x => x).join('\n')
17
+ : stdout.trim();
16
18
  };
17
19
 
18
20
  const which = async (bin) => {
@@ -28,4 +30,4 @@ const assertExist = async (bin, er, code = 500) => {
28
30
  };
29
31
 
30
32
  export default exec;
31
- export { assertExist, exec, exist, which };
33
+ export { assertCommand, assertExist, exec, exist, which };
package/lib/utilitas.mjs CHANGED
@@ -394,6 +394,7 @@ const log = (content, filename, options) => {
394
394
  const args = ['[' + color.red(name) + color.yellow(strTime) + ']'
395
395
  + (isErr ? '' : ` ${content}`)];
396
396
  if (isErr) { args.push(content); }
397
+ if (options?.return) { return args[0]; }
397
398
  return console.info.apply(null, args);
398
399
  };
399
400
 
@@ -669,12 +670,15 @@ const tryUntil = async (fnTry, options) => {
669
670
  interval: 1000 * 1, maxTry: Infinity, log: false, error: 'Operation failed.',
670
671
  verify: async (err, res) => { return !err; }, ...options || {}
671
672
  };
672
- let [curTry, result, err] = [0, null, null];
673
+ let [curTry, result, err, msg] = [0, null, null, null];
673
674
  do {
674
675
  try {
675
676
  assert(await options.verify((err = null), (result = await fnTry())), options.error);
676
677
  } catch (e) {
677
- (err = e) && options?.log && console.log(err?.message || err);
678
+ (err = e) && (msg = err?.message || err) && (
679
+ Function.isFunction(options?.log)
680
+ ? await options.log(msg) : console.log(msg)
681
+ );
678
682
  await timeout(options.interval);
679
683
  }
680
684
  } while (++curTry < options.maxTry && err)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "utilitas",
3
3
  "description": "Just another common utility for JavaScript.",
4
- "version": "1999.1.56",
4
+ "version": "1999.1.58",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/Leask/utilitas",
7
7
  "main": "index.mjs",