@agentscope-ai/platform-cli 1.0.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.
@@ -0,0 +1,276 @@
1
+ declare const CLI_VERSION = "0.1.8";
2
+ declare const PLATFORM_URL = "https://platform-pre.agentscope.io";
3
+ declare const DEFAULT_PLATFORM_URL = "https://platform-pre.agentscope.io";
4
+ /** @deprecated Use {@link PLATFORM_URL} */
5
+ declare const PRE_PLATFORM_URL = "https://platform-pre.agentscope.io";
6
+
7
+ interface GlobalOptions {
8
+ platformUrl?: string;
9
+ token?: string;
10
+ verbose?: boolean;
11
+ json?: boolean;
12
+ }
13
+ interface ResolvedConfig {
14
+ platformUrl: string;
15
+ token?: string;
16
+ verbose: boolean;
17
+ json: boolean;
18
+ }
19
+ declare function resolveConfig(opts?: GlobalOptions): ResolvedConfig;
20
+
21
+ interface MetaResponse {
22
+ request_id: string;
23
+ service: string;
24
+ api_version: string;
25
+ platform_url: string;
26
+ environment: string;
27
+ min_cli_version: string;
28
+ recommended_cli_version: string;
29
+ features: Record<string, boolean>;
30
+ }
31
+ interface MeResponse {
32
+ request_id: string;
33
+ user_id?: string;
34
+ account?: string;
35
+ email?: string;
36
+ username?: string;
37
+ is_admin?: boolean;
38
+ user?: {
39
+ id: string;
40
+ display_name?: string;
41
+ email?: string;
42
+ };
43
+ scopes?: string[];
44
+ }
45
+ interface TokenResponse {
46
+ request_id: string;
47
+ access_token: string;
48
+ refresh_token?: string;
49
+ token_type: string;
50
+ expires_in?: number;
51
+ scope?: string;
52
+ user?: {
53
+ id: string;
54
+ display_name?: string;
55
+ email?: string;
56
+ };
57
+ }
58
+ interface RequestLogItem {
59
+ request_id?: string;
60
+ method: string;
61
+ path: string;
62
+ request_body?: unknown;
63
+ response_status?: number;
64
+ duration_ms?: number;
65
+ created_at: string;
66
+ }
67
+ interface RequestLogsResponse {
68
+ request_id: string;
69
+ items: RequestLogItem[];
70
+ next_cursor?: string | null;
71
+ }
72
+ interface PluginListItem {
73
+ plugin_id: string;
74
+ name?: string;
75
+ description?: string;
76
+ summary?: string;
77
+ source?: "official" | "verified" | "community";
78
+ tech_type?: string;
79
+ category?: string;
80
+ author_display_name?: string;
81
+ latest_version?: string;
82
+ downloads?: number;
83
+ public_url?: string;
84
+ updated_at?: string;
85
+ [key: string]: unknown;
86
+ }
87
+ interface PluginListResponse {
88
+ request_id: string;
89
+ items: PluginListItem[];
90
+ next_cursor?: string | null;
91
+ }
92
+ interface PluginVersionItem {
93
+ version: string;
94
+ published_at?: string;
95
+ deprecated?: boolean;
96
+ [key: string]: unknown;
97
+ }
98
+ interface PluginVersionsResponse {
99
+ request_id: string;
100
+ plugin_id: string;
101
+ items: PluginVersionItem[];
102
+ }
103
+ interface PluginInfoResponse {
104
+ request_id: string;
105
+ plugin_id: string;
106
+ install_command?: string;
107
+ public_url?: string;
108
+ latest_version?: string;
109
+ scan_status?: string;
110
+ min_qwenpaw_version?: string;
111
+ [key: string]: unknown;
112
+ }
113
+ interface SkillListItem {
114
+ skill_id: string;
115
+ skill_code?: string;
116
+ name?: string;
117
+ description?: string;
118
+ summary?: string;
119
+ category?: string;
120
+ category_label?: string;
121
+ source?: "official" | "verified" | "community";
122
+ author_display_name?: string;
123
+ latest_version?: string;
124
+ downloads?: number;
125
+ public_url?: string;
126
+ updated_at?: string;
127
+ [key: string]: unknown;
128
+ }
129
+ interface SkillListResponse {
130
+ request_id: string;
131
+ items: SkillListItem[];
132
+ next_cursor?: string | null;
133
+ }
134
+ interface SkillVersionItem {
135
+ version: string;
136
+ published_at?: string;
137
+ deprecated?: boolean;
138
+ [key: string]: unknown;
139
+ }
140
+ interface SkillVersionsResponse {
141
+ request_id: string;
142
+ skill_id: string;
143
+ items: SkillVersionItem[];
144
+ }
145
+ interface SkillInfoResponse {
146
+ request_id: string;
147
+ skill_id: string;
148
+ install_command?: string;
149
+ public_url?: string;
150
+ latest_version?: string;
151
+ scan_status?: string;
152
+ [key: string]: unknown;
153
+ }
154
+ interface InstallIntentResponse {
155
+ request_id: string;
156
+ download_url: string;
157
+ sha512?: string;
158
+ expires_at?: string;
159
+ signature?: string | null;
160
+ scan_status?: string;
161
+ version?: string;
162
+ }
163
+ interface CliSubmissionUpload {
164
+ method?: string;
165
+ url: string;
166
+ headers?: Record<string, string>;
167
+ expires_at?: string;
168
+ }
169
+ interface CliSubmissionScan {
170
+ status?: "queued" | "running" | "passed" | "failed";
171
+ summary?: string;
172
+ [key: string]: unknown;
173
+ }
174
+ interface CliSubmissionPublish {
175
+ status?: string;
176
+ public_url?: string;
177
+ [key: string]: unknown;
178
+ }
179
+ interface CliSubmissionFailure {
180
+ code?: string;
181
+ message?: string;
182
+ }
183
+ interface CliSubmissionResponse {
184
+ request_id: string;
185
+ submission_id: string;
186
+ status: "upload_url_issued" | "queued_for_scan" | "scanning" | "published" | "scan_failed" | "upload_failed" | "expired";
187
+ terminal: boolean;
188
+ upload?: CliSubmissionUpload | null;
189
+ scan?: CliSubmissionScan | null;
190
+ publish?: CliSubmissionPublish | null;
191
+ failure?: CliSubmissionFailure | null;
192
+ links?: {
193
+ status?: string;
194
+ logs?: string;
195
+ };
196
+ next_poll_after_seconds?: number;
197
+ }
198
+ interface CliSubmissionLogItem {
199
+ level: "info" | "error" | string;
200
+ message: string;
201
+ timestamp: string;
202
+ }
203
+ interface CliSubmissionLogsResponse {
204
+ request_id: string;
205
+ submission_id: string;
206
+ items: CliSubmissionLogItem[];
207
+ }
208
+ declare class CliApiClient {
209
+ private readonly http;
210
+ constructor(config: ResolvedConfig);
211
+ private req;
212
+ getMeta(): Promise<MetaResponse>;
213
+ getMe(): Promise<MeResponse>;
214
+ login(account: string, password: string): Promise<TokenResponse>;
215
+ refresh(refreshToken: string): Promise<TokenResponse>;
216
+ oauthToken(body: Record<string, string>): Promise<TokenResponse>;
217
+ oauthRevoke(token: string, tokenTypeHint?: string): Promise<{
218
+ ok: boolean;
219
+ }>;
220
+ logout(): Promise<{
221
+ ok: boolean;
222
+ }>;
223
+ getRequestLogs(params?: {
224
+ page_size?: number;
225
+ cursor?: string;
226
+ }): Promise<RequestLogsResponse>;
227
+ searchPlugins(params?: {
228
+ q?: string;
229
+ category?: string;
230
+ source?: "official" | "verified" | "community";
231
+ sort?: "recommended" | "downloads" | "updated_at";
232
+ page_size?: number;
233
+ cursor?: string;
234
+ }): Promise<PluginListResponse>;
235
+ getPluginInfo(pluginId: string, version?: string): Promise<PluginInfoResponse>;
236
+ getPluginVersions(pluginId: string): Promise<PluginVersionsResponse>;
237
+ createInstallIntent(pluginId: string, version?: string): Promise<InstallIntentResponse>;
238
+ searchSkills(params?: {
239
+ q?: string;
240
+ category?: string;
241
+ source?: "official" | "verified" | "community";
242
+ tag?: string;
243
+ sort?: "recommended" | "downloads" | "updated_at";
244
+ page_size?: number;
245
+ cursor?: string;
246
+ }): Promise<SkillListResponse>;
247
+ getSkillInfo(skillId: string, version?: string): Promise<SkillInfoResponse>;
248
+ getSkillVersions(skillId: string): Promise<SkillVersionsResponse>;
249
+ createSkillInstallIntent(skillId: string, version?: string): Promise<InstallIntentResponse>;
250
+ createArtifactSubmission(body: Record<string, unknown>): Promise<CliSubmissionResponse>;
251
+ completeArtifactSubmission(submissionId: string, body: {
252
+ sha512: string;
253
+ size_bytes: number;
254
+ }): Promise<CliSubmissionResponse>;
255
+ getArtifactSubmission(submissionId: string): Promise<CliSubmissionResponse>;
256
+ getArtifactSubmissionLogs(submissionId: string): Promise<CliSubmissionLogsResponse>;
257
+ }
258
+
259
+ declare class AspError extends Error {
260
+ readonly code: string;
261
+ readonly hint?: string;
262
+ readonly requestId?: string;
263
+ readonly statusCode?: number;
264
+ readonly exitCode: number;
265
+ constructor(message: string, options?: {
266
+ code?: string;
267
+ hint?: string;
268
+ requestId?: string;
269
+ statusCode?: number;
270
+ exitCode?: number;
271
+ cause?: unknown;
272
+ });
273
+ static fromResponse(status: number, body: unknown): AspError;
274
+ }
275
+
276
+ export { AspError, CLI_VERSION, CliApiClient, DEFAULT_PLATFORM_URL, PLATFORM_URL, PRE_PLATFORM_URL, type ResolvedConfig, resolveConfig };
package/dist/index.js ADDED
@@ -0,0 +1,321 @@
1
+ import {
2
+ CLI_API_PREFIX,
3
+ CLI_VERSION,
4
+ DEFAULT_PLATFORM_URL,
5
+ PLATFORM_URL,
6
+ PRE_PLATFORM_URL,
7
+ credentialsFromTokenResponse,
8
+ isTokenExpired,
9
+ loadCredentials,
10
+ resolveConfig,
11
+ saveCredentials
12
+ } from "./chunk-L5UHVBIK.js";
13
+
14
+ // src/utils/errors.ts
15
+ var AspError = class _AspError extends Error {
16
+ code;
17
+ hint;
18
+ requestId;
19
+ statusCode;
20
+ exitCode;
21
+ constructor(message, options = {}) {
22
+ super(message, { cause: options.cause });
23
+ this.name = "AspError";
24
+ this.code = options.code ?? "UNKNOWN";
25
+ this.hint = options.hint;
26
+ this.requestId = options.requestId;
27
+ this.statusCode = options.statusCode;
28
+ this.exitCode = options.exitCode ?? 1;
29
+ }
30
+ static fromResponse(status, body) {
31
+ const parsed = body;
32
+ if (parsed?.error) {
33
+ const exitCode = mapErrorCodeToExit(parsed.error.code, status);
34
+ let hint = parsed.error.hint ?? parsed.error.detail;
35
+ if (parsed.error.code === "ASP.COMM.NOT_FOUND") {
36
+ hint = hint ?? "The API endpoint is not available on this Platform environment.";
37
+ }
38
+ return new _AspError(parsed.error.message, {
39
+ code: parsed.error.code,
40
+ hint,
41
+ requestId: parsed.request_id,
42
+ statusCode: status,
43
+ exitCode
44
+ });
45
+ }
46
+ return new _AspError(`HTTP ${status}`, {
47
+ code: "HTTP_ERROR",
48
+ statusCode: status,
49
+ exitCode: status >= 500 ? 2 : 1
50
+ });
51
+ }
52
+ };
53
+ function mapErrorCodeToExit(code, status) {
54
+ if (code === "UNAUTHORIZED" || code === "UNAUTHENTICATED" || code === "ASP.AUTH.UNAUTHORIZED" || code === "ASP.AUTH.SESSION_INVALID" || code === "SESSION_INVALID") {
55
+ return 3;
56
+ }
57
+ if (code === "FORBIDDEN") return 4;
58
+ if (status >= 500) return 2;
59
+ return 1;
60
+ }
61
+ function maskSecrets(text) {
62
+ return text.replace(/Bearer\s+[A-Za-z0-9._-]+/gi, "Bearer [REDACTED]").replace(/"access_token"\s*:\s*"[^"]+"/gi, '"access_token":"[REDACTED]"').replace(/"refresh_token"\s*:\s*"[^"]+"/gi, '"refresh_token":"[REDACTED]"').replace(/"token"\s*:\s*"[^"]+"/gi, '"token":"[REDACTED]"');
63
+ }
64
+
65
+ // src/auth/session.ts
66
+ function isSessionInvalidError(err) {
67
+ if (!(err instanceof AspError)) return false;
68
+ return err.code === "ASP.AUTH.SESSION_INVALID" || err.code === "SESSION_INVALID";
69
+ }
70
+ async function refreshStoredSession(config, refreshToken, platformUrl) {
71
+ const client = new CliApiClient({
72
+ ...config,
73
+ token: void 0,
74
+ platformUrl: platformUrl.replace(/\/$/, "")
75
+ });
76
+ const refreshed = await client.refresh(refreshToken);
77
+ const creds = credentialsFromTokenResponse(platformUrl, refreshed);
78
+ await saveCredentials(creds);
79
+ return creds;
80
+ }
81
+
82
+ // src/api/client.ts
83
+ var HttpClient = class {
84
+ constructor(config) {
85
+ this.config = config;
86
+ }
87
+ config;
88
+ async request(opts) {
89
+ try {
90
+ return await this.doRequest(opts);
91
+ } catch (err) {
92
+ if (opts.auth !== false && !opts._retried && isSessionInvalidError(err) && !this.config.token) {
93
+ const creds = await loadCredentials();
94
+ if (creds?.refresh_token) {
95
+ await refreshStoredSession(configWithPlatform(this.config, creds), creds.refresh_token, creds.platform_url);
96
+ return this.doRequest({ ...opts, _retried: true });
97
+ }
98
+ }
99
+ throw err;
100
+ }
101
+ }
102
+ async doRequest(opts) {
103
+ const creds = opts.auth !== false && !this.config.token ? await loadCredentials() : null;
104
+ const platformUrl = creds?.platform_url ?? this.config.platformUrl;
105
+ const prefix = opts.prefix ?? "";
106
+ const url = `${platformUrl}${prefix}${opts.path}`;
107
+ const headers = {
108
+ Accept: "application/json",
109
+ ...opts.headers
110
+ };
111
+ if (opts.body !== void 0) {
112
+ headers["Content-Type"] = "application/json";
113
+ }
114
+ if (opts.auth !== false) {
115
+ const token = await this.resolveAccessToken(creds);
116
+ if (token) {
117
+ headers.Authorization = `Bearer ${token}`;
118
+ }
119
+ }
120
+ if (this.config.verbose) {
121
+ console.error(`[verbose] ${opts.method ?? "GET"} ${url}`);
122
+ if (opts.body) console.error(maskSecrets(JSON.stringify(opts.body)));
123
+ }
124
+ const res = await fetch(url, {
125
+ method: opts.method ?? "GET",
126
+ headers,
127
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
128
+ });
129
+ const text = await res.text();
130
+ let data = {};
131
+ if (text) {
132
+ try {
133
+ data = JSON.parse(text);
134
+ } catch {
135
+ data = { raw: text };
136
+ }
137
+ }
138
+ if (this.config.verbose) {
139
+ console.error(`[verbose] ${res.status}`, maskSecrets(text.slice(0, 2e3)));
140
+ }
141
+ if (!res.ok) {
142
+ throw AspError.fromResponse(res.status, data);
143
+ }
144
+ return data;
145
+ }
146
+ async resolveAccessToken(existing) {
147
+ if (this.config.token) return this.config.token;
148
+ const creds = existing ?? await loadCredentials();
149
+ if (!creds) return void 0;
150
+ if (isTokenExpired(creds) && creds.refresh_token) {
151
+ const refreshed = await refreshStoredSession(
152
+ configWithPlatform(this.config, creds),
153
+ creds.refresh_token,
154
+ creds.platform_url
155
+ );
156
+ return refreshed.access_token;
157
+ }
158
+ return creds.access_token;
159
+ }
160
+ };
161
+ function configWithPlatform(config, creds) {
162
+ return { ...config, platformUrl: creds.platform_url || config.platformUrl };
163
+ }
164
+
165
+ // src/api/cli-api.ts
166
+ var CliApiClient = class {
167
+ http;
168
+ constructor(config) {
169
+ this.http = new HttpClient(config);
170
+ }
171
+ req(opts) {
172
+ return this.http.request({ ...opts, prefix: CLI_API_PREFIX });
173
+ }
174
+ getMeta() {
175
+ return this.req({ path: "/meta", auth: false });
176
+ }
177
+ getMe() {
178
+ return this.req({ path: "/me" });
179
+ }
180
+ login(account, password) {
181
+ return this.req({
182
+ method: "POST",
183
+ path: "/auth/login",
184
+ auth: false,
185
+ body: { account, password }
186
+ });
187
+ }
188
+ refresh(refreshToken) {
189
+ return this.req({
190
+ method: "POST",
191
+ path: "/auth/refresh",
192
+ auth: false,
193
+ body: { refresh_token: refreshToken }
194
+ });
195
+ }
196
+ oauthToken(body) {
197
+ return this.req({ method: "POST", path: "/oauth/token", auth: false, body });
198
+ }
199
+ oauthRevoke(token, tokenTypeHint = "refresh_token") {
200
+ return this.req({
201
+ method: "POST",
202
+ path: "/oauth/revoke",
203
+ body: { token, token_type_hint: tokenTypeHint }
204
+ });
205
+ }
206
+ async logout() {
207
+ try {
208
+ return await this.req({ method: "POST", path: "/auth/logout" });
209
+ } catch {
210
+ return this.oauthRevoke("", "access_token");
211
+ }
212
+ }
213
+ getRequestLogs(params) {
214
+ const query = new URLSearchParams();
215
+ if (params?.page_size !== void 0) query.set("page_size", String(params.page_size));
216
+ if (params?.cursor) query.set("cursor", params.cursor);
217
+ const suffix = query.toString();
218
+ return this.req({ path: `/request-logs${suffix ? `?${suffix}` : ""}` });
219
+ }
220
+ searchPlugins(params) {
221
+ const query = new URLSearchParams();
222
+ if (params?.q) query.set("q", params.q);
223
+ if (params?.category) query.set("category", params.category);
224
+ if (params?.source) query.set("source", params.source);
225
+ if (params?.sort) query.set("sort", params.sort);
226
+ if (params?.page_size !== void 0) query.set("page_size", String(params.page_size));
227
+ if (params?.cursor) query.set("cursor", params.cursor);
228
+ const suffix = query.toString();
229
+ return this.req({ path: `/plugins${suffix ? `?${suffix}` : ""}`, auth: false });
230
+ }
231
+ getPluginInfo(pluginId, version) {
232
+ const query = new URLSearchParams();
233
+ if (version) query.set("version", version);
234
+ const suffix = query.toString();
235
+ return this.req({
236
+ path: `/plugins/${encodeURIComponent(pluginId)}${suffix ? `?${suffix}` : ""}`,
237
+ auth: false
238
+ });
239
+ }
240
+ getPluginVersions(pluginId) {
241
+ return this.req({
242
+ path: `/plugins/${encodeURIComponent(pluginId)}/versions`,
243
+ auth: false
244
+ });
245
+ }
246
+ createInstallIntent(pluginId, version) {
247
+ return this.req({
248
+ method: "POST",
249
+ path: `/plugins/${encodeURIComponent(pluginId)}/install-intent`,
250
+ body: version ? { version } : {}
251
+ });
252
+ }
253
+ searchSkills(params) {
254
+ const query = new URLSearchParams();
255
+ if (params?.q) query.set("q", params.q);
256
+ if (params?.category) query.set("category", params.category);
257
+ if (params?.source) query.set("source", params.source);
258
+ if (params?.tag) query.set("tag", params.tag);
259
+ if (params?.sort) query.set("sort", params.sort);
260
+ if (params?.page_size !== void 0) query.set("page_size", String(params.page_size));
261
+ if (params?.cursor) query.set("cursor", params.cursor);
262
+ const suffix = query.toString();
263
+ return this.req({ path: `/skills${suffix ? `?${suffix}` : ""}`, auth: false });
264
+ }
265
+ getSkillInfo(skillId, version) {
266
+ const query = new URLSearchParams();
267
+ if (version) query.set("version", version);
268
+ const suffix = query.toString();
269
+ return this.req({
270
+ path: `/skills/${encodeURIComponent(skillId)}${suffix ? `?${suffix}` : ""}`,
271
+ auth: false
272
+ });
273
+ }
274
+ getSkillVersions(skillId) {
275
+ return this.req({
276
+ path: `/skills/${encodeURIComponent(skillId)}/versions`,
277
+ auth: false
278
+ });
279
+ }
280
+ createSkillInstallIntent(skillId, version) {
281
+ return this.req({
282
+ method: "POST",
283
+ path: `/skills/${encodeURIComponent(skillId)}/install-intent`,
284
+ body: version ? { version } : {}
285
+ });
286
+ }
287
+ createArtifactSubmission(body) {
288
+ return this.req({
289
+ method: "POST",
290
+ path: "/artifact-submissions",
291
+ body
292
+ });
293
+ }
294
+ completeArtifactSubmission(submissionId, body) {
295
+ return this.req({
296
+ method: "POST",
297
+ path: `/artifact-submissions/${encodeURIComponent(submissionId)}/complete`,
298
+ body
299
+ });
300
+ }
301
+ getArtifactSubmission(submissionId) {
302
+ return this.req({
303
+ path: `/artifact-submissions/${encodeURIComponent(submissionId)}`
304
+ });
305
+ }
306
+ getArtifactSubmissionLogs(submissionId) {
307
+ return this.req({
308
+ path: `/artifact-submissions/${encodeURIComponent(submissionId)}/logs`
309
+ });
310
+ }
311
+ };
312
+ export {
313
+ AspError,
314
+ CLI_VERSION,
315
+ CliApiClient,
316
+ DEFAULT_PLATFORM_URL,
317
+ PLATFORM_URL,
318
+ PRE_PLATFORM_URL,
319
+ resolveConfig
320
+ };
321
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/errors.ts","../src/auth/session.ts","../src/api/client.ts","../src/api/cli-api.ts"],"sourcesContent":["export interface ApiErrorBody {\n request_id?: string;\n error: {\n code: string;\n message: string;\n hint?: string;\n };\n}\n\nexport class AspError extends Error {\n readonly code: string;\n readonly hint?: string;\n readonly requestId?: string;\n readonly statusCode?: number;\n readonly exitCode: number;\n\n constructor(\n message: string,\n options: {\n code?: string;\n hint?: string;\n requestId?: string;\n statusCode?: number;\n exitCode?: number;\n cause?: unknown;\n } = {},\n ) {\n super(message, { cause: options.cause });\n this.name = \"AspError\";\n this.code = options.code ?? \"UNKNOWN\";\n this.hint = options.hint;\n this.requestId = options.requestId;\n this.statusCode = options.statusCode;\n this.exitCode = options.exitCode ?? 1;\n }\n\n static fromResponse(status: number, body: unknown): AspError {\n const parsed = body as Partial<ApiErrorBody> & {\n error?: ApiErrorBody[\"error\"] & { detail?: string };\n };\n if (parsed?.error) {\n const exitCode = mapErrorCodeToExit(parsed.error.code, status);\n let hint = parsed.error.hint ?? parsed.error.detail;\n if (parsed.error.code === \"ASP.COMM.NOT_FOUND\") {\n hint = hint ?? \"The API endpoint is not available on this Platform environment.\";\n }\n return new AspError(parsed.error.message, {\n code: parsed.error.code,\n hint,\n requestId: parsed.request_id,\n statusCode: status,\n exitCode,\n });\n }\n return new AspError(`HTTP ${status}`, {\n code: \"HTTP_ERROR\",\n statusCode: status,\n exitCode: status >= 500 ? 2 : 1,\n });\n }\n}\n\nfunction mapErrorCodeToExit(code: string, status: number): number {\n if (\n code === \"UNAUTHORIZED\" ||\n code === \"UNAUTHENTICATED\" ||\n code === \"ASP.AUTH.UNAUTHORIZED\" ||\n code === \"ASP.AUTH.SESSION_INVALID\" ||\n code === \"SESSION_INVALID\"\n ) {\n return 3;\n }\n if (code === \"FORBIDDEN\") return 4;\n if (status >= 500) return 2;\n return 1;\n}\n\nexport function maskSecrets(text: string): string {\n return text\n .replace(/Bearer\\s+[A-Za-z0-9._-]+/gi, \"Bearer [REDACTED]\")\n .replace(/\"access_token\"\\s*:\\s*\"[^\"]+\"/gi, '\"access_token\":\"[REDACTED]\"')\n .replace(/\"refresh_token\"\\s*:\\s*\"[^\"]+\"/gi, '\"refresh_token\":\"[REDACTED]\"')\n .replace(/\"token\"\\s*:\\s*\"[^\"]+\"/gi, '\"token\":\"[REDACTED]\"');\n}\n","import type { ResolvedConfig } from \"../config.js\";\nimport { CliApiClient, type TokenResponse } from \"../api/cli-api.js\";\nimport {\n credentialsFromTokenResponse,\n saveCredentials,\n type StoredCredentials,\n} from \"./credentials.js\";\nimport { AspError } from \"../utils/errors.js\";\n\nexport function isSessionInvalidError(err: unknown): boolean {\n if (!(err instanceof AspError)) return false;\n return err.code === \"ASP.AUTH.SESSION_INVALID\" || err.code === \"SESSION_INVALID\";\n}\n\nexport async function refreshStoredSession(\n config: ResolvedConfig,\n refreshToken: string,\n platformUrl: string,\n): Promise<StoredCredentials> {\n const client = new CliApiClient({\n ...config,\n token: undefined,\n platformUrl: platformUrl.replace(/\\/$/, \"\"),\n });\n const refreshed = await client.refresh(refreshToken);\n const creds = credentialsFromTokenResponse(platformUrl, refreshed);\n await saveCredentials(creds);\n return creds;\n}\n\n/** Login 返回的 access_token 在 pre 环境需先 refresh 才能访问 /me */\nexport async function finalizeLogin(\n config: ResolvedConfig,\n loginResponse: TokenResponse,\n): Promise<StoredCredentials> {\n if (!loginResponse.refresh_token) {\n const creds = credentialsFromTokenResponse(config.platformUrl, loginResponse);\n await saveCredentials(creds);\n return creds;\n }\n\n try {\n return await refreshStoredSession(\n config,\n loginResponse.refresh_token,\n config.platformUrl,\n );\n } catch {\n const creds = credentialsFromTokenResponse(config.platformUrl, loginResponse);\n await saveCredentials(creds);\n return creds;\n }\n}\n\nexport async function ensureValidSession(config: ResolvedConfig): Promise<StoredCredentials> {\n const { loadCredentials, isTokenExpired } = await import(\"./credentials.js\");\n const creds = await loadCredentials();\n if (!creds) {\n throw new AspError(\"Not logged in.\", {\n code: \"UNAUTHORIZED\",\n hint: \"Run `asp auth login`.\",\n exitCode: 3,\n });\n }\n\n if (!isTokenExpired(creds) && creds.access_token) {\n return creds;\n }\n\n if (!creds.refresh_token) {\n throw new AspError(\"Session expired.\", {\n code: \"ASP.AUTH.SESSION_INVALID\",\n hint: \"Run `asp auth login`.\",\n exitCode: 3,\n });\n }\n\n return refreshStoredSession(config, creds.refresh_token, creds.platform_url);\n}\n","import { AspError, maskSecrets } from \"../utils/errors.js\";\nimport type { ResolvedConfig } from \"../config.js\";\nimport {\n loadCredentials,\n isTokenExpired,\n type StoredCredentials,\n} from \"../auth/credentials.js\";\nimport { refreshStoredSession, isSessionInvalidError } from \"../auth/session.js\";\n\nexport interface RequestOptions {\n method?: string;\n path: string;\n body?: unknown;\n headers?: Record<string, string>;\n auth?: boolean;\n prefix?: string;\n _retried?: boolean;\n}\n\nexport class HttpClient {\n constructor(private readonly config: ResolvedConfig) {}\n\n async request<T>(opts: RequestOptions): Promise<T> {\n try {\n return await this.doRequest<T>(opts);\n } catch (err) {\n if (\n opts.auth !== false &&\n !opts._retried &&\n isSessionInvalidError(err) &&\n !this.config.token\n ) {\n const creds = await loadCredentials();\n if (creds?.refresh_token) {\n await refreshStoredSession(configWithPlatform(this.config, creds), creds.refresh_token, creds.platform_url);\n return this.doRequest<T>({ ...opts, _retried: true });\n }\n }\n throw err;\n }\n }\n\n private async doRequest<T>(opts: RequestOptions): Promise<T> {\n const creds = opts.auth !== false && !this.config.token ? await loadCredentials() : null;\n const platformUrl = creds?.platform_url ?? this.config.platformUrl;\n const prefix = opts.prefix ?? \"\";\n const url = `${platformUrl}${prefix}${opts.path}`;\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n ...opts.headers,\n };\n\n if (opts.body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n if (opts.auth !== false) {\n const token = await this.resolveAccessToken(creds);\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n }\n\n if (this.config.verbose) {\n console.error(`[verbose] ${opts.method ?? \"GET\"} ${url}`);\n if (opts.body) console.error(maskSecrets(JSON.stringify(opts.body)));\n }\n\n const res = await fetch(url, {\n method: opts.method ?? \"GET\",\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n });\n\n const text = await res.text();\n let data: unknown = {};\n if (text) {\n try {\n data = JSON.parse(text);\n } catch {\n data = { raw: text };\n }\n }\n\n if (this.config.verbose) {\n console.error(`[verbose] ${res.status}`, maskSecrets(text.slice(0, 2000)));\n }\n\n if (!res.ok) {\n throw AspError.fromResponse(res.status, data);\n }\n\n return data as T;\n }\n\n async resolveAccessToken(existing?: StoredCredentials | null): Promise<string | undefined> {\n if (this.config.token) return this.config.token;\n\n const creds = existing ?? (await loadCredentials());\n if (!creds) return undefined;\n\n if (isTokenExpired(creds) && creds.refresh_token) {\n const refreshed = await refreshStoredSession(\n configWithPlatform(this.config, creds),\n creds.refresh_token,\n creds.platform_url,\n );\n return refreshed.access_token;\n }\n\n return creds.access_token;\n }\n}\n\nfunction configWithPlatform(config: ResolvedConfig, creds: StoredCredentials): ResolvedConfig {\n return { ...config, platformUrl: creds.platform_url || config.platformUrl };\n}\n","import { CLI_API_PREFIX } from \"../constants.js\";\nimport type { ResolvedConfig } from \"../config.js\";\nimport { HttpClient } from \"./client.js\";\n\nexport interface MetaResponse {\n request_id: string;\n service: string;\n api_version: string;\n platform_url: string;\n environment: string;\n min_cli_version: string;\n recommended_cli_version: string;\n features: Record<string, boolean>;\n}\n\nexport interface MeResponse {\n request_id: string;\n user_id?: string;\n account?: string;\n email?: string;\n username?: string;\n is_admin?: boolean;\n user?: {\n id: string;\n display_name?: string;\n email?: string;\n };\n scopes?: string[];\n}\n\nexport interface TokenResponse {\n request_id: string;\n access_token: string;\n refresh_token?: string;\n token_type: string;\n expires_in?: number;\n scope?: string;\n user?: {\n id: string;\n display_name?: string;\n email?: string;\n };\n}\n\n\nexport interface RequestLogItem {\n request_id?: string;\n method: string;\n path: string;\n request_body?: unknown;\n response_status?: number;\n duration_ms?: number;\n created_at: string;\n}\n\nexport interface RequestLogsResponse {\n request_id: string;\n items: RequestLogItem[];\n next_cursor?: string | null;\n}\n\nexport interface PluginListItem {\n plugin_id: string;\n name?: string;\n description?: string;\n summary?: string;\n source?: \"official\" | \"verified\" | \"community\";\n tech_type?: string;\n category?: string;\n author_display_name?: string;\n latest_version?: string;\n downloads?: number;\n public_url?: string;\n updated_at?: string;\n [key: string]: unknown;\n}\n\nexport interface PluginListResponse {\n request_id: string;\n items: PluginListItem[];\n next_cursor?: string | null;\n}\n\nexport interface PluginVersionItem {\n version: string;\n published_at?: string;\n deprecated?: boolean;\n [key: string]: unknown;\n}\n\nexport interface PluginVersionsResponse {\n request_id: string;\n plugin_id: string;\n items: PluginVersionItem[];\n}\n\nexport interface PluginInfoResponse {\n request_id: string;\n plugin_id: string;\n install_command?: string;\n public_url?: string;\n latest_version?: string;\n scan_status?: string;\n min_qwenpaw_version?: string;\n [key: string]: unknown;\n}\n\nexport interface SkillListItem {\n skill_id: string;\n skill_code?: string;\n name?: string;\n description?: string;\n summary?: string;\n category?: string;\n category_label?: string;\n source?: \"official\" | \"verified\" | \"community\";\n author_display_name?: string;\n latest_version?: string;\n downloads?: number;\n public_url?: string;\n updated_at?: string;\n [key: string]: unknown;\n}\n\nexport interface SkillListResponse {\n request_id: string;\n items: SkillListItem[];\n next_cursor?: string | null;\n}\n\nexport interface SkillVersionItem {\n version: string;\n published_at?: string;\n deprecated?: boolean;\n [key: string]: unknown;\n}\n\nexport interface SkillVersionsResponse {\n request_id: string;\n skill_id: string;\n items: SkillVersionItem[];\n}\n\nexport interface SkillInfoResponse {\n request_id: string;\n skill_id: string;\n install_command?: string;\n public_url?: string;\n latest_version?: string;\n scan_status?: string;\n [key: string]: unknown;\n}\n\nexport interface InstallIntentResponse {\n request_id: string;\n download_url: string;\n sha512?: string;\n expires_at?: string;\n signature?: string | null;\n scan_status?: string;\n version?: string;\n}\n\nexport interface CliSubmissionUpload {\n method?: string;\n url: string;\n headers?: Record<string, string>;\n expires_at?: string;\n}\n\nexport interface CliSubmissionScan {\n status?: \"queued\" | \"running\" | \"passed\" | \"failed\";\n summary?: string;\n [key: string]: unknown;\n}\n\nexport interface CliSubmissionPublish {\n status?: string;\n public_url?: string;\n [key: string]: unknown;\n}\n\nexport interface CliSubmissionFailure {\n code?: string;\n message?: string;\n}\n\nexport interface CliSubmissionResponse {\n request_id: string;\n submission_id: string;\n status:\n | \"upload_url_issued\"\n | \"queued_for_scan\"\n | \"scanning\"\n | \"published\"\n | \"scan_failed\"\n | \"upload_failed\"\n | \"expired\";\n terminal: boolean;\n upload?: CliSubmissionUpload | null;\n scan?: CliSubmissionScan | null;\n publish?: CliSubmissionPublish | null;\n failure?: CliSubmissionFailure | null;\n links?: { status?: string; logs?: string };\n next_poll_after_seconds?: number;\n}\n\nexport interface CliSubmissionLogItem {\n level: \"info\" | \"error\" | string;\n message: string;\n timestamp: string;\n}\n\nexport interface CliSubmissionLogsResponse {\n request_id: string;\n submission_id: string;\n items: CliSubmissionLogItem[];\n}\n\nexport class CliApiClient {\n private readonly http: HttpClient;\n\n constructor(config: ResolvedConfig) {\n this.http = new HttpClient(config);\n }\n\n private req<T>(opts: Parameters<HttpClient[\"request\"]>[0]): Promise<T> {\n return this.http.request<T>({ ...opts, prefix: CLI_API_PREFIX });\n }\n\n getMeta(): Promise<MetaResponse> {\n return this.req({ path: \"/meta\", auth: false });\n }\n\n getMe(): Promise<MeResponse> {\n return this.req({ path: \"/me\" });\n }\n\n login(account: string, password: string): Promise<TokenResponse> {\n return this.req({\n method: \"POST\",\n path: \"/auth/login\",\n auth: false,\n body: { account, password },\n });\n }\n\n refresh(refreshToken: string): Promise<TokenResponse> {\n return this.req({\n method: \"POST\",\n path: \"/auth/refresh\",\n auth: false,\n body: { refresh_token: refreshToken },\n });\n }\n\n oauthToken(body: Record<string, string>): Promise<TokenResponse> {\n return this.req({ method: \"POST\", path: \"/oauth/token\", auth: false, body });\n }\n\n oauthRevoke(token: string, tokenTypeHint = \"refresh_token\"): Promise<{ ok: boolean }> {\n return this.req<{ ok: boolean }>({\n method: \"POST\",\n path: \"/oauth/revoke\",\n body: { token, token_type_hint: tokenTypeHint },\n });\n }\n\n async logout(): Promise<{ ok: boolean }> {\n try {\n return await this.req<{ ok: boolean }>({ method: \"POST\", path: \"/auth/logout\" });\n } catch {\n return this.oauthRevoke(\"\", \"access_token\");\n }\n }\n\n getRequestLogs(params?: {\n page_size?: number;\n cursor?: string;\n }): Promise<RequestLogsResponse> {\n const query = new URLSearchParams();\n if (params?.page_size !== undefined) query.set(\"page_size\", String(params.page_size));\n if (params?.cursor) query.set(\"cursor\", params.cursor);\n const suffix = query.toString();\n return this.req({ path: `/request-logs${suffix ? `?${suffix}` : \"\"}` });\n }\n\n searchPlugins(params?: {\n q?: string;\n category?: string;\n source?: \"official\" | \"verified\" | \"community\";\n sort?: \"recommended\" | \"downloads\" | \"updated_at\";\n page_size?: number;\n cursor?: string;\n }): Promise<PluginListResponse> {\n const query = new URLSearchParams();\n if (params?.q) query.set(\"q\", params.q);\n if (params?.category) query.set(\"category\", params.category);\n if (params?.source) query.set(\"source\", params.source);\n if (params?.sort) query.set(\"sort\", params.sort);\n if (params?.page_size !== undefined) query.set(\"page_size\", String(params.page_size));\n if (params?.cursor) query.set(\"cursor\", params.cursor);\n const suffix = query.toString();\n return this.req({ path: `/plugins${suffix ? `?${suffix}` : \"\"}`, auth: false });\n }\n\n getPluginInfo(pluginId: string, version?: string): Promise<PluginInfoResponse> {\n const query = new URLSearchParams();\n if (version) query.set(\"version\", version);\n const suffix = query.toString();\n return this.req({\n path: `/plugins/${encodeURIComponent(pluginId)}${suffix ? `?${suffix}` : \"\"}`,\n auth: false,\n });\n }\n\n getPluginVersions(pluginId: string): Promise<PluginVersionsResponse> {\n return this.req({\n path: `/plugins/${encodeURIComponent(pluginId)}/versions`,\n auth: false,\n });\n }\n\n createInstallIntent(pluginId: string, version?: string): Promise<InstallIntentResponse> {\n return this.req({\n method: \"POST\",\n path: `/plugins/${encodeURIComponent(pluginId)}/install-intent`,\n body: version ? { version } : {},\n });\n }\n\n searchSkills(params?: {\n q?: string;\n category?: string;\n source?: \"official\" | \"verified\" | \"community\";\n tag?: string;\n sort?: \"recommended\" | \"downloads\" | \"updated_at\";\n page_size?: number;\n cursor?: string;\n }): Promise<SkillListResponse> {\n const query = new URLSearchParams();\n if (params?.q) query.set(\"q\", params.q);\n if (params?.category) query.set(\"category\", params.category);\n if (params?.source) query.set(\"source\", params.source);\n if (params?.tag) query.set(\"tag\", params.tag);\n if (params?.sort) query.set(\"sort\", params.sort);\n if (params?.page_size !== undefined) query.set(\"page_size\", String(params.page_size));\n if (params?.cursor) query.set(\"cursor\", params.cursor);\n const suffix = query.toString();\n return this.req({ path: `/skills${suffix ? `?${suffix}` : \"\"}`, auth: false });\n }\n\n getSkillInfo(skillId: string, version?: string): Promise<SkillInfoResponse> {\n const query = new URLSearchParams();\n if (version) query.set(\"version\", version);\n const suffix = query.toString();\n return this.req({\n path: `/skills/${encodeURIComponent(skillId)}${suffix ? `?${suffix}` : \"\"}`,\n auth: false,\n });\n }\n\n getSkillVersions(skillId: string): Promise<SkillVersionsResponse> {\n return this.req({\n path: `/skills/${encodeURIComponent(skillId)}/versions`,\n auth: false,\n });\n }\n\n createSkillInstallIntent(skillId: string, version?: string): Promise<InstallIntentResponse> {\n return this.req({\n method: \"POST\",\n path: `/skills/${encodeURIComponent(skillId)}/install-intent`,\n body: version ? { version } : {},\n });\n }\n\n createArtifactSubmission(body: Record<string, unknown>): Promise<CliSubmissionResponse> {\n return this.req({\n method: \"POST\",\n path: \"/artifact-submissions\",\n body,\n });\n }\n\n completeArtifactSubmission(\n submissionId: string,\n body: { sha512: string; size_bytes: number },\n ): Promise<CliSubmissionResponse> {\n return this.req({\n method: \"POST\",\n path: `/artifact-submissions/${encodeURIComponent(submissionId)}/complete`,\n body,\n });\n }\n\n getArtifactSubmission(submissionId: string): Promise<CliSubmissionResponse> {\n return this.req({\n path: `/artifact-submissions/${encodeURIComponent(submissionId)}`,\n });\n }\n\n getArtifactSubmissionLogs(submissionId: string): Promise<CliSubmissionLogsResponse> {\n return this.req({\n path: `/artifact-submissions/${encodeURIComponent(submissionId)}/logs`,\n });\n }\n}\n"],"mappings":"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","names":[]}