@babelize/cli 1.0.12 → 1.1.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/LICENSE +200 -4
- package/README.md +44 -15
- package/dist/commands/check.d.ts +22 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +134 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/glossary.d.ts.map +1 -1
- package/dist/commands/glossary.js +2 -1
- package/dist/commands/glossary.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +52 -52
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/tm.d.ts.map +1 -1
- package/dist/commands/tm.js +29 -11
- package/dist/commands/tm.js.map +1 -1
- package/dist/commands/translate.d.ts +24 -0
- package/dist/commands/translate.d.ts.map +1 -0
- package/dist/commands/translate.js +415 -0
- package/dist/commands/translate.js.map +1 -0
- package/dist/index.js +0 -0
- package/dist/local/formatter.d.ts +27 -0
- package/dist/local/formatter.d.ts.map +1 -0
- package/dist/local/formatter.js +69 -0
- package/dist/local/formatter.js.map +1 -0
- package/dist/local/git.d.ts +16 -0
- package/dist/local/git.d.ts.map +1 -0
- package/dist/local/git.js +52 -0
- package/dist/local/git.js.map +1 -0
- package/dist/local/provider.d.ts +41 -0
- package/dist/local/provider.d.ts.map +1 -0
- package/dist/local/provider.js +87 -0
- package/dist/local/provider.js.map +1 -0
- package/dist/local/translate-core.d.ts +188 -0
- package/dist/local/translate-core.d.ts.map +1 -0
- package/dist/local/translate-core.js +401 -0
- package/dist/local/translate-core.js.map +1 -0
- package/dist/local/workspace-copy.d.ts +75 -0
- package/dist/local/workspace-copy.d.ts.map +1 -0
- package/dist/local/workspace-copy.js +263 -0
- package/dist/local/workspace-copy.js.map +1 -0
- package/dist/oauth.d.ts +12 -1
- package/dist/oauth.d.ts.map +1 -1
- package/dist/oauth.js +79 -95
- package/dist/oauth.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +6 -0
- package/dist/program.js.map +1 -1
- package/dist/tui/repl.d.ts.map +1 -1
- package/dist/tui/repl.js +2 -0
- package/dist/tui/repl.js.map +1 -1
- package/dist/utils/zip-upload.d.ts +81 -0
- package/dist/utils/zip-upload.d.ts.map +1 -0
- package/dist/utils/zip-upload.js +277 -0
- package/dist/utils/zip-upload.js.map +1 -0
- package/package.json +6 -2
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
const execFileAsync = promisify(execFile);
|
|
4
|
+
export class GitError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
dirtyFiles;
|
|
7
|
+
constructor(message, code, dirtyFiles = []) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.dirtyFiles = dirtyFiles;
|
|
11
|
+
this.name = 'GitError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async function git(cwd, args) {
|
|
15
|
+
const { stdout } = await execFileAsync('git', args, { cwd, maxBuffer: 64 * 1024 * 1024 });
|
|
16
|
+
return stdout;
|
|
17
|
+
}
|
|
18
|
+
/** Throws GitError('not_a_repo' | 'git_missing') unless `dir` is inside a git work tree. */
|
|
19
|
+
export async function assertGitRepo(dir) {
|
|
20
|
+
try {
|
|
21
|
+
const out = await git(dir, ['rev-parse', '--is-inside-work-tree']);
|
|
22
|
+
if (out.trim() !== 'true')
|
|
23
|
+
throw new Error('not inside a work tree');
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
if (err.code === 'ENOENT') {
|
|
27
|
+
throw new GitError('git is not installed or not on PATH.', 'git_missing');
|
|
28
|
+
}
|
|
29
|
+
throw new GitError('Not a git repository. `babelize translate` writes into your working tree so you can review the result with `git diff` — run it inside a git repo (or `git init` first).', 'not_a_repo');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Uncommitted changes under `dir` (tracked edits and untracked files), as porcelain lines. */
|
|
33
|
+
export async function getUncommittedChanges(dir) {
|
|
34
|
+
const out = await git(dir, ['status', '--porcelain', '--untracked-files=all', '--', '.']);
|
|
35
|
+
return out.split('\n').filter((line) => line.trim().length > 0);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Refuse to run on a dirty tree unless `force`: the result has to be reviewable
|
|
39
|
+
* as its own `git diff`, and a failed review has to be undoable with
|
|
40
|
+
* `git checkout . && git clean -fd` without losing the user's work.
|
|
41
|
+
*/
|
|
42
|
+
export async function assertCleanTree(dir, force) {
|
|
43
|
+
const dirty = await getUncommittedChanges(dir);
|
|
44
|
+
if (dirty.length > 0 && !force) {
|
|
45
|
+
const preview = dirty.slice(0, 10).map((l) => ` ${l}`).join('\n');
|
|
46
|
+
const more = dirty.length > 10 ? `\n … and ${dirty.length - 10} more` : '';
|
|
47
|
+
throw new GitError(`Your working tree has uncommitted changes:\n${preview}${more}\n` +
|
|
48
|
+
'Commit or stash them first so the translation shows up as its own reviewable `git diff`, or re-run with --force.', 'dirty', dirty);
|
|
49
|
+
}
|
|
50
|
+
return dirty;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/local/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGtB;IACA;IAHX,YACE,OAAe,EACN,IAA4C,EAC5C,aAAuB,EAAE;QAElC,KAAK,CAAC,OAAO,CAAC,CAAC;QAHN,SAAI,GAAJ,IAAI,CAAwC;QAC5C,eAAU,GAAV,UAAU,CAAe;QAGlC,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,KAAK,UAAU,GAAG,CAAC,GAAW,EAAE,IAAc;IAC5C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;IAC1F,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,4FAA4F;AAC5F,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAW;IAC7C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC,CAAC;QACnE,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACvE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,IAAI,QAAQ,CAAC,sCAAsC,EAAE,aAAa,CAAC,CAAC;QAC5E,CAAC;QACD,MAAM,IAAI,QAAQ,CAChB,yKAAyK,EACzK,YAAY,CACb,CAAC;IACJ,CAAC;AACH,CAAC;AAED,+FAA+F;AAC/F,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAW;IACrD,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,aAAa,EAAE,uBAAuB,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IAC1F,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAW,EAAE,KAAc;IAC/D,MAAM,KAAK,GAAG,MAAM,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,CAAC,MAAM,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,MAAM,IAAI,QAAQ,CAChB,+CAA+C,OAAO,GAAG,IAAI,IAAI;YAC/D,kHAAkH,EACpH,OAAO,EACP,KAAK,CACN,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type ByokProvider } from '@babelize/types';
|
|
2
|
+
/**
|
|
3
|
+
* Env var holding each provider's key, in auto-detection order: the first one
|
|
4
|
+
* set wins when `--provider` isn't given.
|
|
5
|
+
*/
|
|
6
|
+
export declare const PROVIDER_ENV_VARS: ReadonlyArray<{
|
|
7
|
+
provider: ByokProvider;
|
|
8
|
+
envVar: string;
|
|
9
|
+
}>;
|
|
10
|
+
export interface ResolvedProvider {
|
|
11
|
+
provider: ByokProvider;
|
|
12
|
+
/** Never print this. */
|
|
13
|
+
apiKey: string;
|
|
14
|
+
model: string;
|
|
15
|
+
/** Env var the key came from (safe to print). */
|
|
16
|
+
envVar: string;
|
|
17
|
+
/** True when the provider was picked from the environment, not `--provider`. */
|
|
18
|
+
autoDetected: boolean;
|
|
19
|
+
}
|
|
20
|
+
export type ProviderResolution = {
|
|
21
|
+
ok: true;
|
|
22
|
+
value: ResolvedProvider;
|
|
23
|
+
} | {
|
|
24
|
+
ok: false;
|
|
25
|
+
code: 'unknown_provider' | 'missing_key' | 'no_key';
|
|
26
|
+
message: string;
|
|
27
|
+
};
|
|
28
|
+
export declare function isByokProvider(value: string): value is ByokProvider;
|
|
29
|
+
/** Message shown when no BYOK key is available. Lists env vars, never values. */
|
|
30
|
+
export declare function noKeyMessage(env?: NodeJS.ProcessEnv): string;
|
|
31
|
+
/**
|
|
32
|
+
* Pick the BYOK provider: `--provider` if given (its env var must be set),
|
|
33
|
+
* otherwise the first provider whose env var is set, in PROVIDER_ENV_VARS
|
|
34
|
+
* order. The model is `--model` or the provider's default from
|
|
35
|
+
* @babelize/types.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveProvider(opts: {
|
|
38
|
+
provider?: string;
|
|
39
|
+
model?: string;
|
|
40
|
+
}, env?: NodeJS.ProcessEnv): ProviderResolution;
|
|
41
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/local/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwC,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE1F;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,aAAa,CAAC;IAAE,QAAQ,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAMvF,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,YAAY,CAAC;IACvB,wBAAwB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,GACrC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,kBAAkB,GAAG,aAAa,GAAG,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAExF,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,YAAY,CAEnE;AAMD,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAazE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAC3C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,kBAAkB,CAkDpB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { BYOK_PROVIDERS, PROVIDER_DEFINITIONS } from '@babelize/types';
|
|
2
|
+
/**
|
|
3
|
+
* Env var holding each provider's key, in auto-detection order: the first one
|
|
4
|
+
* set wins when `--provider` isn't given.
|
|
5
|
+
*/
|
|
6
|
+
export const PROVIDER_ENV_VARS = [
|
|
7
|
+
{ provider: 'anthropic', envVar: 'ANTHROPIC_API_KEY' },
|
|
8
|
+
{ provider: 'openai', envVar: 'OPENAI_API_KEY' },
|
|
9
|
+
{ provider: 'gemini', envVar: 'GEMINI_API_KEY' },
|
|
10
|
+
{ provider: 'groq', envVar: 'GROQ_API_KEY' },
|
|
11
|
+
{ provider: 'openrouter', envVar: 'OPENROUTER_API_KEY' },
|
|
12
|
+
];
|
|
13
|
+
export function isByokProvider(value) {
|
|
14
|
+
return BYOK_PROVIDERS.includes(value);
|
|
15
|
+
}
|
|
16
|
+
function envVarFor(provider) {
|
|
17
|
+
return PROVIDER_ENV_VARS.find((p) => p.provider === provider).envVar;
|
|
18
|
+
}
|
|
19
|
+
/** Message shown when no BYOK key is available. Lists env vars, never values. */
|
|
20
|
+
export function noKeyMessage(env = process.env) {
|
|
21
|
+
const lines = [
|
|
22
|
+
'No LLM API key found. `babelize translate` uses your own key for now. Set one of:',
|
|
23
|
+
...PROVIDER_ENV_VARS.map((p) => ` ${p.envVar.padEnd(20)} (${PROVIDER_DEFINITIONS[p.provider].name})`),
|
|
24
|
+
];
|
|
25
|
+
if (env.BABELIZE_API_KEY) {
|
|
26
|
+
lines.push('BABELIZE_API_KEY is set, but Babelize-hosted translation for local runs is not available yet (coming next).');
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
lines.push('Babelize-hosted translation (BABELIZE_API_KEY) is coming next.');
|
|
30
|
+
}
|
|
31
|
+
return lines.join('\n');
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Pick the BYOK provider: `--provider` if given (its env var must be set),
|
|
35
|
+
* otherwise the first provider whose env var is set, in PROVIDER_ENV_VARS
|
|
36
|
+
* order. The model is `--model` or the provider's default from
|
|
37
|
+
* @babelize/types.
|
|
38
|
+
*/
|
|
39
|
+
export function resolveProvider(opts, env = process.env) {
|
|
40
|
+
const model = opts.model?.trim() || undefined;
|
|
41
|
+
if (opts.provider) {
|
|
42
|
+
const requested = opts.provider.trim().toLowerCase();
|
|
43
|
+
if (!isByokProvider(requested)) {
|
|
44
|
+
return {
|
|
45
|
+
ok: false,
|
|
46
|
+
code: 'unknown_provider',
|
|
47
|
+
message: `Unknown provider "${opts.provider}". Use one of: ${PROVIDER_ENV_VARS.map((p) => p.provider).join(', ')}.`,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const envVar = envVarFor(requested);
|
|
51
|
+
const apiKey = env[envVar]?.trim();
|
|
52
|
+
if (!apiKey) {
|
|
53
|
+
return {
|
|
54
|
+
ok: false,
|
|
55
|
+
code: 'missing_key',
|
|
56
|
+
message: `--provider ${requested} needs ${envVar} to be set.`,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
ok: true,
|
|
61
|
+
value: {
|
|
62
|
+
provider: requested,
|
|
63
|
+
apiKey,
|
|
64
|
+
model: model ?? PROVIDER_DEFINITIONS[requested].defaultModel,
|
|
65
|
+
envVar,
|
|
66
|
+
autoDetected: false,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
for (const { provider, envVar } of PROVIDER_ENV_VARS) {
|
|
71
|
+
const apiKey = env[envVar]?.trim();
|
|
72
|
+
if (apiKey) {
|
|
73
|
+
return {
|
|
74
|
+
ok: true,
|
|
75
|
+
value: {
|
|
76
|
+
provider,
|
|
77
|
+
apiKey,
|
|
78
|
+
model: model ?? PROVIDER_DEFINITIONS[provider].defaultModel,
|
|
79
|
+
envVar,
|
|
80
|
+
autoDetected: true,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return { ok: false, code: 'no_key', message: noKeyMessage(env) };
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/local/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAqB,MAAM,iBAAiB,CAAC;AAE1F;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA8D;IAC1F,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,mBAAmB,EAAE;IACtD,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE;IAChD,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE;IAChD,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE;IAC5C,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,oBAAoB,EAAE;CACzD,CAAC;AAiBF,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,OAAQ,cAAoC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,SAAS,CAAC,QAAsB;IACvC,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAE,CAAC,MAAM,CAAC;AACxE,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,YAAY,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC/D,MAAM,KAAK,GAAG;QACZ,mFAAmF;QACnF,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,oBAAoB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC;KACvG,CAAC;IACF,IAAI,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CACR,6GAA6G,CAC9G,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAC7B,IAA2C,EAC3C,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IAE9C,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrD,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,qBAAqB,IAAI,CAAC,QAAQ,kBAAkB,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;aACpH,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,aAAa;gBACnB,OAAO,EAAE,cAAc,SAAS,UAAU,MAAM,aAAa;aAC9D,CAAC;QACJ,CAAC;QACD,OAAO;YACL,EAAE,EAAE,IAAI;YACR,KAAK,EAAE;gBACL,QAAQ,EAAE,SAAS;gBACnB,MAAM;gBACN,KAAK,EAAE,KAAK,IAAI,oBAAoB,CAAC,SAAS,CAAC,CAAC,YAAY;gBAC5D,MAAM;gBACN,YAAY,EAAE,KAAK;aACpB;SACF,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;QACrD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;QACnC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,KAAK,EAAE;oBACL,QAAQ;oBACR,MAAM;oBACN,KAAK,EAAE,KAAK,IAAI,oBAAoB,CAAC,QAAQ,CAAC,CAAC,YAAY;oBAC3D,MAAM;oBACN,YAAY,EAAE,IAAI;iBACnB;aACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;AACnE,CAAC"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { type EngineConfigV2, type EngineResultV2, type TranslationFailure, type TranslationProvider } from '@babelize/engine';
|
|
2
|
+
import { type ByokProvider } from '@babelize/types';
|
|
3
|
+
import { type FormatResult } from './formatter.js';
|
|
4
|
+
import { type ApplyIo, type WorkspaceChanges } from './workspace-copy.js';
|
|
5
|
+
/** Lockfile scope for local runs: `.babelize/local/babelize-lock.json` in the project root. */
|
|
6
|
+
export declare const LOCAL_PROJECT_ID = "local";
|
|
7
|
+
export declare const LOCAL_LOCKFILE = ".babelize/local/babelize-lock.json";
|
|
8
|
+
export declare const SUPPORTED_LOCAL_FRAMEWORKS: readonly ["react", "nextjs"];
|
|
9
|
+
export declare const BETA_LOCAL_FRAMEWORKS: readonly ["vue", "static"];
|
|
10
|
+
export interface LocalTranslateOptions {
|
|
11
|
+
projectDir: string;
|
|
12
|
+
sourceLocale: string;
|
|
13
|
+
targetLocales: string[];
|
|
14
|
+
/** Compute and return the diff; write nothing to the project. */
|
|
15
|
+
dryRun: boolean;
|
|
16
|
+
/** Allow running on a dirty git tree. */
|
|
17
|
+
force: boolean;
|
|
18
|
+
/** The user's LLM key. Required unless `deps.translator` is injected. */
|
|
19
|
+
byok?: {
|
|
20
|
+
provider: ByokProvider;
|
|
21
|
+
apiKey: string;
|
|
22
|
+
model?: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Treat `targetLocales` as the complete list: locales translated earlier
|
|
26
|
+
* but not listed are removed. Default false: earlier locales are kept and
|
|
27
|
+
* brought up to date (from the lockfile, so only new strings cost tokens).
|
|
28
|
+
*/
|
|
29
|
+
replace?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface LocalTranslateDeps {
|
|
32
|
+
/** Replaces the BYOK translator (tests, future Babelize-hosted provider). */
|
|
33
|
+
translator?: TranslationProvider;
|
|
34
|
+
/** Engine entry point; injectable for tests. */
|
|
35
|
+
runEngine?: (config: EngineConfigV2) => Promise<EngineResultV2>;
|
|
36
|
+
/** Engine progress; `status` is running/success/warning/error. */
|
|
37
|
+
onProgress?: (message: string, phase?: string, status?: string) => void;
|
|
38
|
+
/** Called once the framework is known, before any LLM call. */
|
|
39
|
+
onFramework?: (framework: string, status: FrameworkStatus) => void;
|
|
40
|
+
/** Parent dir for the temp copy (defaults to the OS temp dir). */
|
|
41
|
+
tmpRoot?: string;
|
|
42
|
+
/** File operations for applying changes; injectable to simulate disk failures. */
|
|
43
|
+
applyIo?: ApplyIo;
|
|
44
|
+
}
|
|
45
|
+
export type FrameworkStatus = 'supported' | 'beta';
|
|
46
|
+
export type LocalTranslateErrorCode = 'not_a_repo' | 'git_missing' | 'dirty' | 'invalid_locale' | 'no_translator' | 'unsupported_framework' | 'translator_unreachable' | 'engine_failed' | 'incomplete_translation'
|
|
47
|
+
/** Writing to the project failed; see `changedFiles` for what is left changed. */
|
|
48
|
+
| 'apply_failed'
|
|
49
|
+
/** Project files changed while the run was in progress; nothing was applied. */
|
|
50
|
+
| 'project_changed';
|
|
51
|
+
export declare class LocalTranslateError extends Error {
|
|
52
|
+
readonly code: LocalTranslateErrorCode;
|
|
53
|
+
/** Files left changed in the project (only for a failed, un-rolled-back apply). */
|
|
54
|
+
readonly changedFiles: string[];
|
|
55
|
+
constructor(message: string, code: LocalTranslateErrorCode,
|
|
56
|
+
/** Files left changed in the project (only for a failed, un-rolled-back apply). */
|
|
57
|
+
changedFiles?: string[]);
|
|
58
|
+
}
|
|
59
|
+
/** Per-locale outcome. `missing` and `sameAsSource` are what a reviewer should look at. */
|
|
60
|
+
export interface LocaleReport {
|
|
61
|
+
locale: string;
|
|
62
|
+
/** Keys in the source locale. */
|
|
63
|
+
total: number;
|
|
64
|
+
/** Keys with a value (including values identical to the source, see `sameAsSource`). */
|
|
65
|
+
translated: number;
|
|
66
|
+
/** Keys with no value in this locale (the app will show the fallback). */
|
|
67
|
+
missing: string[];
|
|
68
|
+
/** Keys the engine could not translate this run, with the reason (subset of `missing`). */
|
|
69
|
+
failed: Array<{
|
|
70
|
+
key: string;
|
|
71
|
+
reason: string;
|
|
72
|
+
message?: string;
|
|
73
|
+
retryable: boolean;
|
|
74
|
+
}>;
|
|
75
|
+
/** Keys translated with QA warnings from the engine (glossary, length, …). */
|
|
76
|
+
qa: Array<{
|
|
77
|
+
key: string;
|
|
78
|
+
warnings: string[];
|
|
79
|
+
}>;
|
|
80
|
+
/**
|
|
81
|
+
* Keys whose value is identical to the source text. The engine already
|
|
82
|
+
* rejects untranslated output, so this is only a review hint (brand names,
|
|
83
|
+
* "OK", or a cached value from before that check existed).
|
|
84
|
+
*/
|
|
85
|
+
sameAsSource: string[];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Everything a run produced. Structured so a per-key QA report (#237) can be
|
|
89
|
+
* rendered from it without re-running anything.
|
|
90
|
+
*/
|
|
91
|
+
export interface LocalTranslateReport {
|
|
92
|
+
framework: string;
|
|
93
|
+
frameworkStatus: FrameworkStatus;
|
|
94
|
+
provider?: {
|
|
95
|
+
provider: ByokProvider;
|
|
96
|
+
name: string;
|
|
97
|
+
model: string;
|
|
98
|
+
};
|
|
99
|
+
sourceLocale: string;
|
|
100
|
+
/** Locales translated in this run: `--to` plus earlier locales (unless replace). */
|
|
101
|
+
targetLocales: string[];
|
|
102
|
+
/** Earlier locales that were kept and updated although not in `--to`. */
|
|
103
|
+
keptLocales: string[];
|
|
104
|
+
/** Earlier locales removed by `--replace` (files and lockfile entries). */
|
|
105
|
+
droppedLocales: string[];
|
|
106
|
+
/**
|
|
107
|
+
* Source keys with no t() reference found by a heuristic scan. Advisory
|
|
108
|
+
* only: they are still translated, kept and written like any other key.
|
|
109
|
+
*/
|
|
110
|
+
unusedKeys: string[];
|
|
111
|
+
/** Strings extracted (and translated) but not wired into the code. */
|
|
112
|
+
notInjected: Array<{
|
|
113
|
+
file: string;
|
|
114
|
+
key: string;
|
|
115
|
+
text: string;
|
|
116
|
+
reason: string;
|
|
117
|
+
}>;
|
|
118
|
+
/** Files whose non-literal t() keys made every key count as used. */
|
|
119
|
+
dynamicKeyFiles: string[];
|
|
120
|
+
dryRun: boolean;
|
|
121
|
+
/** True when changes were written to the project. */
|
|
122
|
+
applied: boolean;
|
|
123
|
+
changes: WorkspaceChanges;
|
|
124
|
+
/** Unified diff of `changes` (always computed for --dry-run). */
|
|
125
|
+
diff?: string;
|
|
126
|
+
stats: {
|
|
127
|
+
filesScanned: number;
|
|
128
|
+
stringsExtracted: number;
|
|
129
|
+
keysExtracted: number;
|
|
130
|
+
injectionsApplied: number;
|
|
131
|
+
keysFromLockfile: number;
|
|
132
|
+
keysSentToTranslator: number;
|
|
133
|
+
/** (key, locale) translations produced by the translator this run (billable). */
|
|
134
|
+
translatedThisRun?: number;
|
|
135
|
+
};
|
|
136
|
+
locales: LocaleReport[];
|
|
137
|
+
/** Every key that failed, across locales. Non-empty means the run is partial. */
|
|
138
|
+
translationFailures: TranslationFailure[];
|
|
139
|
+
warnings: Array<{
|
|
140
|
+
type: string;
|
|
141
|
+
file: string;
|
|
142
|
+
line?: number;
|
|
143
|
+
message: string;
|
|
144
|
+
}>;
|
|
145
|
+
/** Finalization notes (dependencies added, config created, …). */
|
|
146
|
+
notes: string[];
|
|
147
|
+
/** The project's prettier/biome run on changed files, if it has one. */
|
|
148
|
+
formatter?: FormatResult;
|
|
149
|
+
/** Warnings/errors the engine logged while running. */
|
|
150
|
+
engineLog: Array<{
|
|
151
|
+
level: 'warn' | 'error';
|
|
152
|
+
message: string;
|
|
153
|
+
}>;
|
|
154
|
+
lockfile: string;
|
|
155
|
+
/**
|
|
156
|
+
* True when the lockfile is gitignored (`babelize init` adds `.babelize/`):
|
|
157
|
+
* it still works locally, but teammates and CI won't get it.
|
|
158
|
+
*/
|
|
159
|
+
lockfileIgnored: boolean;
|
|
160
|
+
/** Per-key engine metadata (confidence, TM/lockfile origin) by locale. */
|
|
161
|
+
metadata: Record<string, Record<string, unknown>>;
|
|
162
|
+
/** source key → source text, and locale → key → translated text. */
|
|
163
|
+
results: {
|
|
164
|
+
source: Record<string, string>;
|
|
165
|
+
targets: Record<string, Record<string, string>>;
|
|
166
|
+
};
|
|
167
|
+
durationMs: number;
|
|
168
|
+
}
|
|
169
|
+
/** Normalise `--to fr,de , ja` into a deduped list without the source locale. */
|
|
170
|
+
export declare function parseLocales(raw: string | string[] | undefined, sourceLocale: string): string[];
|
|
171
|
+
export declare function validateLocales(sourceLocale: string, targetLocales: string[]): void;
|
|
172
|
+
/**
|
|
173
|
+
* Engine log lines that are wrong or redundant for a local run: the
|
|
174
|
+
* TRANSLATOR_URL check doesn't know about BYOK/injected providers, and the
|
|
175
|
+
* "run your install" hint is already a finalization note in the summary.
|
|
176
|
+
*/
|
|
177
|
+
/** `msg` as one sentence: trailing dots/spaces trimmed, exactly one period added. */
|
|
178
|
+
export declare function sentence(msg: string): string;
|
|
179
|
+
export declare function isEngineLogNoise(message: string): boolean;
|
|
180
|
+
export declare function buildLocaleReports(targetLocales: string[], source: Record<string, string>, targets: Record<string, Record<string, string>>, failures?: TranslationFailure[], metadata?: Record<string, Record<string, unknown>>): LocaleReport[];
|
|
181
|
+
/**
|
|
182
|
+
* Run the Babelize engine on a temp copy of `projectDir` and, unless
|
|
183
|
+
* `dryRun`, apply the result back to the working tree. The project is never
|
|
184
|
+
* touched until the engine has finished successfully and every target locale
|
|
185
|
+
* has translations.
|
|
186
|
+
*/
|
|
187
|
+
export declare function runLocalTranslate(opts: LocalTranslateOptions, deps?: LocalTranslateDeps): Promise<LocalTranslateReport>;
|
|
188
|
+
//# sourceMappingURL=translate-core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translate-core.d.ts","sourceRoot":"","sources":["../../src/local/translate-core.ts"],"names":[],"mappings":"AAIA,OAAO,EAML,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE1E,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EASL,KAAK,OAAO,EACZ,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAC;AAI7B,+FAA+F;AAC/F,eAAO,MAAM,gBAAgB,UAAU,CAAC;AACxC,eAAO,MAAM,cAAc,uCAAqD,CAAC;AAEjF,eAAO,MAAM,0BAA0B,8BAA+B,CAAC;AACvE,eAAO,MAAM,qBAAqB,4BAA6B,CAAC;AAEhE,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,iEAAiE;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB,yCAAyC;IACzC,KAAK,EAAE,OAAO,CAAC;IACf,yEAAyE;IACzE,IAAI,CAAC,EAAE;QAAE,QAAQ,EAAE,YAAY,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,gDAAgD;IAChD,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAChE,kEAAkE;IAClE,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,+DAA+D;IAC/D,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IACnE,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,MAAM,CAAC;AAEnD,MAAM,MAAM,uBAAuB,GAC/B,YAAY,GACZ,aAAa,GACb,OAAO,GACP,gBAAgB,GAChB,eAAe,GACf,uBAAuB,GACvB,wBAAwB,GACxB,eAAe,GACf,wBAAwB;AAC1B,kFAAkF;GAChF,cAAc;AAChB,gFAAgF;GAC9E,iBAAiB,CAAC;AAEtB,qBAAa,mBAAoB,SAAQ,KAAK;IAG1C,QAAQ,CAAC,IAAI,EAAE,uBAAuB;IACtC,mFAAmF;IACnF,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE;gBAH/B,OAAO,EAAE,MAAM,EACN,IAAI,EAAE,uBAAuB;IACtC,mFAAmF;IAC1E,YAAY,GAAE,MAAM,EAAO;CAKvC;AAED,2FAA2F;AAC3F,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2FAA2F;IAC3F,MAAM,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACrF,8EAA8E;IAC9E,EAAE,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC/C;;;;OAIG;IACH,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,EAAE;QAAE,QAAQ,EAAE,YAAY,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,yEAAyE;IACzE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,2EAA2E;IAC3E,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB;;;OAGG;IACH,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,sEAAsE;IACtE,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChF,qEAAqE;IACrE,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,qDAAqD;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,gBAAgB,EAAE,MAAM,CAAC;QACzB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,iFAAiF;QACjF,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,iFAAiF;IACjF,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;IAC1C,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChF,kEAAkE;IAClE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,wEAAwE;IACxE,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,uDAAuD;IACvD,SAAS,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,oEAAoE;IACpE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;KAAE,CAAC;IAC7F,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CAM/F;AAED,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI,CAWnF;AAwCD;;;;GAIG;AACH,qFAAqF;AACrF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG5C;AAWD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;AA2DD,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,MAAM,EAAE,EACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC/C,QAAQ,GAAE,kBAAkB,EAAO,EACnC,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM,GACrD,YAAY,EAAE,CA2BhB;AAaD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,qBAAqB,EAC3B,IAAI,GAAE,kBAAuB,GAC5B,OAAO,CAAC,oBAAoB,CAAC,CAqO/B"}
|