@302ai/media-studio-cli 0.1.0-beta.7 → 0.1.1-beta.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/README.md +25 -18
- package/dist/index.js +368 -55
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,16 +10,9 @@ npm install -g @302ai/media-studio-cli
|
|
|
10
10
|
# requires Node.js >= 22
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
npm install -g @302ai/media-studio-cli@beta
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
> **No stable release exists yet.** `latest` points at a prerelease, so both
|
|
20
|
-
> commands above currently install the same build. Staging- and Local-server
|
|
21
|
-
> visibility is gated on the package *version* carrying a prerelease tag — not
|
|
22
|
-
> on the dist-tag — so both are on for either install: **Staging** and
|
|
13
|
+
> **No stable release exists yet.** `latest` currently points at a prerelease.
|
|
14
|
+
> Staging- and Local-server visibility is gated on the package *version*
|
|
15
|
+
> carrying a prerelease tag — not on the dist-tag — so **Staging** and
|
|
23
16
|
> **Local** appear in `msc login` and in `--region` whichever way you install.
|
|
24
17
|
> A future stable release will hide them from both channels.
|
|
25
18
|
|
|
@@ -49,10 +42,12 @@ name:
|
|
|
49
42
|
```bash
|
|
50
43
|
msc chat "画一只猫" -r # -r/--show-reasoning = 展示模型推理过程
|
|
51
44
|
msc chat "hi" --json # machine-readable output
|
|
52
|
-
msc chat "hi" --session <id> #
|
|
45
|
+
msc chat "hi" --session <id> # 切换到已有会话(先校验存在)并设为默认
|
|
46
|
+
msc chat "hi" --new # 新建会话并设为默认(id 不复用)
|
|
53
47
|
msc sessions # 列出所有会话(标记当前默认 `(current)`)
|
|
54
48
|
msc sessions --json # 机器可读的原始 JSON 数组
|
|
55
|
-
msc sessions use <id> #
|
|
49
|
+
msc sessions use <id> # 校验存在后切换默认会话
|
|
50
|
+
msc sessions use --new # 新建会话并设为默认
|
|
56
51
|
msc skills # 列出技能库(--plaza 浏览技能广场)
|
|
57
52
|
msc skills add <slug> # 从广场安装技能(如 brainstorming,见 --plaza --json 的 slug)
|
|
58
53
|
msc skills rm <command> # 从技能库移除(-y/--yes 跳过确认)
|
|
@@ -86,10 +81,20 @@ whose browser can reach the loopback callback.
|
|
|
86
81
|
loses a live session.
|
|
87
82
|
- **Later chats** continue that session — upstream remembers the
|
|
88
83
|
conversation by session id, so no history is resent.
|
|
89
|
-
- If the session
|
|
90
|
-
fresh one and
|
|
91
|
-
|
|
92
|
-
|
|
84
|
+
- If the current session is gone **before a turn produces any output**, the CLI
|
|
85
|
+
transparently provisions a fresh one and re-runs the turn — a first-turn
|
|
86
|
+
failure never strands you.
|
|
87
|
+
- Once a turn has started producing output, a session failure is reported
|
|
88
|
+
instead: the partial result stands, nothing is re-run, and no replacement
|
|
89
|
+
session is created (a retry would replay output and re-dispatch tool calls or
|
|
90
|
+
generation tasks the first attempt may already have started).
|
|
91
|
+
- `--session <id>` switches to an existing session (including web-created
|
|
92
|
+
ones) and makes it the default. The id is verified upstream first: a missing
|
|
93
|
+
id fails with a hint, it never provisions a different session behind your
|
|
94
|
+
back.
|
|
95
|
+
- `--new` creates a fresh session with a newly generated id and makes it the
|
|
96
|
+
default for later runs. Ids are never reused or adopted: the CLI either uses
|
|
97
|
+
the id it generated or reports the refusal.
|
|
93
98
|
|
|
94
99
|
Manual proof of continuity:
|
|
95
100
|
|
|
@@ -324,8 +329,10 @@ msc chat "刚才的数字是几?" # answers 42
|
|
|
324
329
|
|
|
325
330
|
# Session management verification:
|
|
326
331
|
msc sessions # shows session list with (current) marker
|
|
327
|
-
msc chat "hi" --session <id> # switch to
|
|
328
|
-
msc
|
|
332
|
+
msc chat "hi" --session <id> # switch to an existing session
|
|
333
|
+
msc chat "hi" --new # start a new session
|
|
334
|
+
msc sessions use <id> # switch default pointer to an existing session
|
|
335
|
+
msc sessions use --new # create a new session and switch to it
|
|
329
336
|
```
|
|
330
337
|
|
|
331
338
|
Without the local server, point at production with
|
package/dist/index.js
CHANGED
|
@@ -4284,7 +4284,7 @@ var consola = createConsola2();
|
|
|
4284
4284
|
// package.json
|
|
4285
4285
|
var package_default = {
|
|
4286
4286
|
name: "@302ai/media-studio-cli",
|
|
4287
|
-
version: "0.1.
|
|
4287
|
+
version: "0.1.1-beta.0",
|
|
4288
4288
|
description: "CLI for AI Media Studio — let external agents drive the core media-studio features",
|
|
4289
4289
|
author: "302.AI",
|
|
4290
4290
|
license: "Apache-2.0",
|
|
@@ -9749,6 +9749,151 @@ function isString(value) {
|
|
|
9749
9749
|
return typeof value === "string";
|
|
9750
9750
|
}
|
|
9751
9751
|
// ../media-studio-contract/src/err-codes.ts
|
|
9752
|
+
var ErrCode = {
|
|
9753
|
+
MISSING_REQUIRED_PARAM: 10001,
|
|
9754
|
+
INVALID_PARAM_FORMAT: 10002,
|
|
9755
|
+
RESOURCE_NOT_FOUND: 10003,
|
|
9756
|
+
METHOD_NOT_ALLOWED: 10004,
|
|
9757
|
+
RATE_LIMITED: 10005,
|
|
9758
|
+
PAYLOAD_TOO_LARGE: 10006,
|
|
9759
|
+
UNSUPPORTED_MEDIA_TYPE: 10007,
|
|
9760
|
+
INTERNAL_ERROR: 10500,
|
|
9761
|
+
DEPENDENCY_UNAVAILABLE: 10501,
|
|
9762
|
+
DATABASE_ERROR: 10502,
|
|
9763
|
+
SERVICE_UNAVAILABLE: 10503,
|
|
9764
|
+
CACHE_UNAVAILABLE: 10504,
|
|
9765
|
+
UNAUTHORIZED: 20001,
|
|
9766
|
+
TOKEN_MISSING: 20002,
|
|
9767
|
+
TOKEN_INVALID: 20003,
|
|
9768
|
+
TOKEN_EXPIRED: 20004,
|
|
9769
|
+
TOKEN_REVOKED: 20005,
|
|
9770
|
+
REFRESH_TOKEN_INVALID: 20006,
|
|
9771
|
+
REFRESH_TOKEN_ROTATED: 20007,
|
|
9772
|
+
VERIFICATION_CODE_INVALID: 20101,
|
|
9773
|
+
VERIFICATION_CODE_EXPIRED: 20102,
|
|
9774
|
+
CODE_SEND_RATE_LIMITED: 20103,
|
|
9775
|
+
CODE_SEND_DAILY_LIMIT: 20104,
|
|
9776
|
+
EMAIL_SEND_FAILED: 20105,
|
|
9777
|
+
EMAIL_ALREADY_REGISTERED: 20106,
|
|
9778
|
+
EMAIL_NOT_REGISTERED: 20107,
|
|
9779
|
+
OAUTH_STATE_INVALID: 20201,
|
|
9780
|
+
OAUTH_CALLBACK_FAILED: 20202,
|
|
9781
|
+
OAUTH_ACCOUNT_ALREADY_BOUND: 20203,
|
|
9782
|
+
SSO_INFO_CONFLICT: 20204,
|
|
9783
|
+
FORBIDDEN: 20301,
|
|
9784
|
+
ADMIN_REQUIRED: 20302,
|
|
9785
|
+
ACCOUNT_DEACTIVATED: 20303,
|
|
9786
|
+
INSUFFICIENT_BALANCE: 30001,
|
|
9787
|
+
CREDIT_FREEZE_FAILED: 30002,
|
|
9788
|
+
FREEZE_RECORD_NOT_FOUND: 30003,
|
|
9789
|
+
FREEZE_ALREADY_SETTLED: 30004,
|
|
9790
|
+
CREDIT_SETTLE_FAILED: 30005,
|
|
9791
|
+
SETTLE_EXCEEDS_FREEZE: 30006,
|
|
9792
|
+
UNFREEZE_FAILED: 30007,
|
|
9793
|
+
CREDIT_BATCH_EXPIRED: 30008,
|
|
9794
|
+
CREDIT_BATCH_NOT_FOUND: 30009,
|
|
9795
|
+
CONCURRENT_MODIFICATION: 30010,
|
|
9796
|
+
PRICING_RULE_NOT_FOUND: 30101,
|
|
9797
|
+
MODEL_PRICE_MISSING: 30102,
|
|
9798
|
+
USAGE_RECORD_DUPLICATED: 30103,
|
|
9799
|
+
BALANCE_CACHE_REBUILD_FAILED: 30104,
|
|
9800
|
+
LEDGER_WRITE_FAILED: 30105,
|
|
9801
|
+
UPSTREAM_ERROR: 40001,
|
|
9802
|
+
UPSTREAM_TIMEOUT: 40002,
|
|
9803
|
+
UPSTREAM_RATE_LIMITED: 40003,
|
|
9804
|
+
UPSTREAM_UNAVAILABLE: 40004,
|
|
9805
|
+
UPSTREAM_AUTH_FAILED: 40005,
|
|
9806
|
+
UPSTREAM_DATA_INVALID: 40006,
|
|
9807
|
+
MODEL_UNSUPPORTED: 40101,
|
|
9808
|
+
MODEL_LABEL_INVALID: 40102,
|
|
9809
|
+
MODEL_PRICE_NOT_CONFIGURED: 40103,
|
|
9810
|
+
MODEL_LABEL_DEPRECATED: 40104,
|
|
9811
|
+
SANDBOX_TOKEN_INVALID: 40201,
|
|
9812
|
+
SANDBOX_TOKEN_EXPIRED: 40202,
|
|
9813
|
+
OSS_TRANSFER_FAILED: 40301,
|
|
9814
|
+
OSS_URL_PRESIGN_FAILED: 40302,
|
|
9815
|
+
PLAN_NOT_FOUND: 50001,
|
|
9816
|
+
PLAN_UNAVAILABLE: 50002,
|
|
9817
|
+
PLAN_PRICE_MISSING: 50003,
|
|
9818
|
+
ORDER_NOT_FOUND: 50101,
|
|
9819
|
+
ORDER_ALREADY_PAID: 50102,
|
|
9820
|
+
ORDER_EXPIRED: 50103,
|
|
9821
|
+
ORDER_AMOUNT_MISMATCH: 50104,
|
|
9822
|
+
ORDER_STATUS_NOT_ALLOWED: 50105,
|
|
9823
|
+
ORDER_CANCEL_FAILED: 50106,
|
|
9824
|
+
ORDER_PENDING_EXISTS: 50107,
|
|
9825
|
+
PAYMENT_FAILED: 50201,
|
|
9826
|
+
PAYMENT_REJECTED: 50202,
|
|
9827
|
+
PAYMENT_METHOD_NOT_FOUND: 50203,
|
|
9828
|
+
WEBHOOK_SIGNATURE_INVALID: 50204,
|
|
9829
|
+
WEBHOOK_EVENT_UNKNOWN: 50205,
|
|
9830
|
+
STRIPE_API_ERROR: 50206,
|
|
9831
|
+
SUBSCRIPTION_NOT_FOUND: 50301,
|
|
9832
|
+
SUBSCRIPTION_STATUS_NOT_ALLOWED: 50302,
|
|
9833
|
+
SUBSCRIPTION_CANCELED: 50303,
|
|
9834
|
+
UPGRADE_PRORATION_FAILED: 50304,
|
|
9835
|
+
DOWNGRADE_NOT_ALLOWED: 50305,
|
|
9836
|
+
AUTO_RENEW_FAILED: 50306,
|
|
9837
|
+
SAVED_CARD_INVALID: 50307,
|
|
9838
|
+
REFUND_NOT_ELIGIBLE: 50401,
|
|
9839
|
+
REFUND_WINDOW_EXPIRED: 50402,
|
|
9840
|
+
REFUND_THRESHOLD_EXCEEDED: 50403,
|
|
9841
|
+
REFUND_FAILED: 50404,
|
|
9842
|
+
TOPUP_SUBSCRIPTION_ONLY: 50501,
|
|
9843
|
+
TOPUP_FROZEN: 50502,
|
|
9844
|
+
TOPUP_NOT_FOUND: 50503,
|
|
9845
|
+
SESSION_NOT_FOUND: 60001,
|
|
9846
|
+
SESSION_ALREADY_EXISTS: 60002,
|
|
9847
|
+
SESSION_STATUS_NOT_ALLOWED: 60003,
|
|
9848
|
+
CHAT_SESSION_EXPIRED: 60004,
|
|
9849
|
+
CHAT_CONTEXT_MISSING: 60005,
|
|
9850
|
+
PROMPT_SUGGESTION_FAILED: 60006,
|
|
9851
|
+
TITLE_GENERATION_FAILED: 60007,
|
|
9852
|
+
CHAT_TASK_NOT_FOUND: 60101,
|
|
9853
|
+
CHAT_TASK_IN_PROGRESS: 60102,
|
|
9854
|
+
CHAT_TASK_CANCELED: 60103,
|
|
9855
|
+
CHAT_TASK_STATUS_NOT_ALLOWED: 60104,
|
|
9856
|
+
SANDBOX_CREATE_FAILED: 60201,
|
|
9857
|
+
SANDBOX_WARMUP_FAILED: 60202,
|
|
9858
|
+
SANDBOX_TIMEOUT: 60203,
|
|
9859
|
+
SANDBOX_UNAVAILABLE: 60204,
|
|
9860
|
+
SANDBOX_COMMAND_FAILED: 60205,
|
|
9861
|
+
SKILL_NOT_FOUND: 60301,
|
|
9862
|
+
SKILL_FILE_INVALID: 60302,
|
|
9863
|
+
SKILL_BUILTIN_IMMUTABLE: 60303,
|
|
9864
|
+
SKILL_UPLOAD_INVALID: 60304,
|
|
9865
|
+
ASSET_NOT_FOUND: 70001,
|
|
9866
|
+
ASSET_GROUP_NOT_FOUND: 70002,
|
|
9867
|
+
ASSET_GROUP_NAME_EXISTS: 70003,
|
|
9868
|
+
ASSET_UPLOAD_FAILED: 70004,
|
|
9869
|
+
ASSET_TOO_LARGE: 70005,
|
|
9870
|
+
ASSET_TYPE_NOT_ALLOWED: 70006,
|
|
9871
|
+
ASSET_GROUP_INVALID: 70007,
|
|
9872
|
+
OSS_UPLOAD_FAILED: 70101,
|
|
9873
|
+
OSS_DOWNLOAD_FAILED: 70102,
|
|
9874
|
+
COVER_UPLOAD_FAILED: 70103,
|
|
9875
|
+
OSS_DELETE_FAILED: 70104,
|
|
9876
|
+
FILE_NOT_FOUND: 70201,
|
|
9877
|
+
FILE_READ_FAILED: 70202,
|
|
9878
|
+
FILE_WRITE_FAILED: 70203,
|
|
9879
|
+
FILE_FORMAT_INVALID: 70204,
|
|
9880
|
+
FILE_FORMAT_TEXT_FILE_ONLY: 70205,
|
|
9881
|
+
FILE_OPERATION_INVALID: 70206,
|
|
9882
|
+
FILE_TARGET_PATH_REQUIRED: 70207,
|
|
9883
|
+
FILE_PATH_COUNT_MISMATCH: 70208,
|
|
9884
|
+
FILE_RENAME_BATCH_UNSUPPORTED: 70209,
|
|
9885
|
+
ADMIN_NOT_LOGGED_IN: 90001,
|
|
9886
|
+
ADMIN_2FA_REQUIRED: 90002,
|
|
9887
|
+
ADMIN_2FA_CODE_INVALID: 90003,
|
|
9888
|
+
ADMIN_2FA_RATE_LIMITED: 90004,
|
|
9889
|
+
ADMIN_FORBIDDEN: 90005,
|
|
9890
|
+
ADMIN_NOT_FOUND: 90006,
|
|
9891
|
+
RISK_CONTROL_TRIGGERED: 90101,
|
|
9892
|
+
RISK_CONTROL_RATE_LIMITED: 90102,
|
|
9893
|
+
RECONCILIATION_MISMATCH: 90103,
|
|
9894
|
+
RECONCILIATION_TASK_FAILED: 90104,
|
|
9895
|
+
AUDIT_LOG_WRITE_FAILED: 90105
|
|
9896
|
+
};
|
|
9752
9897
|
var ERR_NEXT_STEP = {
|
|
9753
9898
|
10001: "fix_input",
|
|
9754
9899
|
10002: "fix_input",
|
|
@@ -9915,6 +10060,15 @@ var MEDIA_STUDIO_HOSTS = [
|
|
|
9915
10060
|
new URL(MEDIA_STUDIO_URLS.cn).hostname,
|
|
9916
10061
|
new URL(MEDIA_STUDIO_URLS.staging).hostname
|
|
9917
10062
|
];
|
|
10063
|
+
var APP_ENVS = ["development", "staging", "production"];
|
|
10064
|
+
var APP_ENV_SCHEMA = _enum(APP_ENVS);
|
|
10065
|
+
var APP_ENV_HOSTS = {
|
|
10066
|
+
staging: [new URL(MEDIA_STUDIO_URLS.staging).hostname],
|
|
10067
|
+
production: [
|
|
10068
|
+
new URL(MEDIA_STUDIO_URLS.default).hostname,
|
|
10069
|
+
new URL(MEDIA_STUDIO_URLS.cn).hostname
|
|
10070
|
+
]
|
|
10071
|
+
};
|
|
9918
10072
|
|
|
9919
10073
|
// ../media-studio-contract/src/skills/activation.ts
|
|
9920
10074
|
var SKILL_ACTIVATION_MARKER = "%%";
|
|
@@ -10018,6 +10172,15 @@ function attempt2(func) {
|
|
|
10018
10172
|
return [error, null];
|
|
10019
10173
|
}
|
|
10020
10174
|
}
|
|
10175
|
+
|
|
10176
|
+
// ../../node_modules/es-toolkit/dist/util/attemptAsync.mjs
|
|
10177
|
+
async function attemptAsync(func) {
|
|
10178
|
+
try {
|
|
10179
|
+
return [null, await func()];
|
|
10180
|
+
} catch (error) {
|
|
10181
|
+
return [error, null];
|
|
10182
|
+
}
|
|
10183
|
+
}
|
|
10021
10184
|
// ../../node_modules/ts-pattern/dist/index.js
|
|
10022
10185
|
var t2 = Symbol.for("@ts-pattern/matcher");
|
|
10023
10186
|
var e2 = Symbol.for("@ts-pattern/isVariadic");
|
|
@@ -16960,6 +17123,15 @@ class ClientSessions {
|
|
|
16960
17123
|
const url = `${this.baseUrl}/api/sessions${search ? `?${search}` : ""}`;
|
|
16961
17124
|
return requestJson(this.customFetch, url, { method: "GET", headers: this.authHeaders() }, ListSessionsResponseSchema, (status) => `Failed to fetch sessions with status ${status}`);
|
|
16962
17125
|
}
|
|
17126
|
+
async exists(sessionId) {
|
|
17127
|
+
const params = new URLSearchParams({ sessionId, limit: "1" });
|
|
17128
|
+
const [err] = await attemptAsync(() => requestJson(this.customFetch, `${this.baseUrl}/api/sessions/detail?${params.toString()}`, { method: "GET", headers: this.authHeaders() }, unknown2(), (status) => `Failed to verify session ${sessionId} with status ${status}`));
|
|
17129
|
+
if (!err)
|
|
17130
|
+
return true;
|
|
17131
|
+
if (err instanceof ChatUpstreamError && err.status === 404)
|
|
17132
|
+
return false;
|
|
17133
|
+
throw err;
|
|
17134
|
+
}
|
|
16963
17135
|
async artifacts(query) {
|
|
16964
17136
|
const params = new URLSearchParams({ sessionId: query.sessionId });
|
|
16965
17137
|
if (query.taskId !== undefined)
|
|
@@ -16997,12 +17169,17 @@ class ClientSessions {
|
|
|
16997
17169
|
signal
|
|
16998
17170
|
});
|
|
16999
17171
|
if (!response.ok) {
|
|
17000
|
-
await response.
|
|
17001
|
-
return;
|
|
17002
|
-
});
|
|
17172
|
+
const body = await response.text().catch(() => "");
|
|
17003
17173
|
const retryable = response.status >= 500 || response.status === 429;
|
|
17004
|
-
if (!retryable)
|
|
17174
|
+
if (!retryable) {
|
|
17175
|
+
if (!state.sessionReady) {
|
|
17176
|
+
state.outcome = {
|
|
17177
|
+
status: "failed",
|
|
17178
|
+
error: new ChatUpstreamError(`Session prewarm was rejected with status ${response.status}`, response.status, body)
|
|
17179
|
+
};
|
|
17180
|
+
}
|
|
17005
17181
|
break;
|
|
17182
|
+
}
|
|
17006
17183
|
continue;
|
|
17007
17184
|
}
|
|
17008
17185
|
await this.consumePrewarmStream(response, state, {
|
|
@@ -17021,7 +17198,10 @@ class ClientSessions {
|
|
|
17021
17198
|
}
|
|
17022
17199
|
if (state.outcome)
|
|
17023
17200
|
return state.outcome;
|
|
17024
|
-
return state.sessionReady ? { status: "fallback", session: state.sessionReady } : {
|
|
17201
|
+
return state.sessionReady ? { status: "fallback", session: state.sessionReady } : {
|
|
17202
|
+
status: "failed",
|
|
17203
|
+
error: new ChatUpstreamError("Session prewarm never completed: no session_ready event (request retries exhausted or timed out).", 0, "")
|
|
17204
|
+
};
|
|
17025
17205
|
}
|
|
17026
17206
|
async consumePrewarmStream(response, state, callbacks) {
|
|
17027
17207
|
if (!response.body)
|
|
@@ -17052,12 +17232,18 @@ class ClientSessions {
|
|
|
17052
17232
|
}
|
|
17053
17233
|
case "done": {
|
|
17054
17234
|
PrewarmDoneSchema.parse(data);
|
|
17055
|
-
state.outcome = state.sessionReady ? { status: "ready", session: state.sessionReady } : {
|
|
17235
|
+
state.outcome = state.sessionReady ? { status: "ready", session: state.sessionReady } : {
|
|
17236
|
+
status: "failed",
|
|
17237
|
+
error: new ChatUpstreamError("Session prewarm ended before the session was created upstream.", 0, "")
|
|
17238
|
+
};
|
|
17056
17239
|
return;
|
|
17057
17240
|
}
|
|
17058
17241
|
case "error": {
|
|
17059
|
-
PrewarmErrorSchema.parse(data);
|
|
17060
|
-
state.outcome = state.sessionReady ? { status: "fallback", session: state.sessionReady } : {
|
|
17242
|
+
const payload = PrewarmErrorSchema.parse(data);
|
|
17243
|
+
state.outcome = state.sessionReady ? { status: "fallback", session: state.sessionReady } : {
|
|
17244
|
+
status: "failed",
|
|
17245
|
+
error: new ChatUpstreamError(payload.message, 0, JSON.stringify({ error: payload }))
|
|
17246
|
+
};
|
|
17061
17247
|
return;
|
|
17062
17248
|
}
|
|
17063
17249
|
default:
|
|
@@ -17101,8 +17287,6 @@ var SkillListItemSchema = object2({
|
|
|
17101
17287
|
link: string4(),
|
|
17102
17288
|
descriptionEn: string4(),
|
|
17103
17289
|
descriptionZh: string4(),
|
|
17104
|
-
tagsEn: array2(string4()),
|
|
17105
|
-
tagsZh: array2(string4()),
|
|
17106
17290
|
enabled: boolean4(),
|
|
17107
17291
|
added: boolean4(),
|
|
17108
17292
|
builtIn: boolean4(),
|
|
@@ -17132,8 +17316,6 @@ var PlazaSkillItemSchema = object2({
|
|
|
17132
17316
|
command: string4(),
|
|
17133
17317
|
descriptionEn: string4(),
|
|
17134
17318
|
descriptionZh: string4(),
|
|
17135
|
-
tagsEn: array2(string4()),
|
|
17136
|
-
tagsZh: array2(string4()),
|
|
17137
17319
|
link: string4(),
|
|
17138
17320
|
cover: string4().nullable(),
|
|
17139
17321
|
version: string4(),
|
|
@@ -17807,29 +17989,56 @@ async function resolvePromptAttachments(options) {
|
|
|
17807
17989
|
}
|
|
17808
17990
|
|
|
17809
17991
|
// src/services/session.ts
|
|
17992
|
+
var SESSION_GONE_ERR_CODES = [
|
|
17993
|
+
ErrCode.SESSION_NOT_FOUND,
|
|
17994
|
+
ErrCode.CHAT_SESSION_EXPIRED
|
|
17995
|
+
];
|
|
17810
17996
|
function isSessionGoneError(err) {
|
|
17811
17997
|
if (!(err instanceof ChatUpstreamError))
|
|
17812
17998
|
return false;
|
|
17999
|
+
if (err.errCode !== null) {
|
|
18000
|
+
return SESSION_GONE_ERR_CODES.includes(err.errCode);
|
|
18001
|
+
}
|
|
17813
18002
|
if (err.status === 404)
|
|
17814
18003
|
return true;
|
|
17815
18004
|
return err.body.includes(ERR_SESSION_EXPIRED);
|
|
17816
18005
|
}
|
|
18006
|
+
async function ensureSessionExists(options) {
|
|
18007
|
+
const client = new MediaStudioClient({
|
|
18008
|
+
baseUrl: options.apiBaseUrl,
|
|
18009
|
+
apiKey: options.apiKey
|
|
18010
|
+
});
|
|
18011
|
+
if (await client.sessions.exists(options.sessionId))
|
|
18012
|
+
return;
|
|
18013
|
+
throw new Error(`Session ${options.sessionId} does not exist.
|
|
18014
|
+
` + ' → Create one: `msc sessions use --new`, or `msc chat --new "<prompt>"` to also send a prompt.');
|
|
18015
|
+
}
|
|
18016
|
+
function finalizeProvision(result, spinner) {
|
|
18017
|
+
spinner?.stop();
|
|
18018
|
+
if (result.status === "failed") {
|
|
18019
|
+
throw result.error;
|
|
18020
|
+
}
|
|
18021
|
+
if (result.status === "fallback") {
|
|
18022
|
+
consola.warn("Session created, but sandbox/skill setup did not fully complete. Plain-text chat still works.");
|
|
18023
|
+
}
|
|
18024
|
+
return result.sessionId;
|
|
18025
|
+
}
|
|
17817
18026
|
async function provisionSession(options) {
|
|
17818
|
-
const sessionId = nanoid3();
|
|
17819
18027
|
const client = new MediaStudioClient({
|
|
17820
18028
|
baseUrl: options.apiBaseUrl,
|
|
17821
18029
|
apiKey: options.apiKey
|
|
17822
18030
|
});
|
|
18031
|
+
const sessionId = nanoid3();
|
|
17823
18032
|
const outcome = await client.sessions.prewarm({
|
|
17824
18033
|
sessionId,
|
|
17825
18034
|
source: "cli",
|
|
17826
18035
|
onSessionReady: () => saveLastSessionId(sessionId),
|
|
17827
|
-
|
|
18036
|
+
onStageChange: options.onStageChange
|
|
17828
18037
|
});
|
|
17829
|
-
|
|
17830
|
-
status,
|
|
17831
|
-
|
|
17832
|
-
|
|
18038
|
+
if (outcome.status === "failed") {
|
|
18039
|
+
return { status: "failed", error: outcome.error };
|
|
18040
|
+
}
|
|
18041
|
+
return { status: outcome.status, sessionId };
|
|
17833
18042
|
}
|
|
17834
18043
|
|
|
17835
18044
|
// src/lib/skill-refs.ts
|
|
@@ -17958,34 +18167,34 @@ function printTerminalMediaAssets(mediaAssets, fullText) {
|
|
|
17958
18167
|
process.stdout.write(`====================
|
|
17959
18168
|
`);
|
|
17960
18169
|
}
|
|
17961
|
-
function
|
|
17962
|
-
spinner.
|
|
17963
|
-
|
|
17964
|
-
|
|
17965
|
-
|
|
17966
|
-
|
|
17967
|
-
|
|
17968
|
-
|
|
17969
|
-
return result.sessionId;
|
|
18170
|
+
async function provisionNewSession(options) {
|
|
18171
|
+
const onStageChange = options.quiet ? undefined : (stage) => options.spinner.start(PROVISION_STAGE_LABELS[stage]);
|
|
18172
|
+
const result = await provisionSession({
|
|
18173
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
18174
|
+
apiKey: options.apiKey,
|
|
18175
|
+
onStageChange
|
|
18176
|
+
});
|
|
18177
|
+
return finalizeProvision(result, options.spinner);
|
|
17970
18178
|
}
|
|
17971
18179
|
async function resolveChatSession(options) {
|
|
18180
|
+
if (options.newSession) {
|
|
18181
|
+
return {
|
|
18182
|
+
sessionId: await provisionNewSession(options),
|
|
18183
|
+
recreateOnGone: false
|
|
18184
|
+
};
|
|
18185
|
+
}
|
|
17972
18186
|
if (options.sessionFlag) {
|
|
17973
18187
|
saveLastSessionId(options.sessionFlag);
|
|
17974
|
-
return { sessionId: options.sessionFlag, recreateOnGone:
|
|
18188
|
+
return { sessionId: options.sessionFlag, recreateOnGone: false };
|
|
17975
18189
|
}
|
|
17976
18190
|
const pointer = readLastSessionId();
|
|
17977
18191
|
if (pointer) {
|
|
17978
18192
|
return { sessionId: pointer, recreateOnGone: true };
|
|
17979
18193
|
}
|
|
17980
|
-
|
|
17981
|
-
|
|
17982
|
-
|
|
17983
|
-
|
|
17984
|
-
onStageChange: (stage) => options.spinner.start(PROVISION_STAGE_LABELS[stage])
|
|
17985
|
-
}
|
|
17986
|
-
});
|
|
17987
|
-
const sessionId = finalizeProvision(result, options.spinner);
|
|
17988
|
-
return { sessionId, recreateOnGone: false };
|
|
18194
|
+
return {
|
|
18195
|
+
sessionId: await provisionNewSession(options),
|
|
18196
|
+
recreateOnGone: false
|
|
18197
|
+
};
|
|
17989
18198
|
}
|
|
17990
18199
|
async function streamTurn(options) {
|
|
17991
18200
|
const { args, sessionId, spinner, autoEnabled, attachments } = options;
|
|
@@ -18007,6 +18216,9 @@ async function streamTurn(options) {
|
|
|
18007
18216
|
const mediaAssets = [];
|
|
18008
18217
|
let hasFinished = false;
|
|
18009
18218
|
for await (const ev of stream) {
|
|
18219
|
+
if (ev.type !== "finish" && ev.type !== "error") {
|
|
18220
|
+
options.progress.emitted = true;
|
|
18221
|
+
}
|
|
18010
18222
|
M(ev).with({ type: "text-delta", delta: z2.string }, ({ delta }) => {
|
|
18011
18223
|
isThinking = false;
|
|
18012
18224
|
spinner.stop();
|
|
@@ -18108,17 +18320,28 @@ async function runTurn(options) {
|
|
|
18108
18320
|
try {
|
|
18109
18321
|
await streamTurn(options);
|
|
18110
18322
|
} catch (err) {
|
|
18111
|
-
|
|
18323
|
+
const sessionGone = isSessionGoneError(err);
|
|
18324
|
+
if (sessionGone && options.progress.emitted) {
|
|
18325
|
+
throw new Error(`Session ${options.sessionId} failed after this turn had already started.
|
|
18326
|
+
` + " → The partial result above stands; re-run the same prompt to continue in a new session.");
|
|
18327
|
+
}
|
|
18328
|
+
if (sessionGone && !options.recreateOnGone) {
|
|
18329
|
+
throw new Error(`Session ${options.sessionId} does not exist.
|
|
18330
|
+
` + ' → Create one: `msc sessions use --new`, or `msc chat --new "<prompt>"` to also send a prompt.');
|
|
18331
|
+
}
|
|
18332
|
+
if (sessionGone) {
|
|
18112
18333
|
consola.warn(`Session ${options.sessionId} is no longer available. Provisioning a new one...`);
|
|
18113
|
-
const
|
|
18334
|
+
const sessionId = await provisionNewSession({
|
|
18114
18335
|
apiBaseUrl: options.apiBaseUrl,
|
|
18115
18336
|
apiKey: resolveApiKey(),
|
|
18116
|
-
|
|
18117
|
-
|
|
18118
|
-
|
|
18337
|
+
spinner: options.spinner,
|
|
18338
|
+
quiet: options.args.json === true
|
|
18339
|
+
});
|
|
18340
|
+
await streamTurn({
|
|
18341
|
+
...options,
|
|
18342
|
+
sessionId,
|
|
18343
|
+
apiKey: resolveApiKey()
|
|
18119
18344
|
});
|
|
18120
|
-
const sessionId = finalizeProvision(result, options.spinner);
|
|
18121
|
-
await streamTurn({ ...options, sessionId, apiKey: resolveApiKey() });
|
|
18122
18345
|
return;
|
|
18123
18346
|
}
|
|
18124
18347
|
throw err;
|
|
@@ -18142,7 +18365,11 @@ var chatCommand = defineCommand({
|
|
|
18142
18365
|
},
|
|
18143
18366
|
session: {
|
|
18144
18367
|
type: "string",
|
|
18145
|
-
description: "
|
|
18368
|
+
description: "Chat in an existing session id (verified upstream); becomes the default session. A missing id fails — create one with --new"
|
|
18369
|
+
},
|
|
18370
|
+
new: {
|
|
18371
|
+
type: "boolean",
|
|
18372
|
+
description: "Create a new session and chat in it; becomes the default session"
|
|
18146
18373
|
},
|
|
18147
18374
|
"show-reasoning": {
|
|
18148
18375
|
type: "boolean",
|
|
@@ -18154,6 +18381,16 @@ var chatCommand = defineCommand({
|
|
|
18154
18381
|
const spinner = new AgentSpinner;
|
|
18155
18382
|
try {
|
|
18156
18383
|
const apiBaseUrl = resolveApiBaseUrl();
|
|
18384
|
+
if (args.new && args.session) {
|
|
18385
|
+
throw new Error("--new and --session cannot be combined: --session selects an existing session, --new creates one.");
|
|
18386
|
+
}
|
|
18387
|
+
if (args.session) {
|
|
18388
|
+
await ensureSessionExists({
|
|
18389
|
+
apiBaseUrl,
|
|
18390
|
+
apiKey: resolveApiKey(),
|
|
18391
|
+
sessionId: args.session
|
|
18392
|
+
});
|
|
18393
|
+
}
|
|
18157
18394
|
const { text, skillUrls, autoEnabled } = await resolvePromptSkills({
|
|
18158
18395
|
prompt: args.prompt,
|
|
18159
18396
|
apiBaseUrl,
|
|
@@ -18172,6 +18409,7 @@ var chatCommand = defineCommand({
|
|
|
18172
18409
|
});
|
|
18173
18410
|
const resolved = await resolveChatSession({
|
|
18174
18411
|
sessionFlag: args.session,
|
|
18412
|
+
newSession: args.new,
|
|
18175
18413
|
apiBaseUrl,
|
|
18176
18414
|
apiKey: resolveApiKey(),
|
|
18177
18415
|
spinner,
|
|
@@ -18182,6 +18420,7 @@ var chatCommand = defineCommand({
|
|
|
18182
18420
|
prompt: promptWithAttachments,
|
|
18183
18421
|
sessionId: resolved.sessionId,
|
|
18184
18422
|
recreateOnGone: resolved.recreateOnGone,
|
|
18423
|
+
progress: { emitted: false },
|
|
18185
18424
|
apiBaseUrl,
|
|
18186
18425
|
apiKey: resolveApiKey(),
|
|
18187
18426
|
spinner,
|
|
@@ -18216,6 +18455,12 @@ images, videos, and multimedia content through AI Media Studio.
|
|
|
18216
18455
|
3. Refine in the next turn (multi-turn is automatic):
|
|
18217
18456
|
msc chat "change the car color to emerald green and add rain"
|
|
18218
18457
|
|
|
18458
|
+
Agent Skill (recommended for AI agents):
|
|
18459
|
+
If the agent does not already know how to use msc, install the public
|
|
18460
|
+
Agent Skill before starting a new session:
|
|
18461
|
+
npx -y skills add 302ai/msc-skill --skill msc-skill -g -y
|
|
18462
|
+
This is optional for direct terminal use.
|
|
18463
|
+
|
|
18219
18464
|
|
|
18220
18465
|
2. AUTHENTICATION & SERVERS
|
|
18221
18466
|
|
|
@@ -18274,8 +18519,16 @@ ${getAvailableRegions().map((r) => ` ${r.key.padEnd(8)} - ${r.url} (${r.des
|
|
|
18274
18519
|
"no such file". Remote URLs are not attachments and there is no @url form.
|
|
18275
18520
|
|
|
18276
18521
|
Session Switching:
|
|
18277
|
-
Pass \`--session <id>\` to direct a prompt to
|
|
18278
|
-
|
|
18522
|
+
Pass \`--session <id>\` to direct a prompt to an existing session and make it
|
|
18523
|
+
your new active session. The id is verified against the server first: the
|
|
18524
|
+
CLI only ever selects sessions that exist, so an unknown id fails with a
|
|
18525
|
+
hint instead of silently starting a different conversation.
|
|
18526
|
+
|
|
18527
|
+
Pass \`--new\` to start a fresh session (new id, never reused) and chat in
|
|
18528
|
+
it, ignoring the current default. \`--new\` and \`--session\` are mutually
|
|
18529
|
+
exclusive.
|
|
18530
|
+
msc chat "start over" --new # new session, new context
|
|
18531
|
+
msc sessions # pick an existing id for --session
|
|
18279
18532
|
|
|
18280
18533
|
4. USING SKILLS
|
|
18281
18534
|
|
|
@@ -18316,7 +18569,13 @@ ${getAvailableRegions().map((r) => ` ${r.key.padEnd(8)} - ${r.url} (${r.des
|
|
|
18316
18569
|
including download URLs and model metadata.
|
|
18317
18570
|
|
|
18318
18571
|
msc sessions use <session-id>
|
|
18319
|
-
Switch your active session pointer
|
|
18572
|
+
Switch your active session pointer to an existing session. The id is
|
|
18573
|
+
verified against the server; an unknown id fails here and leaves the
|
|
18574
|
+
pointer untouched.
|
|
18575
|
+
|
|
18576
|
+
msc sessions use --new
|
|
18577
|
+
Create a new session upstream and switch the pointer to it, without sending
|
|
18578
|
+
a prompt.
|
|
18320
18579
|
|
|
18321
18580
|
Session deletion is not available in the CLI. Open the corresponding session
|
|
18322
18581
|
in the Media Studio web app and delete it there manually.
|
|
@@ -18369,6 +18628,13 @@ ${getAvailableRegions().map((r) => ` ${r.key.padEnd(8)} - ${r.url}`).join(`
|
|
|
18369
18628
|
"nextStep": "relogin" // recommended action keyword
|
|
18370
18629
|
}
|
|
18371
18630
|
|
|
18631
|
+
Session commands:
|
|
18632
|
+
msc sessions --json # list: [{ sessionId, note, ... }]
|
|
18633
|
+
msc sessions use <id> --json # { "sessionId": "string" }
|
|
18634
|
+
msc sessions use --new --json # { "sessionId": "string" } (newly created)
|
|
18635
|
+
\`--session\`/\`use <id>\` verify the id upstream; an unknown id exits 1 with
|
|
18636
|
+
the \`--new\` hint and leaves the default session untouched.
|
|
18637
|
+
|
|
18372
18638
|
Recommended next steps:
|
|
18373
18639
|
relogin Session expired or missing; run \`msc login\`
|
|
18374
18640
|
retry_later Rate limit reached; wait before re-sending
|
|
@@ -20361,18 +20627,63 @@ var artifactsCommand = defineCommand({
|
|
|
20361
20627
|
var useSessionCommand = defineCommand({
|
|
20362
20628
|
meta: {
|
|
20363
20629
|
name: "use",
|
|
20364
|
-
description: "Switch default session
|
|
20630
|
+
description: "Switch the default session to an existing session, or create a fresh one with --new"
|
|
20365
20631
|
},
|
|
20366
20632
|
args: {
|
|
20367
20633
|
sessionId: {
|
|
20368
20634
|
type: "positional",
|
|
20369
|
-
required:
|
|
20370
|
-
description: "
|
|
20635
|
+
required: false,
|
|
20636
|
+
description: "Existing session id to set as default"
|
|
20637
|
+
},
|
|
20638
|
+
new: {
|
|
20639
|
+
type: "boolean",
|
|
20640
|
+
description: "Create a new session and make it the default"
|
|
20641
|
+
},
|
|
20642
|
+
json: {
|
|
20643
|
+
type: "boolean",
|
|
20644
|
+
alias: "j",
|
|
20645
|
+
description: "Output machine-readable JSON: { sessionId }"
|
|
20371
20646
|
}
|
|
20372
20647
|
},
|
|
20373
|
-
run: ({ args }) => {
|
|
20374
|
-
|
|
20375
|
-
|
|
20648
|
+
run: async ({ args }) => {
|
|
20649
|
+
try {
|
|
20650
|
+
const sessionId = args.sessionId;
|
|
20651
|
+
const apiBaseUrl = resolveApiBaseUrl();
|
|
20652
|
+
if (args.new) {
|
|
20653
|
+
if (sessionId) {
|
|
20654
|
+
throw new Error("--new and <session-id> cannot be combined: pass one, not both.");
|
|
20655
|
+
}
|
|
20656
|
+
const result = await provisionSession({
|
|
20657
|
+
apiBaseUrl,
|
|
20658
|
+
apiKey: resolveApiKey()
|
|
20659
|
+
});
|
|
20660
|
+
const created = finalizeProvision(result);
|
|
20661
|
+
if (args.json) {
|
|
20662
|
+
process.stdout.write(`${JSON.stringify({ sessionId: created })}
|
|
20663
|
+
`);
|
|
20664
|
+
return;
|
|
20665
|
+
}
|
|
20666
|
+
consola.success(`Created and switched to session ${created}`);
|
|
20667
|
+
return;
|
|
20668
|
+
}
|
|
20669
|
+
if (!sessionId) {
|
|
20670
|
+
throw new Error("Pass the session id to switch to, or --new to create a new session.");
|
|
20671
|
+
}
|
|
20672
|
+
await ensureSessionExists({
|
|
20673
|
+
apiBaseUrl,
|
|
20674
|
+
apiKey: resolveApiKey(),
|
|
20675
|
+
sessionId
|
|
20676
|
+
});
|
|
20677
|
+
saveLastSessionId(sessionId);
|
|
20678
|
+
if (args.json) {
|
|
20679
|
+
process.stdout.write(`${JSON.stringify({ sessionId })}
|
|
20680
|
+
`);
|
|
20681
|
+
return;
|
|
20682
|
+
}
|
|
20683
|
+
consola.success(`Switched default session to ${sessionId}`);
|
|
20684
|
+
} catch (err) {
|
|
20685
|
+
reportCommandError(err, { json: args.json });
|
|
20686
|
+
}
|
|
20376
20687
|
}
|
|
20377
20688
|
});
|
|
20378
20689
|
var sessionsCommand = defineCommand({
|
|
@@ -20752,6 +21063,8 @@ AGENT QUICKSTART
|
|
|
20752
21063
|
1. msc login # a human must finish this in a browser; instant if
|
|
20753
21064
|
# that browser is already signed in to the web app
|
|
20754
21065
|
2. msc chat "a red car" --json # one turn; the conversation continues across runs
|
|
21066
|
+
# (--new starts a fresh session, --session <id> picks
|
|
21067
|
+
# an existing one; both are verified)
|
|
20755
21068
|
3. msc skills --plaza --json # find a skill, then reference it by leading the
|
|
20756
21069
|
# prompt with /name or %%/name%%
|
|
20757
21070
|
|
package/package.json
CHANGED