@remixmate/cli 0.9.72 → 0.9.73
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/LICENSE +45 -21
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/argv.js +1 -51
- package/dist/auth/auth-lock.js +1 -100
- package/dist/auth/auto-login.js +7 -75
- package/dist/auth/commands.js +40 -290
- package/dist/auth/credential-store.js +1 -143
- package/dist/auth/device-flow-runner.js +13 -110
- package/dist/auth/device-flow.js +1 -132
- package/dist/auth/ensure.js +1 -62
- package/dist/auth/environment.js +1 -69
- package/dist/auth/pending-store.js +1 -45
- package/dist/auth/resolve.js +1 -44
- package/dist/billing.js +3 -76
- package/dist/capabilities.js +1 -75
- package/dist/cli.js +39 -211
- package/dist/diagnostics.js +2 -70
- package/dist/doctor.js +9 -188
- package/dist/errors.js +1 -33
- package/dist/exec.js +4 -47
- package/dist/handlers/gen-digital-human.js +33 -264
- package/dist/handlers/gen-image.js +9 -113
- package/dist/handlers/gen-post.js +15 -192
- package/dist/handlers/gen-video.js +7 -185
- package/dist/handlers/gen-voice.js +19 -133
- package/dist/handlers/index.js +1 -20
- package/dist/handlers/shared.js +1 -66
- package/dist/handlers/template-init.js +1 -21
- package/dist/http.js +3 -155
- package/dist/index.js +1 -8
- package/dist/install.js +40 -448
- package/dist/manifest.json +44 -3
- package/dist/progress.js +2 -15
- package/dist/project/commands.js +34 -156
- package/dist/project/host.js +1 -151
- package/dist/project/resolve.js +1 -65
- package/dist/project/store.js +2 -97
- package/dist/project/take.js +1 -106
- package/dist/project/trace.js +5 -278
- package/dist/registry.js +3 -70
- package/dist/runner.js +7 -225
- package/dist/skill-schema.js +1 -194
- package/dist/template/args.js +1 -69
- package/dist/template/check.js +2 -30
- package/dist/template/commands.js +34 -163
- package/dist/template/constants.js +1 -46
- package/dist/template/init.js +5 -133
- package/dist/template/list.js +1 -46
- package/dist/template/preview.js +7 -318
- package/dist/template/proc.js +1 -43
- package/dist/template/project.js +6 -161
- package/dist/template/publish.js +5 -185
- package/dist/template/render-client.js +2 -79
- package/dist/template/upgrade.js +4 -123
- package/dist/text.js +1 -15
- package/package.json +2 -35
- package/skills/doc-parse/scripts/extract_via_render.py +32 -32
- package/skills/export-jianying/scripts/gen_jianying_draft.py +188 -188
- package/skills/gen-script/SKILL.md +23 -1
- package/skills/gen-script/scripts/gen_script.py +644 -551
- package/skills/gen-script/skill.json +12 -0
- package/skills/gen-script/version.json +1 -1
- package/skills/prepare-video-assets/scripts/prepare_video_assets.py +21 -21
- package/skills/render-video/scripts/_chrome_vendor.py +17 -17
- package/skills/render-video/scripts/_digital_human_segments.py +34 -34
- package/skills/render-video/scripts/_video_probe.py +33 -33
- package/skills/render-video/scripts/_vod_polling.py +13 -13
- package/skills/render-video/scripts/remote_renderer_client.py +42 -42
- package/skills/render-video/scripts/render_video.py +639 -639
- package/skills/render-video/scripts/required_props.py +37 -37
- package/skills/render-video/scripts/upload_video.py +35 -35
- package/skills/render-video/version.json +1 -1
- package/skills/template-registry/SKILL.md +16 -0
- package/skills/template-registry/scripts/countdown_spec.py +92 -92
- package/skills/template-registry/scripts/doc_extract.py +40 -40
- package/skills/template-registry/scripts/list_templates.py +303 -191
- package/skills/template-registry/scripts/log_diagnostics.py +1 -1
- package/skills/template-registry/scripts/match_template.py +87 -87
- package/skills/template-registry/scripts/payload_hydrator.py +89 -89
- package/skills/template-registry/scripts/registry_loader.py +159 -159
- package/skills/template-registry/scripts/render_job_client.py +75 -75
- package/skills/template-registry/scripts/showcase_loader.py +44 -44
- package/skills/template-registry/skill.json +4 -1
- package/skills/template-registry/version.json +1 -1
- package/skills/template-registry/video_dsl/runtime/__init__.py +8 -8
- package/skills/template-registry/video_dsl/runtime/dsl_validator.py +329 -329
- package/skills/template-registry/video_dsl/runtime/narration_budget.py +36 -36
- package/skills/template-registry/video_dsl/runtime/payload_contract.py +7 -7
- package/skills/template-registry/video_dsl/runtime/prompt_enhancer.py +98 -98
- package/skills/template-registry/video_dsl/runtime/timeline_compiler.py +127 -127
- package/skills/template-registry/video_dsl/schema/video-dsl-v1alpha1.json +14 -1
- package/skills/video-parser/scripts/analyze_video.py +173 -173
- package/skills/video-parser/scripts/deconstruct_video.py +91 -91
- package/skills/video-parser/scripts/parse_via_render.py +21 -21
- package/skills/web-screenshot/scripts/_media_screenshot/__init__.py +4 -4
- package/skills/web-screenshot/scripts/_media_screenshot/bootstrap.py +7 -7
- package/skills/web-screenshot/scripts/_media_screenshot/browser.py +4 -4
- package/skills/web-screenshot/scripts/_media_screenshot/cli_args.py +4 -4
- package/skills/web-screenshot/scripts/_media_screenshot/js_loader.py +2 -2
- package/skills/web-screenshot/scripts/_media_screenshot/overlay.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/reader.py +40 -40
- package/skills/web-screenshot/scripts/_media_screenshot/recording.py +11 -11
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/__init__.py +8 -8
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/arrow.py +2 -2
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/caption.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/click.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/code_lines.py +5 -5
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/focus.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/highlight.py +3 -3
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/hover.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/redact.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/scroll.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/sequence.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/title_card.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/type.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/wait.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/zoom.py +2 -2
- package/skills/web-screenshot/scripts/_media_screenshot/screenshot.py +15 -15
- package/skills/web-screenshot/scripts/_media_screenshot/storyboard.py +2 -2
- package/skills/web-screenshot/scripts/_media_screenshot/template.py +11 -11
- package/skills/web-screenshot/scripts/_media_screenshot/trim.py +10 -10
- package/skills/web-screenshot/scripts/_media_screenshot/urlguard.py +22 -22
- package/skills/web-screenshot/scripts/_media_upload.py +33 -33
- package/skills/web-screenshot/scripts/read_page.py +15 -15
- package/skills/web-screenshot/scripts/record.py +26 -26
- package/skills/web-screenshot/scripts/screenshot.py +5 -5
- package/dist/argv.d.ts +0 -15
- package/dist/auth/auth-lock.d.ts +0 -26
- package/dist/auth/auto-login.d.ts +0 -20
- package/dist/auth/commands.d.ts +0 -8
- package/dist/auth/credential-store.d.ts +0 -60
- package/dist/auth/device-flow-runner.d.ts +0 -58
- package/dist/auth/device-flow.d.ts +0 -52
- package/dist/auth/ensure.d.ts +0 -55
- package/dist/auth/environment.d.ts +0 -38
- package/dist/auth/pending-store.d.ts +0 -33
- package/dist/auth/resolve.d.ts +0 -30
- package/dist/billing.d.ts +0 -44
- package/dist/capabilities.d.ts +0 -63
- package/dist/cli.d.ts +0 -13
- package/dist/diagnostics.d.ts +0 -24
- package/dist/doctor.d.ts +0 -22
- package/dist/errors.d.ts +0 -29
- package/dist/exec.d.ts +0 -18
- package/dist/handlers/gen-digital-human.d.ts +0 -17
- package/dist/handlers/gen-image.d.ts +0 -20
- package/dist/handlers/gen-post.d.ts +0 -22
- package/dist/handlers/gen-video.d.ts +0 -19
- package/dist/handlers/gen-voice.d.ts +0 -26
- package/dist/handlers/index.d.ts +0 -20
- package/dist/handlers/shared.d.ts +0 -26
- package/dist/handlers/template-init.d.ts +0 -10
- package/dist/http.d.ts +0 -72
- package/dist/index.d.ts +0 -9
- package/dist/install.d.ts +0 -71
- package/dist/progress.d.ts +0 -23
- package/dist/project/commands.d.ts +0 -19
- package/dist/project/host.d.ts +0 -91
- package/dist/project/resolve.d.ts +0 -43
- package/dist/project/store.d.ts +0 -31
- package/dist/project/take.d.ts +0 -50
- package/dist/project/trace.d.ts +0 -98
- package/dist/registry.d.ts +0 -30
- package/dist/runner.d.ts +0 -39
- package/dist/skill-schema.d.ts +0 -138
- package/dist/template/args.d.ts +0 -25
- package/dist/template/check.d.ts +0 -23
- package/dist/template/commands.d.ts +0 -25
- package/dist/template/constants.d.ts +0 -39
- package/dist/template/init.d.ts +0 -28
- package/dist/template/list.d.ts +0 -23
- package/dist/template/preview.d.ts +0 -60
- package/dist/template/proc.d.ts +0 -26
- package/dist/template/project.d.ts +0 -47
- package/dist/template/publish.d.ts +0 -43
- package/dist/template/render-client.d.ts +0 -39
- package/dist/template/upgrade.d.ts +0 -44
- package/dist/text.d.ts +0 -8
package/dist/handlers/shared.js
CHANGED
|
@@ -1,66 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Shared helpers for TS skill handlers.
|
|
3
|
-
*
|
|
4
|
-
* These were previously copy-pasted across gen-image / gen-video /
|
|
5
|
-
* gen-digital-human / gen-voice. Centralizing them keeps argument coercion and
|
|
6
|
-
* image-input resolution identical across every atomic generator.
|
|
7
|
-
*
|
|
8
|
-
* Lives under handlers/ (not src/ root) so the compiled `dist/handlers/shared.js`
|
|
9
|
-
* travels with the rest of the handler bundle when ab-agent copies `dist/`.
|
|
10
|
-
*/
|
|
11
|
-
import { readFileSync, existsSync, statSync } from 'node:fs';
|
|
12
|
-
import path from 'node:path';
|
|
13
|
-
import { SkillError } from '../http.js';
|
|
14
|
-
const MIME_BY_EXT = {
|
|
15
|
-
'.png': 'image/png',
|
|
16
|
-
'.jpg': 'image/jpeg',
|
|
17
|
-
'.jpeg': 'image/jpeg',
|
|
18
|
-
'.webp': 'image/webp',
|
|
19
|
-
'.gif': 'image/gif',
|
|
20
|
-
};
|
|
21
|
-
/** Truthy check tolerant of CLI string values (`--flag` → true, `--flag true` → 'true'). */
|
|
22
|
-
export function isTrue(value) {
|
|
23
|
-
return value === true || value === 'true';
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Coerce a flag value into a finite number, or `undefined` when absent/empty.
|
|
27
|
-
* Throws SkillError on a non-numeric value so callers fail fast with a clear msg.
|
|
28
|
-
*/
|
|
29
|
-
export function toNumber(value, name) {
|
|
30
|
-
if (value === undefined || value === null || value === '')
|
|
31
|
-
return undefined;
|
|
32
|
-
const n = Number(value);
|
|
33
|
-
if (!Number.isFinite(n))
|
|
34
|
-
throw new SkillError(`❌ ${name} must be a number, received: ${value}`);
|
|
35
|
-
return n;
|
|
36
|
-
}
|
|
37
|
-
/** Coerce a repeatable flag (string | string[] | undefined) into a string array. */
|
|
38
|
-
export function toStringArray(value) {
|
|
39
|
-
if (value === undefined || value === null)
|
|
40
|
-
return [];
|
|
41
|
-
if (Array.isArray(value))
|
|
42
|
-
return value.map(String);
|
|
43
|
-
return [String(value)];
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Resolve an image reference into a value the backend accepts:
|
|
47
|
-
* - http(s) URLs and data: URIs pass through unchanged
|
|
48
|
-
* - local file paths are read and base64-encoded into a `data:<mime>;base64,…` URI
|
|
49
|
-
* Throws SkillError when a local path does not exist or is not a file.
|
|
50
|
-
*/
|
|
51
|
-
export function resolveImageInput(pathOrUrl) {
|
|
52
|
-
const trimmed = pathOrUrl.trim();
|
|
53
|
-
if (!trimmed)
|
|
54
|
-
return '';
|
|
55
|
-
const lower = trimmed.toLowerCase();
|
|
56
|
-
if (lower.startsWith('http://') || lower.startsWith('https://') || lower.startsWith('data:')) {
|
|
57
|
-
return trimmed;
|
|
58
|
-
}
|
|
59
|
-
if (!existsSync(trimmed) || !statSync(trimmed).isFile()) {
|
|
60
|
-
throw new SkillError(`❌ image path does not exist or is not a file: ${trimmed}`);
|
|
61
|
-
}
|
|
62
|
-
const ext = path.extname(trimmed).toLowerCase();
|
|
63
|
-
const mime = MIME_BY_EXT[ext] ?? 'image/jpeg';
|
|
64
|
-
const b64 = readFileSync(trimmed).toString('base64');
|
|
65
|
-
return `data:${mime};base64,${b64}`;
|
|
66
|
-
}
|
|
1
|
+
var p=Object.defineProperty;var i=(t,r)=>p(t,"name",{value:r,configurable:!0});import{readFileSync as a,existsSync as g,statSync as f}from"node:fs";import u from"node:path";import{SkillError as n}from"../http.js";const c={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".gif":"image/gif"};function x(t){return t===!0||t==="true"}i(x,"isTrue");function S(t,r){if(t==null||t==="")return;const e=Number(t);if(!Number.isFinite(e))throw new n(`❌ ${r} must be a number, received: ${t}`);return e}i(S,"toNumber");function y(t){return t==null?[]:Array.isArray(t)?t.map(String):[String(t)]}i(y,"toStringArray");function j(t){const r=t.trim();if(!r)return"";const e=r.toLowerCase();if(e.startsWith("http://")||e.startsWith("https://")||e.startsWith("data:"))return r;if(!g(r)||!f(r).isFile())throw new n(`❌ image path does not exist or is not a file: ${r}`);const o=u.extname(r).toLowerCase(),s=c[o]??"image/jpeg",m=a(r).toString("base64");return`data:${s};base64,${m}`}i(j,"resolveImageInput");export{x as isTrue,j as resolveImageInput,S as toNumber,y as toStringArray};
|
|
@@ -1,21 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* template-authoring skill → `remixmate template init`.
|
|
3
|
-
*
|
|
4
|
-
* Agent hosts call skills as `remixmate template-authoring --dir X [--force]`;
|
|
5
|
-
* this handler is a thin adapter so both entry points share one implementation.
|
|
6
|
-
* Purely local (auth: none): fetches the starter via npm, no ab-api calls.
|
|
7
|
-
*/
|
|
8
|
-
import { EXIT, SkillError } from '../errors.js';
|
|
9
|
-
import { runInit } from '../template/init.js';
|
|
10
|
-
export async function templateInit(input, _ctx) {
|
|
11
|
-
const dir = typeof input.dir === 'string' ? input.dir.trim() : '';
|
|
12
|
-
if (!dir)
|
|
13
|
-
throw new SkillError('❌ 缺少 --dir:模板工程的目标目录', EXIT.USAGE);
|
|
14
|
-
await runInit({
|
|
15
|
-
dir,
|
|
16
|
-
force: input.force === true || input.force === 'true',
|
|
17
|
-
json: input.json_output === true || input.json === true,
|
|
18
|
-
skipInstall: input.skip_install === true,
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
export default templateInit;
|
|
1
|
+
var i=Object.defineProperty;var e=(r,t)=>i(r,"name",{value:t,configurable:!0});import{EXIT as s,SkillError as f}from"../errors.js";import{runInit as l}from"../template/init.js";async function n(r,t){const o=typeof r.dir=="string"?r.dir.trim():"";if(!o)throw new f("❌ 缺少 --dir:模板工程的目标目录",s.USAGE);await l({dir:o,force:r.force===!0||r.force==="true",json:r.json_output===!0||r.json===!0,skipInstall:r.skip_install===!0})}e(n,"templateInit");var d=n;export{d as default,n as templateInit};
|
package/dist/http.js
CHANGED
|
@@ -1,155 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* Centralizes the auth contract (X-Priv-Token + x-invoke-skill / x-invoke-agent /
|
|
5
|
-
* x-conversation-id), business-code error handling (result.code != 0), and the
|
|
6
|
-
* env var resolution order that every Python skill used to duplicate.
|
|
7
|
-
*
|
|
8
|
-
* Token resolution order (high → low), shared with the CLI auth commands via
|
|
9
|
-
* src/auth/resolve.ts:
|
|
10
|
-
* 1. opts.privateToken — caller override (maps to --token/--priv-token)
|
|
11
|
-
* 2. process.env.PRIV_TOKEN — process env (CI / agent-embedded hosts)
|
|
12
|
-
* 3. Credential_Store[apiBaseUrl] — written by `remixmate login`
|
|
13
|
-
* (none) → throws SkillError — non-interactive failure
|
|
14
|
-
*
|
|
15
|
-
* Base URL resolution:
|
|
16
|
-
* 1. opts.apiBaseUrl — caller override
|
|
17
|
-
* 2. process.env.MM_API_BASE_URL — process env (point at local/staging here)
|
|
18
|
-
* 3. process.env.MM_BACKEND_API_URL — ab-agent's convention (back-compat)
|
|
19
|
-
* 4. https://api.remixmate.ai/api — production default (zero-config)
|
|
20
|
-
*/
|
|
21
|
-
import { traceHeaders, cleanDiagnosticText } from './diagnostics.js';
|
|
22
|
-
import { recordBilling } from './billing.js';
|
|
23
|
-
import { resolvePrivToken, NOT_AUTHENTICATED_HINT } from './auth/resolve.js';
|
|
24
|
-
import { attemptAutoLogin } from './auth/auto-login.js';
|
|
25
|
-
import { EXIT, SkillError } from './errors.js';
|
|
26
|
-
const DEFAULT_API_BASE_URL = 'https://api.remixmate.ai/api';
|
|
27
|
-
// Re-exported so the many `import { SkillError } from '../http.js'` call sites
|
|
28
|
-
// stay valid; the definition moved to errors.ts to break an import cycle with
|
|
29
|
-
// the auth gateway (see errors.ts).
|
|
30
|
-
export { SkillError, EXIT } from './errors.js';
|
|
31
|
-
/**
|
|
32
|
-
* Resolve the ab-api base URL the same way for authenticated and device-flow calls.
|
|
33
|
-
*
|
|
34
|
-
* `MM_BACKEND_API_URL` is honored because several Python skills already fall back
|
|
35
|
-
* to it (registry_loader, render_job_client, _vod_polling). Since runner.ts now
|
|
36
|
-
* injects the resolved base URL into those child processes, leaving it out here
|
|
37
|
-
* would let a prod default silently override an ab-agent-injected backend.
|
|
38
|
-
*/
|
|
39
|
-
export function resolveApiBaseUrl(flag) {
|
|
40
|
-
const fromEnv = (process.env.MM_API_BASE_URL ?? '').trim() || (process.env.MM_BACKEND_API_URL ?? '').trim();
|
|
41
|
-
return ((flag ?? '').trim() || fromEnv || DEFAULT_API_BASE_URL).replace(/\/+$/, '');
|
|
42
|
-
}
|
|
43
|
-
export async function resolveHttpContext(skillName, opts = {}) {
|
|
44
|
-
const apiBaseUrl = resolveApiBaseUrl(opts.apiBaseUrl);
|
|
45
|
-
// An explicit --token flag still wins over the preflight result.
|
|
46
|
-
let resolved = await resolvePrivToken({
|
|
47
|
-
flag: opts.privateToken ?? opts.preflightToken,
|
|
48
|
-
apiBaseUrl,
|
|
49
|
-
});
|
|
50
|
-
// Only when flag/env/store are all empty do we try automatic browser auth.
|
|
51
|
-
// attemptAutoLogin self-gates (cloud env / headless / disabled → returns null
|
|
52
|
-
// immediately), so the env-injected path never reaches it (zero regression).
|
|
53
|
-
if (!resolved) {
|
|
54
|
-
resolved = await attemptAutoLogin(apiBaseUrl);
|
|
55
|
-
}
|
|
56
|
-
if (!resolved) {
|
|
57
|
-
throw new SkillError(NOT_AUTHENTICATED_HINT, EXIT.NOT_AUTHENTICATED);
|
|
58
|
-
}
|
|
59
|
-
return {
|
|
60
|
-
apiBaseUrl,
|
|
61
|
-
privateToken: resolved.privToken,
|
|
62
|
-
skillName,
|
|
63
|
-
agentName: process.env.AGENT_NAME || undefined,
|
|
64
|
-
conversationId: process.env.CONVERSATION_ID || undefined,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
function buildHeaders(ctx, extra) {
|
|
68
|
-
const headers = {
|
|
69
|
-
'Content-Type': 'application/json',
|
|
70
|
-
'X-Priv-Token': ctx.privateToken,
|
|
71
|
-
'x-invoke-skill': ctx.skillName,
|
|
72
|
-
};
|
|
73
|
-
if (ctx.agentName)
|
|
74
|
-
headers['x-invoke-agent'] = ctx.agentName;
|
|
75
|
-
if (ctx.conversationId)
|
|
76
|
-
headers['x-conversation-id'] = ctx.conversationId;
|
|
77
|
-
return { ...headers, ...extra, ...traceHeaders() };
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* POST JSON to ab-api and return the parsed business payload.
|
|
81
|
-
* Throws SkillError on HTTP errors or business code != 0.
|
|
82
|
-
*/
|
|
83
|
-
export async function mmPost(ctx, pathOrUrl, body, opts = {}) {
|
|
84
|
-
const url = pathOrUrl.startsWith('http') ? pathOrUrl : `${ctx.apiBaseUrl}${pathOrUrl}`;
|
|
85
|
-
const controller = new AbortController();
|
|
86
|
-
const timeout = setTimeout(() => controller.abort(), opts.timeoutMs ?? 120_000);
|
|
87
|
-
let resp;
|
|
88
|
-
try {
|
|
89
|
-
resp = await fetch(url, {
|
|
90
|
-
method: 'POST',
|
|
91
|
-
headers: buildHeaders(ctx),
|
|
92
|
-
body: JSON.stringify(body),
|
|
93
|
-
signal: controller.signal,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
catch (err) {
|
|
97
|
-
if (err instanceof Error && err.name === 'AbortError') {
|
|
98
|
-
throw new SkillError(`❌ request timed out: ${url}`, EXIT.BACKEND_UNREACHABLE);
|
|
99
|
-
}
|
|
100
|
-
throw new SkillError(`❌ network error: ${err.message}`, EXIT.BACKEND_UNREACHABLE);
|
|
101
|
-
}
|
|
102
|
-
finally {
|
|
103
|
-
clearTimeout(timeout);
|
|
104
|
-
}
|
|
105
|
-
const text = await resp.text();
|
|
106
|
-
if (!resp.ok) {
|
|
107
|
-
// 401/403 is not a generic API failure — it means the credential is missing,
|
|
108
|
-
// expired or revoked. Surfacing it as such (with exit code 4) is what lets a
|
|
109
|
-
// host offer to re-authorize instead of reporting an opaque backend error.
|
|
110
|
-
if (resp.status === 401 || resp.status === 403) {
|
|
111
|
-
throw new SkillError(`${NOT_AUTHENTICATED_HINT}\n (后端返回 HTTP ${resp.status})`, EXIT.NOT_AUTHENTICATED);
|
|
112
|
-
}
|
|
113
|
-
if (resp.status >= 500) {
|
|
114
|
-
throw new SkillError(`❌ API request failed (HTTP ${resp.status}): [response omitted]`, EXIT.BACKEND_UNREACHABLE);
|
|
115
|
-
}
|
|
116
|
-
throw new SkillError(`❌ API request failed (HTTP ${resp.status}): [response omitted]`);
|
|
117
|
-
}
|
|
118
|
-
let parsed;
|
|
119
|
-
try {
|
|
120
|
-
parsed = JSON.parse(text);
|
|
121
|
-
}
|
|
122
|
-
catch {
|
|
123
|
-
throw new SkillError(`❌ failed to parse response, body is not JSON: [response omitted]`);
|
|
124
|
-
}
|
|
125
|
-
// Before the code check: a charged response is always code=0 today, but a
|
|
126
|
-
// partial-failure envelope that still billed must not lose its billing line.
|
|
127
|
-
recordBilling(parsed.billing);
|
|
128
|
-
if (parsed.code !== 0) {
|
|
129
|
-
// ab-api reports auth failures in the envelope (HTTP 200 + code=401), so the
|
|
130
|
-
// business-code path needs the same 401 → "re-authorize" mapping as above.
|
|
131
|
-
if (parsed.code === 401 || parsed.code === 403) {
|
|
132
|
-
throw new SkillError(`${NOT_AUTHENTICATED_HINT}\n (后端返回 code=${parsed.code}${parsed.msg ? `: ${parsed.msg}` : ''})`, EXIT.NOT_AUTHENTICATED);
|
|
133
|
-
}
|
|
134
|
-
throw new SkillError(`❌ API returned a business error: ${cleanDiagnosticText(parsed.msg ?? 'unknown error')} (code=${parsed.code})`);
|
|
135
|
-
}
|
|
136
|
-
return parsed.data ?? undefined;
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Generic polling helper. Invokes `probe()` immediately, then every
|
|
140
|
-
* `intervalMs`, until it returns a non-null value or `timeoutMs` elapses.
|
|
141
|
-
* Probing first (rather than sleeping first) avoids a wasted initial interval
|
|
142
|
-
* when the backend job is already complete.
|
|
143
|
-
*/
|
|
144
|
-
export async function pollUntil(probe, opts = {}) {
|
|
145
|
-
const intervalMs = opts.intervalMs ?? 5_000;
|
|
146
|
-
const timeoutMs = opts.timeoutMs ?? 120_000;
|
|
147
|
-
const start = Date.now();
|
|
148
|
-
while (Date.now() - start < timeoutMs) {
|
|
149
|
-
const result = await probe();
|
|
150
|
-
if (result !== null)
|
|
151
|
-
return result;
|
|
152
|
-
await new Promise((r) => setTimeout(r, intervalMs));
|
|
153
|
-
}
|
|
154
|
-
throw new SkillError(`❌ polling timed out (${Math.round(timeoutMs / 1000)}s)`);
|
|
155
|
-
}
|
|
1
|
+
var f=Object.defineProperty;var a=(e,t)=>f(e,"name",{value:t,configurable:!0});import{traceHeaders as A,cleanDiagnosticText as w}from"./diagnostics.js";import{recordBilling as E}from"./billing.js";import{resolvePrivToken as N,NOT_AUTHENTICATED_HINT as d}from"./auth/resolve.js";import{attemptAutoLogin as v}from"./auth/auto-login.js";import{EXIT as l,SkillError as n}from"./errors.js";const _="https://api.remixmate.ai/api";import{SkillError as S,EXIT as b}from"./errors.js";function h(e){const t=(process.env.MM_API_BASE_URL??"").trim()||(process.env.MM_BACKEND_API_URL??"").trim();return((e??"").trim()||t||_).replace(/\/+$/,"")}a(h,"resolveApiBaseUrl");async function P(e,t={}){const o=h(t.apiBaseUrl);let i=await N({flag:t.privateToken??t.preflightToken,apiBaseUrl:o});if(i||(i=await v(o)),!i)throw new n(d,l.NOT_AUTHENTICATED);return{apiBaseUrl:o,privateToken:i.privToken,skillName:e,agentName:process.env.AGENT_NAME||void 0,conversationId:process.env.CONVERSATION_ID||void 0}}a(P,"resolveHttpContext");function g(e,t){const o={"Content-Type":"application/json","X-Priv-Token":e.privateToken,"x-invoke-skill":e.skillName};return e.agentName&&(o["x-invoke-agent"]=e.agentName),e.conversationId&&(o["x-conversation-id"]=e.conversationId),{...o,...t,...A()}}a(g,"buildHeaders");async function U(e,t,o,i={}){const m=t.startsWith("http")?t:`${e.apiBaseUrl}${t}`,c=new AbortController,T=setTimeout(()=>c.abort(),i.timeoutMs??12e4);let s;try{s=await fetch(m,{method:"POST",headers:g(e),body:JSON.stringify(o),signal:c.signal})}catch(u){throw u instanceof Error&&u.name==="AbortError"?new n(`❌ request timed out: ${m}`,l.BACKEND_UNREACHABLE):new n(`❌ network error: ${u.message}`,l.BACKEND_UNREACHABLE)}finally{clearTimeout(T)}const p=await s.text();if(!s.ok)throw s.status===401||s.status===403?new n(`${d}
|
|
2
|
+
(后端返回 HTTP ${s.status})`,l.NOT_AUTHENTICATED):s.status>=500?new n(`❌ API request failed (HTTP ${s.status}): [response omitted]`,l.BACKEND_UNREACHABLE):new n(`❌ API request failed (HTTP ${s.status}): [response omitted]`);let r;try{r=JSON.parse(p)}catch{throw new n("❌ failed to parse response, body is not JSON: [response omitted]")}if(E(r.billing),r.code!==0)throw r.code===401||r.code===403?new n(`${d}
|
|
3
|
+
(后端返回 code=${r.code}${r.msg?`: ${r.msg}`:""})`,l.NOT_AUTHENTICATED):new n(`❌ API returned a business error: ${w(r.msg??"unknown error")} (code=${r.code})`);return r.data??void 0}a(U,"mmPost");async function D(e,t={}){const o=t.intervalMs??5e3,i=t.timeoutMs??12e4,m=Date.now();for(;Date.now()-m<i;){const c=await e();if(c!==null)return c;await new Promise(T=>setTimeout(T,o))}throw new n(`❌ polling timed out (${Math.round(i/1e3)}s)`)}a(D,"pollUntil");export{b as EXIT,S as SkillError,U as mmPost,D as pollUntil,h as resolveApiBaseUrl,P as resolveHttpContext};
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* remixmate — public library exports.
|
|
3
|
-
*
|
|
4
|
-
* The CLI entrypoint lives in `cli.ts` (`bin: remixmate`). This file is the
|
|
5
|
-
* library surface for type-sharing consumers; the published npm package
|
|
6
|
-
* exposes it via `main: dist/index.js` / `types: dist/index.d.ts`.
|
|
7
|
-
*/
|
|
8
|
-
export { loadSkills, findSkill, SKILLS_DIR } from './registry.js';
|
|
1
|
+
import{loadSkills as i,findSkill as o,SKILLS_DIR as d}from"./registry.js";export{d as SKILLS_DIR,o as findSkill,i as loadSkills};
|