museav-cli 2.4.1 → 2.5.0
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/AGENTS.md +3 -1
- package/CHANGELOG.md +11 -0
- package/README.md +4 -0
- package/dist/client.d.ts +7 -2
- package/dist/client.js +9 -3
- package/dist/commands/projects.js +4 -1
- package/dist/commands/templates.d.ts +7 -2
- package/dist/commands/templates.js +26 -3
- package/dist/commands/whoami.d.ts +7 -1
- package/dist/commands/whoami.js +15 -10
- package/dist/index.js +3 -0
- package/package.json +1 -1
- package/src/client.ts +11 -3
- package/src/commands/projects.ts +6 -1
- package/src/commands/templates.ts +26 -6
- package/src/commands/whoami.ts +40 -13
- package/src/index.ts +3 -0
package/AGENTS.md
CHANGED
|
@@ -87,7 +87,9 @@ museav products
|
|
|
87
87
|
museav assets
|
|
88
88
|
|
|
89
89
|
# Check who you're logged in as and whether the account is affiliated with a tenant
|
|
90
|
-
#
|
|
90
|
+
# Works for both personal login and apiKey (platform account or tenant). For apiKey:
|
|
91
|
+
# platform-account → 账户: nickname + 邮箱 + 累计出图 + credits
|
|
92
|
+
# tenant → 租户: tenant_id + name + logo
|
|
91
93
|
museav whoami
|
|
92
94
|
```
|
|
93
95
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.5.0 (2026-08-17)
|
|
4
|
+
|
|
5
|
+
### 修复
|
|
6
|
+
- **`whoami` 不再拒绝 apiKey 模式**:之前会直接抛错「只支持个人 login 身份」。实际上 `/api/me` 对两种 apiKey 都返回真实数据——
|
|
7
|
+
- 平台账户 apiKey(`STUDIO_API_KEY` 指向 `accounts.sk-*`)→ 账户身份:邮箱 + nickname + 累计出图次数 + credits
|
|
8
|
+
- 租户 apiKey(指向 `api_tenants.tenant_key`)→ 业务身份:tenant_id + name + nickname + logo
|
|
9
|
+
修复后三种身份都能 `museav whoami` 查清楚当前是谁、关联到哪个租户。
|
|
10
|
+
|
|
11
|
+
### 文档
|
|
12
|
+
- AGENTS.md `whoami` 说明:去掉「apiKey 不可用」的旧断言。
|
|
13
|
+
|
|
3
14
|
## 2.4.0 · 2026-08-17
|
|
4
15
|
|
|
5
16
|
**本地图像工具箱补全(免登录、零成本、macOS/Windows 通用)。** 均为轻量级工具,无大模型常驻内存。
|
package/README.md
CHANGED
|
@@ -214,6 +214,10 @@ curl -o poster.png "$URL"
|
|
|
214
214
|
# 先查有哪些模板(自己租户建的 + 平台共享的)
|
|
215
215
|
museav templates
|
|
216
216
|
museav templates --category 电商白底图 # 按分类过滤
|
|
217
|
+
museav templates --mine # 只看我这个人建的
|
|
218
|
+
museav templates --tenant # 只看本租户专属的
|
|
219
|
+
museav templates --platform # 只看平台共享的
|
|
220
|
+
museav templates --type image # 按类型过滤(image / article)
|
|
217
221
|
|
|
218
222
|
# 没有占位符的模板,直接用
|
|
219
223
|
museav gen --template <模板id>
|
package/dist/client.d.ts
CHANGED
|
@@ -71,6 +71,10 @@ export interface TemplateOption {
|
|
|
71
71
|
sample_cover_image?: string | null;
|
|
72
72
|
/** 归属:自己租户建的 vs 平台共享的(tenant_id 为空) */
|
|
73
73
|
tenant_id: string | null;
|
|
74
|
+
/** 中台下发的归属标记:mine=本租户建的 / platform=平台共享 / personal=我这个人建的 */
|
|
75
|
+
source?: 'mine' | 'platform' | 'personal';
|
|
76
|
+
/** 创建人(平台管理员个人建的模板会带邮箱;租户建的为 null) */
|
|
77
|
+
created_by?: string | null;
|
|
74
78
|
generation_configs: Array<{
|
|
75
79
|
model: string;
|
|
76
80
|
prompt_template: string;
|
|
@@ -319,8 +323,9 @@ export declare class StudioClient {
|
|
|
319
323
|
/** 可用技能清单:私有 + 所属租户专属模板 + 公共库,服务端已按调用者权限过滤 */
|
|
320
324
|
skills(): Promise<SkillOption[]>;
|
|
321
325
|
/** 可用图片/文字模板清单:自己租户建的 + 平台共享的,服务端已按调用者权限过滤。
|
|
322
|
-
* type=image|article 二选一(不传则图片+文字都返回,跟中台默认一致)。
|
|
323
|
-
|
|
326
|
+
* type=image|article 二选一(不传则图片+文字都返回,跟中台默认一致)。
|
|
327
|
+
* source=mine|platform|personal|all(默认 all;mine=本租户,platform=平台共享,personal=我这个人建的)。 */
|
|
328
|
+
templates(type?: 'image' | 'article', source?: 'mine' | 'platform' | 'personal' | 'all'): Promise<TemplateOption[]>;
|
|
324
329
|
/** 视频模板清单(POST /api/videos 用 template_id)。结构同图片模板的 generation_configs 形态 */
|
|
325
330
|
videoTemplates(): Promise<TemplateOption[]>;
|
|
326
331
|
/** 新建图片模板。归属(是否关联租户)由服务端根据鉴权身份决定,见 CreateTemplateInput 注释 */
|
package/dist/client.js
CHANGED
|
@@ -90,9 +90,15 @@ export class StudioClient {
|
|
|
90
90
|
return Array.isArray(r) ? r : [];
|
|
91
91
|
}
|
|
92
92
|
/** 可用图片/文字模板清单:自己租户建的 + 平台共享的,服务端已按调用者权限过滤。
|
|
93
|
-
* type=image|article 二选一(不传则图片+文字都返回,跟中台默认一致)。
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
* type=image|article 二选一(不传则图片+文字都返回,跟中台默认一致)。
|
|
94
|
+
* source=mine|platform|personal|all(默认 all;mine=本租户,platform=平台共享,personal=我这个人建的)。 */
|
|
95
|
+
async templates(type, source) {
|
|
96
|
+
const params = new URLSearchParams();
|
|
97
|
+
if (type)
|
|
98
|
+
params.set('type', type);
|
|
99
|
+
if (source && source !== 'all')
|
|
100
|
+
params.set('source', source);
|
|
101
|
+
const qs = params.toString() ? `?${params}` : '';
|
|
96
102
|
const r = await this.request(`templates${qs}`);
|
|
97
103
|
return Array.isArray(r) ? r : [];
|
|
98
104
|
}
|
|
@@ -20,9 +20,12 @@ export async function projects(client) {
|
|
|
20
20
|
process.stderr.write('还没有工作区(museav projects create --name 新建)\n');
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
|
+
// 每个项目的素材数(模板不挂项目,这里统计的是项目素材库,不是模板)
|
|
24
|
+
const assetCounts = await Promise.all(list.map(async (w) => ({ id: w.id, n: (await client.workspaceAssets(w.id).catch(() => [])).length })));
|
|
25
|
+
const assetOf = Object.fromEntries(assetCounts.map((x) => [x.id, x.n]));
|
|
23
26
|
process.stderr.write(`工作区(${list.length} 个):\n`);
|
|
24
27
|
for (const w of list) {
|
|
25
|
-
process.stderr.write(` ${w.id} ${w.name.padEnd(16)} 出图 ${w.gen_done ?? 0}/${w.gen_total ?? 0}${w.brand ? ` brand:${w.brand}` : ''}\n`);
|
|
28
|
+
process.stderr.write(` ${w.id} ${w.name.padEnd(16)} 出图 ${w.gen_done ?? 0}/${w.gen_total ?? 0} 素材 ${assetOf[w.id] ?? 0}${w.brand ? ` brand:${w.brand}` : ''}\n`);
|
|
26
29
|
}
|
|
27
30
|
process.stderr.write(`\n素材库: museav projects assets --project <id|名>\n出图归档: museav gen --project <id|名> ...\n`);
|
|
28
31
|
// stdout 只出 id,便于脚本解析
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
/** museav templates ——
|
|
2
|
-
* --type image|article
|
|
1
|
+
/** museav templates —— 查可用图片/文字模板。
|
|
2
|
+
* --type image|article 按类型过滤
|
|
3
|
+
* --mine 只看本租户建的;--platform 只看平台共享的;都不传则全部列出
|
|
4
|
+
* --category 按分类过滤 */
|
|
3
5
|
import type { StudioClient } from '../client.js';
|
|
4
6
|
export declare function templates(client: StudioClient, opts?: {
|
|
5
7
|
category?: string;
|
|
6
8
|
type?: string;
|
|
9
|
+
mine?: boolean;
|
|
10
|
+
tenant?: boolean;
|
|
11
|
+
platform?: boolean;
|
|
7
12
|
}): Promise<void>;
|
|
8
13
|
interface CreateTemplateOpts {
|
|
9
14
|
name: string;
|
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
export async function templates(client, opts = {}) {
|
|
2
|
-
|
|
2
|
+
const type = opts.type === 'image' || opts.type === 'article' ? opts.type : undefined;
|
|
3
|
+
// 三个归属维度都走服务端 source 参数(正式 API,不再客户端猜):
|
|
4
|
+
// --mine → source=personal(created_by = 当前账户邮箱,我这个人建的)
|
|
5
|
+
// --tenant → source=mine(本租户专属)
|
|
6
|
+
// --platform → source=platform(平台共享)
|
|
7
|
+
let list;
|
|
8
|
+
if (opts.mine) {
|
|
9
|
+
list = await client.templates(type, 'personal');
|
|
10
|
+
}
|
|
11
|
+
else if (opts.tenant) {
|
|
12
|
+
list = await client.templates(type, 'mine');
|
|
13
|
+
}
|
|
14
|
+
else if (opts.platform) {
|
|
15
|
+
list = await client.templates(type, 'platform');
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
list = await client.templates(type);
|
|
19
|
+
}
|
|
3
20
|
if (opts.category) {
|
|
4
21
|
const kw = opts.category.toLowerCase();
|
|
5
22
|
list = list.filter((t) => (t.category || '').toLowerCase().includes(kw));
|
|
@@ -8,7 +25,13 @@ export async function templates(client, opts = {}) {
|
|
|
8
25
|
process.stderr.write(opts.category ? `没有匹配「${opts.category}」的模板\n` : '没有可用模板\n');
|
|
9
26
|
return;
|
|
10
27
|
}
|
|
11
|
-
const tag = (t) =>
|
|
28
|
+
const tag = (t) => {
|
|
29
|
+
if (t.source === 'personal')
|
|
30
|
+
return '[个人]';
|
|
31
|
+
if (t.tenant_id)
|
|
32
|
+
return '[租户]';
|
|
33
|
+
return '[平台]';
|
|
34
|
+
};
|
|
12
35
|
const typeTag = (t) => (t.template_type === 'article' ? '[文字]' : t.template_type === 'image' ? '[图片]' : '');
|
|
13
36
|
process.stderr.write(`可用模板(${list.length} 个):\n`);
|
|
14
37
|
for (const t of list) {
|
|
@@ -19,7 +42,7 @@ export async function templates(client, opts = {}) {
|
|
|
19
42
|
process.stderr.write(` ${t.id.padEnd(38)} ${(t.zh_name || '').padEnd(16)} ${(t.category || '').padEnd(10)} ${(t.ratio || '').padEnd(6)} ${typeTag(t).padEnd(8)} ${fieldHint.padEnd(20)} ${tag(t)}\n`);
|
|
20
43
|
}
|
|
21
44
|
process.stderr.write(`\n出图: museav gen --template <模板id> [--fields '{"key":"值"}']\n`);
|
|
22
|
-
process.stderr.write(
|
|
45
|
+
process.stderr.write(`筛选: --mine(我建的) --tenant(本租户) --platform(平台共享) --type image|article --category <分类>\n`);
|
|
23
46
|
// stdout 只出 id,便于脚本与 agent 解析
|
|
24
47
|
console.log(list.map((t) => t.id).join('\n'));
|
|
25
48
|
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
/** museav whoami ——
|
|
1
|
+
/** museav whoami —— 查当前身份 + 关联信息。
|
|
2
|
+
*
|
|
3
|
+
* apiKey 模式下也支持(2026-08-17 修复):服务端 /api/me 对两种 apiKey 都返回真实数据——
|
|
4
|
+
* - 平台账户 apiKey(STUDIO_API_KEY 指向 accounts.sk-*) → 走个人身份,含 credits / gen 统计
|
|
5
|
+
* - 租户 apiKey(指向 api_tenants.tenant_key) → 走业务身份,只下发 tenant 信息
|
|
6
|
+
* 个人 login(museav login)走完整 me,输出不变。
|
|
7
|
+
*/
|
|
2
8
|
import type { StudioClient } from '../client.js';
|
|
3
9
|
export declare function whoami(client: StudioClient): Promise<void>;
|
package/dist/commands/whoami.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
import { loadConfig } from '../config.js';
|
|
2
1
|
export async function whoami(client) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
const me = (await client.me());
|
|
3
|
+
if (me.identity === 'tenant') {
|
|
4
|
+
const t = me.tenant;
|
|
5
|
+
process.stderr.write(`身份: 租户 API Key\n`);
|
|
6
|
+
process.stderr.write(`租户: ${t.nickname || t.name}(${t.name})\n`);
|
|
7
|
+
process.stderr.write(`tenant_id: ${t.id}\n`);
|
|
8
|
+
if (t.logo)
|
|
9
|
+
process.stderr.write(`logo: ${t.logo}\n`);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
process.stderr.write(`账户: ${me.nickname || me.email}(${me.email})\n`);
|
|
13
|
+
process.stderr.write(me.brand ? `业务系统: ${me.brand.name}\n` : `身份: 平台账户 API Key\n`);
|
|
14
|
+
process.stderr.write(`出图: 累计 ${me.gen_total ?? 0} 次,成功 ${me.gen_done ?? 0} 次\n`);
|
|
15
|
+
if (me.credits != null)
|
|
16
|
+
process.stderr.write(`credits: ${me.credits}\n`);
|
|
8
17
|
}
|
|
9
|
-
const me = await client.me();
|
|
10
|
-
process.stderr.write(`账户: ${me.nickname || me.email}(${me.email})\n`);
|
|
11
|
-
process.stderr.write(me.brand ? `业务系统: ${me.brand.name}\n` : '业务系统: 未接入(个人用户)\n');
|
|
12
|
-
process.stderr.write(`出图: 累计 ${me.gen_total} 次,成功 ${me.gen_done} 次\n`);
|
|
13
18
|
console.log(JSON.stringify(me));
|
|
14
19
|
}
|
package/dist/index.js
CHANGED
|
@@ -262,6 +262,9 @@ const templatesCmd = program
|
|
|
262
262
|
.description('查可用图片/文字模板:自己租户建的 + 平台共享的(跟技能是两套不同的机制,见 gen --template)')
|
|
263
263
|
.option('--category <name>', '按分类过滤,如 电商白底图 / 演唱会')
|
|
264
264
|
.option('--type <type>', '按类型过滤:image(图片) / article(文字),不传则两类都列并标注')
|
|
265
|
+
.option('--mine', '只看我这个人建的模板(created_by 是我,排除系统种子和租户专属)')
|
|
266
|
+
.option('--tenant', '只看本租户建的模板')
|
|
267
|
+
.option('--platform', '只看平台共享的模板')
|
|
265
268
|
.action(withClient((client, opts) => templates(client, opts)));
|
|
266
269
|
const videoTemplatesCmd = program
|
|
267
270
|
.command('video-templates')
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -123,6 +123,10 @@ export interface TemplateOption {
|
|
|
123
123
|
sample_cover_image?: string | null
|
|
124
124
|
/** 归属:自己租户建的 vs 平台共享的(tenant_id 为空) */
|
|
125
125
|
tenant_id: string | null
|
|
126
|
+
/** 中台下发的归属标记:mine=本租户建的 / platform=平台共享 / personal=我这个人建的 */
|
|
127
|
+
source?: 'mine' | 'platform' | 'personal'
|
|
128
|
+
/** 创建人(平台管理员个人建的模板会带邮箱;租户建的为 null) */
|
|
129
|
+
created_by?: string | null
|
|
126
130
|
generation_configs: Array<{
|
|
127
131
|
model: string
|
|
128
132
|
prompt_template: string
|
|
@@ -386,9 +390,13 @@ export class StudioClient {
|
|
|
386
390
|
}
|
|
387
391
|
|
|
388
392
|
/** 可用图片/文字模板清单:自己租户建的 + 平台共享的,服务端已按调用者权限过滤。
|
|
389
|
-
* type=image|article 二选一(不传则图片+文字都返回,跟中台默认一致)。
|
|
390
|
-
|
|
391
|
-
|
|
393
|
+
* type=image|article 二选一(不传则图片+文字都返回,跟中台默认一致)。
|
|
394
|
+
* source=mine|platform|personal|all(默认 all;mine=本租户,platform=平台共享,personal=我这个人建的)。 */
|
|
395
|
+
async templates(type?: 'image' | 'article', source?: 'mine' | 'platform' | 'personal' | 'all'): Promise<TemplateOption[]> {
|
|
396
|
+
const params = new URLSearchParams()
|
|
397
|
+
if (type) params.set('type', type)
|
|
398
|
+
if (source && source !== 'all') params.set('source', source)
|
|
399
|
+
const qs = params.toString() ? `?${params}` : ''
|
|
392
400
|
const r = await this.request(`templates${qs}`)
|
|
393
401
|
return Array.isArray(r) ? r : []
|
|
394
402
|
}
|
package/src/commands/projects.ts
CHANGED
|
@@ -22,10 +22,15 @@ export async function projects(client: StudioClient): Promise<void> {
|
|
|
22
22
|
process.stderr.write('还没有工作区(museav projects create --name 新建)\n')
|
|
23
23
|
return
|
|
24
24
|
}
|
|
25
|
+
// 每个项目的素材数(模板不挂项目,这里统计的是项目素材库,不是模板)
|
|
26
|
+
const assetCounts = await Promise.all(
|
|
27
|
+
list.map(async (w) => ({ id: w.id, n: (await client.workspaceAssets(w.id).catch(() => [])).length })),
|
|
28
|
+
)
|
|
29
|
+
const assetOf = Object.fromEntries(assetCounts.map((x) => [x.id, x.n]))
|
|
25
30
|
process.stderr.write(`工作区(${list.length} 个):\n`)
|
|
26
31
|
for (const w of list) {
|
|
27
32
|
process.stderr.write(
|
|
28
|
-
` ${w.id} ${w.name.padEnd(16)} 出图 ${w.gen_done ?? 0}/${w.gen_total ?? 0}${w.brand ? ` brand:${w.brand}` : ''}\n`,
|
|
33
|
+
` ${w.id} ${w.name.padEnd(16)} 出图 ${w.gen_done ?? 0}/${w.gen_total ?? 0} 素材 ${assetOf[w.id] ?? 0}${w.brand ? ` brand:${w.brand}` : ''}\n`,
|
|
29
34
|
)
|
|
30
35
|
}
|
|
31
36
|
process.stderr.write(`\n素材库: museav projects assets --project <id|名>\n出图归档: museav gen --project <id|名> ...\n`)
|
|
@@ -1,9 +1,25 @@
|
|
|
1
|
-
/** museav templates ——
|
|
2
|
-
* --type image|article
|
|
1
|
+
/** museav templates —— 查可用图片/文字模板。
|
|
2
|
+
* --type image|article 按类型过滤
|
|
3
|
+
* --mine 只看本租户建的;--platform 只看平台共享的;都不传则全部列出
|
|
4
|
+
* --category 按分类过滤 */
|
|
3
5
|
import type { StudioClient } from '../client.js'
|
|
4
6
|
|
|
5
|
-
export async function templates(client: StudioClient, opts: { category?: string; type?: string } = {}): Promise<void> {
|
|
6
|
-
|
|
7
|
+
export async function templates(client: StudioClient, opts: { category?: string; type?: string; mine?: boolean; tenant?: boolean; platform?: boolean } = {}): Promise<void> {
|
|
8
|
+
const type = opts.type === 'image' || opts.type === 'article' ? opts.type : undefined
|
|
9
|
+
// 三个归属维度都走服务端 source 参数(正式 API,不再客户端猜):
|
|
10
|
+
// --mine → source=personal(created_by = 当前账户邮箱,我这个人建的)
|
|
11
|
+
// --tenant → source=mine(本租户专属)
|
|
12
|
+
// --platform → source=platform(平台共享)
|
|
13
|
+
let list: Awaited<ReturnType<StudioClient['templates']>>
|
|
14
|
+
if (opts.mine) {
|
|
15
|
+
list = await client.templates(type, 'personal')
|
|
16
|
+
} else if (opts.tenant) {
|
|
17
|
+
list = await client.templates(type, 'mine')
|
|
18
|
+
} else if (opts.platform) {
|
|
19
|
+
list = await client.templates(type, 'platform')
|
|
20
|
+
} else {
|
|
21
|
+
list = await client.templates(type)
|
|
22
|
+
}
|
|
7
23
|
if (opts.category) {
|
|
8
24
|
const kw = opts.category.toLowerCase()
|
|
9
25
|
list = list.filter((t) => (t.category || '').toLowerCase().includes(kw))
|
|
@@ -13,7 +29,11 @@ export async function templates(client: StudioClient, opts: { category?: string;
|
|
|
13
29
|
return
|
|
14
30
|
}
|
|
15
31
|
|
|
16
|
-
const tag = (t: (typeof list)[number]) =>
|
|
32
|
+
const tag = (t: (typeof list)[number]) => {
|
|
33
|
+
if (t.source === 'personal') return '[个人]'
|
|
34
|
+
if (t.tenant_id) return '[租户]'
|
|
35
|
+
return '[平台]'
|
|
36
|
+
}
|
|
17
37
|
const typeTag = (t: (typeof list)[number]) => (t.template_type === 'article' ? '[文字]' : t.template_type === 'image' ? '[图片]' : '')
|
|
18
38
|
|
|
19
39
|
process.stderr.write(`可用模板(${list.length} 个):\n`)
|
|
@@ -27,7 +47,7 @@ export async function templates(client: StudioClient, opts: { category?: string;
|
|
|
27
47
|
)
|
|
28
48
|
}
|
|
29
49
|
process.stderr.write(`\n出图: museav gen --template <模板id> [--fields '{"key":"值"}']\n`)
|
|
30
|
-
process.stderr.write(
|
|
50
|
+
process.stderr.write(`筛选: --mine(我建的) --tenant(本租户) --platform(平台共享) --type image|article --category <分类>\n`)
|
|
31
51
|
// stdout 只出 id,便于脚本与 agent 解析
|
|
32
52
|
console.log(list.map((t) => t.id).join('\n'))
|
|
33
53
|
}
|
package/src/commands/whoami.ts
CHANGED
|
@@ -1,19 +1,46 @@
|
|
|
1
|
-
/** museav whoami ——
|
|
1
|
+
/** museav whoami —— 查当前身份 + 关联信息。
|
|
2
|
+
*
|
|
3
|
+
* apiKey 模式下也支持(2026-08-17 修复):服务端 /api/me 对两种 apiKey 都返回真实数据——
|
|
4
|
+
* - 平台账户 apiKey(STUDIO_API_KEY 指向 accounts.sk-*) → 走个人身份,含 credits / gen 统计
|
|
5
|
+
* - 租户 apiKey(指向 api_tenants.tenant_key) → 走业务身份,只下发 tenant 信息
|
|
6
|
+
* 个人 login(museav login)走完整 me,输出不变。
|
|
7
|
+
*/
|
|
2
8
|
import type { StudioClient } from '../client.js'
|
|
3
|
-
|
|
9
|
+
|
|
10
|
+
/** /api/me 实际返回的形状:可能是账户身份也可能是租户身份(apiKey 模式) */
|
|
11
|
+
type MeResponse =
|
|
12
|
+
| {
|
|
13
|
+
identity?: 'account'
|
|
14
|
+
id: string
|
|
15
|
+
email: string
|
|
16
|
+
nickname?: string | null
|
|
17
|
+
bio?: string | null
|
|
18
|
+
role: string
|
|
19
|
+
credits?: number | null
|
|
20
|
+
gen_quota?: number | null
|
|
21
|
+
gen_total?: number
|
|
22
|
+
gen_done?: number
|
|
23
|
+
brand?: { name: string } | null
|
|
24
|
+
}
|
|
25
|
+
| {
|
|
26
|
+
identity: 'tenant'
|
|
27
|
+
tenant: { id: string; name: string; nickname?: string | null; logo?: string | null }
|
|
28
|
+
}
|
|
4
29
|
|
|
5
30
|
export async function whoami(client: StudioClient): Promise<void> {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
)
|
|
31
|
+
const me = (await client.me()) as MeResponse
|
|
32
|
+
|
|
33
|
+
if (me.identity === 'tenant') {
|
|
34
|
+
const t = me.tenant
|
|
35
|
+
process.stderr.write(`身份: 租户 API Key\n`)
|
|
36
|
+
process.stderr.write(`租户: ${t.nickname || t.name}(${t.name})\n`)
|
|
37
|
+
process.stderr.write(`tenant_id: ${t.id}\n`)
|
|
38
|
+
if (t.logo) process.stderr.write(`logo: ${t.logo}\n`)
|
|
39
|
+
} else {
|
|
40
|
+
process.stderr.write(`账户: ${me.nickname || me.email}(${me.email})\n`)
|
|
41
|
+
process.stderr.write(me.brand ? `业务系统: ${me.brand.name}\n` : `身份: 平台账户 API Key\n`)
|
|
42
|
+
process.stderr.write(`出图: 累计 ${me.gen_total ?? 0} 次,成功 ${me.gen_done ?? 0} 次\n`)
|
|
43
|
+
if (me.credits != null) process.stderr.write(`credits: ${me.credits}\n`)
|
|
13
44
|
}
|
|
14
|
-
const me = await client.me()
|
|
15
|
-
process.stderr.write(`账户: ${me.nickname || me.email}(${me.email})\n`)
|
|
16
|
-
process.stderr.write(me.brand ? `业务系统: ${me.brand.name}\n` : '业务系统: 未接入(个人用户)\n')
|
|
17
|
-
process.stderr.write(`出图: 累计 ${me.gen_total} 次,成功 ${me.gen_done} 次\n`)
|
|
18
45
|
console.log(JSON.stringify(me))
|
|
19
46
|
}
|
package/src/index.ts
CHANGED
|
@@ -281,6 +281,9 @@ const templatesCmd = program
|
|
|
281
281
|
.description('查可用图片/文字模板:自己租户建的 + 平台共享的(跟技能是两套不同的机制,见 gen --template)')
|
|
282
282
|
.option('--category <name>', '按分类过滤,如 电商白底图 / 演唱会')
|
|
283
283
|
.option('--type <type>', '按类型过滤:image(图片) / article(文字),不传则两类都列并标注')
|
|
284
|
+
.option('--mine', '只看我这个人建的模板(created_by 是我,排除系统种子和租户专属)')
|
|
285
|
+
.option('--tenant', '只看本租户建的模板')
|
|
286
|
+
.option('--platform', '只看平台共享的模板')
|
|
284
287
|
.action(withClient((client: StudioClient, opts: any) => templates(client, opts)))
|
|
285
288
|
|
|
286
289
|
const videoTemplatesCmd = program
|