@baryonlabs/cli 0.3.6 → 0.3.7
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/bin/baryon.js +18 -7
- package/package.json +1 -1
- package/src/api.js +25 -0
- package/src/commands.js +107 -99
- package/src/i18n.js +359 -0
- package/src/pi.js +2 -5
package/bin/baryon.js
CHANGED
|
@@ -16,10 +16,11 @@ import {
|
|
|
16
16
|
import { loadConfig, piProviderConfigured, hasConfig, prunePiPackages } from "../src/config.js";
|
|
17
17
|
import { DEPRECATED_EXTENSIONS } from "../src/constants.js";
|
|
18
18
|
import { runPi, resolvePiEntry } from "../src/pi.js";
|
|
19
|
-
import { checkLatest } from "../src/api.js";
|
|
19
|
+
import { checkLatest, whoami } from "../src/api.js";
|
|
20
20
|
import { spawnSync } from "node:child_process";
|
|
21
21
|
import { createRequire } from "node:module";
|
|
22
22
|
import { c, err, log, sym } from "../src/ui.js";
|
|
23
|
+
import { t } from "../src/i18n.js";
|
|
23
24
|
|
|
24
25
|
/** Best-effort: warn loudly when a newer CLI exists. The gateway enforces the
|
|
25
26
|
* minimum version (426), so cloud use is blocked until you update; this is the
|
|
@@ -28,8 +29,8 @@ async function warnIfOutdated() {
|
|
|
28
29
|
const r = await checkLatest();
|
|
29
30
|
if (r?.outdated) {
|
|
30
31
|
log(
|
|
31
|
-
`\n ${sym.warn} ${c.yellow(
|
|
32
|
-
` ${c.dim("
|
|
32
|
+
`\n ${sym.warn} ${c.yellow(t("bin.outdated", { current: r.current, latest: r.latest }))}\n` +
|
|
33
|
+
` ${c.dim(t("bin.outdatedSub"))} ${c.lime("baryon update")} ${c.dim(t("bin.outdatedRun") + "\n")}`,
|
|
33
34
|
);
|
|
34
35
|
}
|
|
35
36
|
}
|
|
@@ -44,7 +45,7 @@ function showVersion() {
|
|
|
44
45
|
const r = spawnSync(process.execPath, [entry, "--version"], {
|
|
45
46
|
encoding: "utf8",
|
|
46
47
|
});
|
|
47
|
-
if (r.stdout) log(
|
|
48
|
+
if (r.stdout) log(t("bin.piVersion", { version: c.dim(r.stdout.trim()) }));
|
|
48
49
|
}
|
|
49
50
|
return 0;
|
|
50
51
|
}
|
|
@@ -97,12 +98,12 @@ async function main() {
|
|
|
97
98
|
if (unconfigured && !userTargets) {
|
|
98
99
|
if (process.stdin.isTTY) {
|
|
99
100
|
log(
|
|
100
|
-
` ${sym.warn} ${c.yellow("
|
|
101
|
+
` ${sym.warn} ${c.yellow(t("bin.unconfiguredTTY"))} ${c.lime("baryon setup")} ${c.dim(t("bin.unconfiguredTTYRun"))}\n`,
|
|
101
102
|
);
|
|
102
103
|
return setup([]);
|
|
103
104
|
}
|
|
104
105
|
log(
|
|
105
|
-
` ${sym.warn} ${c.yellow("
|
|
106
|
+
` ${sym.warn} ${c.yellow(t("bin.unconfigured"))} ${c.lime("baryon setup")} ${c.dim(t("bin.unconfiguredRun"))}`,
|
|
106
107
|
);
|
|
107
108
|
return 1;
|
|
108
109
|
}
|
|
@@ -112,11 +113,21 @@ async function main() {
|
|
|
112
113
|
try {
|
|
113
114
|
const pruned = prunePiPackages(DEPRECATED_EXTENSIONS);
|
|
114
115
|
if (pruned.length)
|
|
115
|
-
log(` ${sym.info} ${c.dim(
|
|
116
|
+
log(` ${sym.info} ${c.dim(t("bin.prunedConflicts", { names: pruned.join(", ") }))}`);
|
|
116
117
|
} catch {
|
|
117
118
|
/* best-effort */
|
|
118
119
|
}
|
|
119
120
|
const cfg = loadConfig();
|
|
121
|
+
// Show which room (project/분반 · seat) this key is in — best-effort.
|
|
122
|
+
try {
|
|
123
|
+
const who = await whoami(cfg.baseUrl, cfg.apiKey);
|
|
124
|
+
if (who?.project) {
|
|
125
|
+
const key = who.project_status === "active" ? "bin.room" : "bin.roomInactive";
|
|
126
|
+
log(` ${c.teal(t(key, { project: who.project, seat: who.seat || "—" }))}`);
|
|
127
|
+
}
|
|
128
|
+
} catch {
|
|
129
|
+
/* best-effort */
|
|
130
|
+
}
|
|
120
131
|
return runPi(argv, cfg);
|
|
121
132
|
}
|
|
122
133
|
}
|
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -99,4 +99,29 @@ export async function ping(baseUrl, apiKey, { timeoutMs = 6000 } = {}) {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Resolve the connected project (분반) + seat for the configured key, so the CLI
|
|
104
|
+
* can show which "room" it's in. Best-effort: null on any failure / offline.
|
|
105
|
+
*/
|
|
106
|
+
export async function whoami(baseUrl, apiKey, { timeoutMs = 4000 } = {}) {
|
|
107
|
+
if (!apiKey) return null;
|
|
108
|
+
const ctrl = new AbortController();
|
|
109
|
+
const timer = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
110
|
+
try {
|
|
111
|
+
const res = await fetch(joinUrl(baseUrl, "/whoami"), {
|
|
112
|
+
headers: {
|
|
113
|
+
Authorization: `Bearer ${apiKey}`,
|
|
114
|
+
"X-Baryon-Client": `baryon-cli/${CLIENT_VERSION}`,
|
|
115
|
+
},
|
|
116
|
+
signal: ctrl.signal,
|
|
117
|
+
});
|
|
118
|
+
if (!res.ok) return null;
|
|
119
|
+
return await res.json();
|
|
120
|
+
} catch {
|
|
121
|
+
return null;
|
|
122
|
+
} finally {
|
|
123
|
+
clearTimeout(timer);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
102
127
|
export { DEFAULT_MODELS };
|
package/src/commands.js
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
} from "./constants.js";
|
|
34
34
|
import { runPi, resolvePiEntry } from "./pi.js";
|
|
35
35
|
import { banner, c, info, log, ok, err, warn, prompt, promptHidden, sym } from "./ui.js";
|
|
36
|
+
import { t, normalizeLocale, getLocale } from "./i18n.js";
|
|
36
37
|
|
|
37
38
|
/** Parse `--flag value` / `--flag=value` pairs out of argv. */
|
|
38
39
|
function parseFlags(args) {
|
|
@@ -53,7 +54,7 @@ function parseFlags(args) {
|
|
|
53
54
|
export async function setup(args) {
|
|
54
55
|
const flags = parseFlags(args);
|
|
55
56
|
banner();
|
|
56
|
-
log(c.bold("
|
|
57
|
+
log(c.bold(` ${t("setup.title")}\n`));
|
|
57
58
|
|
|
58
59
|
const existing = loadConfig();
|
|
59
60
|
const baseUrl = flags["base-url"] || existing.baseUrl || DEFAULT_BASE_URL;
|
|
@@ -61,103 +62,107 @@ export async function setup(args) {
|
|
|
61
62
|
let apiKey = flags.key || flags["api-key"] || process.env.BARYON_API_KEY || "";
|
|
62
63
|
if (!apiKey) {
|
|
63
64
|
// Tell the user where keys come from before asking for one.
|
|
64
|
-
log(` ${sym.info}
|
|
65
|
-
log(` ${c.dim(
|
|
66
|
-
apiKey = await promptHidden(` ${sym.info}
|
|
65
|
+
log(` ${sym.info} ${t("setup.keyHint", { url: c.lime(KEYS_URL) })}`);
|
|
66
|
+
log(` ${c.dim(t("setup.keyHintSub", { prefix: KEY_PREFIX }))}\n`);
|
|
67
|
+
apiKey = await promptHidden(` ${sym.info} ${t("setup.keyPrompt")}`);
|
|
67
68
|
}
|
|
68
69
|
if (!apiKey) {
|
|
69
|
-
warn("
|
|
70
|
+
warn(t("setup.noKey"));
|
|
70
71
|
} else if (!apiKey.startsWith(KEY_PREFIX)) {
|
|
71
|
-
warn(
|
|
72
|
+
warn(t("setup.badKeyFormat", { prefix: KEY_PREFIX }));
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
saveConfig({ apiKey, baseUrl });
|
|
75
|
-
ok(
|
|
76
|
+
ok(t("setup.configSaved", { file: c.dim(BARYON_CONFIG) }));
|
|
76
77
|
|
|
77
78
|
// Try live model discovery; fall back to defaults offline.
|
|
78
79
|
let models = null;
|
|
79
80
|
if (apiKey) {
|
|
80
|
-
info("
|
|
81
|
+
info(t("setup.discovering"));
|
|
81
82
|
models = await discoverModels(baseUrl, apiKey);
|
|
82
83
|
}
|
|
83
84
|
if (models) {
|
|
84
|
-
ok(
|
|
85
|
+
ok(t("setup.modelsFound", {
|
|
86
|
+
count: models.length,
|
|
87
|
+
list: c.lime(models.map((m) => m.id).slice(0, 4).join(", ")),
|
|
88
|
+
more: models.length > 4 ? "…" : "",
|
|
89
|
+
}));
|
|
85
90
|
} else {
|
|
86
91
|
models = DEFAULT_MODELS;
|
|
87
|
-
warn(
|
|
92
|
+
warn(t("setup.modelsFailed", { count: models.length }));
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
saveConfig({ defaultModel: models[0].id });
|
|
91
96
|
const file = syncPiModels({ baseUrl, models });
|
|
92
|
-
ok(
|
|
97
|
+
ok(t("setup.providerConfigured", { provider: c.lime(PROVIDER), file: c.dim(file) }));
|
|
93
98
|
|
|
94
99
|
if (flags["no-extensions"]) {
|
|
95
|
-
info(
|
|
100
|
+
info(t("setup.skipExtensions"));
|
|
96
101
|
} else {
|
|
97
102
|
installDefaults();
|
|
98
103
|
}
|
|
99
104
|
|
|
100
105
|
if (flags["no-skills"]) {
|
|
101
|
-
info(
|
|
106
|
+
info(t("setup.skipSkills"));
|
|
102
107
|
} else {
|
|
103
108
|
installSkills();
|
|
104
109
|
}
|
|
105
110
|
|
|
106
111
|
if (flags["no-browser"]) {
|
|
107
|
-
info(
|
|
112
|
+
info(t("setup.skipBrowser"));
|
|
108
113
|
} else {
|
|
109
114
|
installBrowser();
|
|
110
115
|
}
|
|
111
116
|
|
|
112
|
-
log(`\n ${sym.ok}
|
|
117
|
+
log(`\n ${sym.ok} ${t("setup.done", { cmd: c.lime("baryon") })}\n`);
|
|
113
118
|
return 0;
|
|
114
119
|
}
|
|
115
120
|
|
|
116
121
|
export async function doctor() {
|
|
117
122
|
banner();
|
|
118
|
-
log(c.bold(
|
|
123
|
+
log(c.bold(` ${t("doctor.title")}\n`));
|
|
119
124
|
let problems = 0;
|
|
120
125
|
|
|
121
126
|
// node
|
|
122
127
|
const major = Number(process.versions.node.split(".")[0]);
|
|
123
|
-
if (major >= 22) ok(
|
|
128
|
+
if (major >= 22) ok(t("doctor.node", { version: process.version }));
|
|
124
129
|
else {
|
|
125
|
-
err(
|
|
130
|
+
err(t("doctor.nodeOld", { version: process.version }));
|
|
126
131
|
problems++;
|
|
127
132
|
}
|
|
128
133
|
|
|
129
134
|
// pi installed?
|
|
130
135
|
const entry = resolvePiEntry();
|
|
131
|
-
if (entry) ok(
|
|
136
|
+
if (entry) ok(t("doctor.piInstalled", { pkg: PI_PACKAGE }));
|
|
132
137
|
else {
|
|
133
|
-
err(
|
|
138
|
+
err(t("doctor.piMissing", { pkg: PI_PACKAGE }));
|
|
134
139
|
problems++;
|
|
135
140
|
}
|
|
136
141
|
|
|
137
142
|
// config?
|
|
138
|
-
if (hasConfig()) ok(
|
|
143
|
+
if (hasConfig()) ok(t("doctor.configFound", { file: c.dim(BARYON_CONFIG) }));
|
|
139
144
|
else {
|
|
140
|
-
warn("
|
|
145
|
+
warn(t("doctor.configMissing"));
|
|
141
146
|
problems++;
|
|
142
147
|
}
|
|
143
148
|
|
|
144
149
|
const cfg = loadConfig();
|
|
145
|
-
if (cfg.apiKey) ok(
|
|
146
|
-
else warn("
|
|
150
|
+
if (cfg.apiKey) ok(t("doctor.apiKeySet", { masked: `${cfg.apiKey.slice(0, 4)}${"•".repeat(6)}` }));
|
|
151
|
+
else warn(t("doctor.apiKeyMissing"));
|
|
147
152
|
|
|
148
153
|
// CLI version currency (best-effort; silent offline)
|
|
149
154
|
const ver = await checkLatest();
|
|
150
155
|
if (ver?.outdated) {
|
|
151
|
-
warn(
|
|
156
|
+
warn(t("doctor.cliOutdated", { current: ver.current, latest: ver.latest }));
|
|
152
157
|
problems++;
|
|
153
158
|
} else if (ver) {
|
|
154
|
-
ok(
|
|
159
|
+
ok(t("doctor.cliCurrent", { current: ver.current }));
|
|
155
160
|
}
|
|
156
161
|
|
|
157
162
|
// pi provider registered?
|
|
158
|
-
if (piProviderConfigured()) ok(
|
|
163
|
+
if (piProviderConfigured()) ok(t("doctor.providerRegistered", { provider: c.lime(PROVIDER), file: c.dim(PI_MODELS_JSON) }));
|
|
159
164
|
else {
|
|
160
|
-
warn("
|
|
165
|
+
warn(t("doctor.providerMissing"));
|
|
161
166
|
problems++;
|
|
162
167
|
}
|
|
163
168
|
|
|
@@ -166,26 +171,26 @@ export async function doctor() {
|
|
|
166
171
|
fs.existsSync(path.join(PI_SKILLS_DIR, s.name, "SKILL.md")),
|
|
167
172
|
).length;
|
|
168
173
|
if (haveSkills === DEFAULT_SKILLS.length)
|
|
169
|
-
ok(
|
|
174
|
+
ok(t("doctor.skillsAll", { have: haveSkills, total: DEFAULT_SKILLS.length }));
|
|
170
175
|
else
|
|
171
|
-
info(
|
|
176
|
+
info(t("doctor.skillsSome", { have: haveSkills, total: DEFAULT_SKILLS.length }));
|
|
172
177
|
|
|
173
178
|
// agent-browser (web/ERP automation) — informational
|
|
174
179
|
const ab = spawnSync("agent-browser", ["--version"], { encoding: "utf8" });
|
|
175
|
-
if (ab.status === 0) ok(
|
|
176
|
-
else info(
|
|
180
|
+
if (ab.status === 0) ok(t("doctor.browserInstalled", { version: (ab.stdout || "").trim() || "ok" }));
|
|
181
|
+
else info(t("doctor.browserMissing"));
|
|
177
182
|
|
|
178
183
|
// connectivity
|
|
179
|
-
info(
|
|
184
|
+
info(t("doctor.checkingConn", { url: c.dim(cfg.baseUrl) }));
|
|
180
185
|
const r = await ping(cfg.baseUrl, cfg.apiKey);
|
|
181
|
-
if (r.ok) ok(
|
|
182
|
-
else if (r.status) warn(
|
|
183
|
-
else warn(
|
|
186
|
+
if (r.ok) ok(t("doctor.connOk", { status: r.status }));
|
|
187
|
+
else if (r.status) warn(t("doctor.connStatus", { status: r.status }));
|
|
188
|
+
else warn(t("doctor.connFail", { error: r.error }));
|
|
184
189
|
|
|
185
190
|
log(
|
|
186
191
|
problems === 0
|
|
187
|
-
? `\n ${sym.ok} ${c.teal("
|
|
188
|
-
: `\n ${sym.warn} ${c.yellow(
|
|
192
|
+
? `\n ${sym.ok} ${c.teal(t("doctor.allPass"))}\n`
|
|
193
|
+
: `\n ${sym.warn} ${c.yellow(t("doctor.problems", { count: problems }))}\n`,
|
|
189
194
|
);
|
|
190
195
|
return problems === 0 ? 0 : 1;
|
|
191
196
|
}
|
|
@@ -198,33 +203,35 @@ export async function models(args) {
|
|
|
198
203
|
|
|
199
204
|
export async function configCmd(args) {
|
|
200
205
|
const flags = parseFlags(args);
|
|
201
|
-
if (flags.key || flags["api-key"] || flags["base-url"] || flags.model) {
|
|
206
|
+
if (flags.key || flags["api-key"] || flags["base-url"] || flags.model || flags.lang) {
|
|
202
207
|
const patch = {};
|
|
203
208
|
if (flags.key || flags["api-key"]) patch.apiKey = flags.key || flags["api-key"];
|
|
204
209
|
if (flags["base-url"]) patch.baseUrl = flags["base-url"];
|
|
205
210
|
if (flags.model) patch.defaultModel = flags.model;
|
|
211
|
+
if (flags.lang) patch.lang = normalizeLocale(flags.lang);
|
|
206
212
|
saveConfig(patch);
|
|
207
|
-
ok("config
|
|
213
|
+
ok(t("config.updated"));
|
|
208
214
|
return 0;
|
|
209
215
|
}
|
|
210
216
|
const cfg = loadConfig();
|
|
211
217
|
banner();
|
|
212
|
-
log(c.bold(
|
|
213
|
-
info(
|
|
214
|
-
info(
|
|
215
|
-
info(
|
|
216
|
-
info(
|
|
217
|
-
info(
|
|
218
|
-
info(
|
|
218
|
+
log(c.bold(` ${t("config.title")}\n`));
|
|
219
|
+
info(t("config.baseUrl", { url: c.lime(cfg.baseUrl) }));
|
|
220
|
+
info(t("config.default", { model: c.lime(cfg.defaultModel) }));
|
|
221
|
+
info(t("config.apiKey", { masked: cfg.apiKey ? c.lime(cfg.apiKey.slice(0, 4) + "•".repeat(6)) : c.dim(t("config.apiKeyNone")) }));
|
|
222
|
+
info(t("config.lang", { lang: c.lime(getLocale()) }));
|
|
223
|
+
info(t("config.keysMgmt", { url: c.lime(KEYS_URL) }));
|
|
224
|
+
info(t("config.file", { file: c.dim(BARYON_CONFIG) }));
|
|
225
|
+
info(t("config.piModels", { file: c.dim(PI_MODELS_JSON) }));
|
|
219
226
|
log("");
|
|
220
227
|
return 0;
|
|
221
228
|
}
|
|
222
229
|
|
|
223
230
|
export function keys() {
|
|
224
|
-
log(` ${sym.info}
|
|
231
|
+
log(` ${sym.info} ${t("keys.title")}`);
|
|
225
232
|
log(` ${c.lime(KEYS_URL)}`);
|
|
226
|
-
log(` ${c.dim(
|
|
227
|
-
log(` ${c.dim("
|
|
233
|
+
log(` ${c.dim(t("keys.sub", { prefix: KEY_PREFIX }))}`);
|
|
234
|
+
log(` ${c.dim(t("keys.after"))} ${c.lime("baryon setup")} ${c.dim(t("keys.or"))} ${c.lime("baryon config --key vc_live_…")}`);
|
|
228
235
|
// best-effort open in browser
|
|
229
236
|
const opener =
|
|
230
237
|
process.platform === "darwin"
|
|
@@ -247,14 +254,14 @@ export function keys() {
|
|
|
247
254
|
export function update() {
|
|
248
255
|
return new Promise((resolve) => {
|
|
249
256
|
// 1/2 — CLI + pi core via npm (gets the latest pi binary, e.g. 0.80.x).
|
|
250
|
-
log(` ${sym.info}
|
|
257
|
+
log(` ${sym.info} ${t("update.stage1", { cmd: c.lime(`npm install -g @baryonlabs/cli ${PI_PACKAGE}`) })}\n`);
|
|
251
258
|
const npm = spawn("npm", ["install", "-g", "@baryonlabs/cli", PI_PACKAGE], {
|
|
252
259
|
stdio: "inherit",
|
|
253
260
|
shell: process.platform === "win32",
|
|
254
261
|
});
|
|
255
262
|
|
|
256
263
|
npm.on("error", () => {
|
|
257
|
-
err("
|
|
264
|
+
err(t("update.npmFail"));
|
|
258
265
|
resolve(1);
|
|
259
266
|
});
|
|
260
267
|
|
|
@@ -264,11 +271,11 @@ export function update() {
|
|
|
264
271
|
const entry = resolvePiEntry();
|
|
265
272
|
if (!entry) return resolve(code ?? 0);
|
|
266
273
|
|
|
267
|
-
log(`\n ${sym.info}
|
|
274
|
+
log(`\n ${sym.info} ${t("update.stage2", { cmd: c.lime("pi update") })}\n`);
|
|
268
275
|
const pu = spawn(process.execPath, [entry, "update"], { stdio: "inherit" });
|
|
269
276
|
pu.on("error", () => resolve(code ?? 0));
|
|
270
277
|
pu.on("exit", () => {
|
|
271
|
-
log(`\n ${sym.ok}
|
|
278
|
+
log(`\n ${sym.ok} ${t("update.done", { hint: c.dim(t("update.doneHint")) })}`);
|
|
272
279
|
resolve(code ?? 0);
|
|
273
280
|
});
|
|
274
281
|
});
|
|
@@ -279,7 +286,7 @@ export function installDefaults() {
|
|
|
279
286
|
const entry = resolvePiEntry();
|
|
280
287
|
|
|
281
288
|
if (!entry) {
|
|
282
|
-
warn(
|
|
289
|
+
warn(t("ext.piMissing", { pkg: PI_PACKAGE }));
|
|
283
290
|
return 0;
|
|
284
291
|
}
|
|
285
292
|
|
|
@@ -287,9 +294,9 @@ export function installDefaults() {
|
|
|
287
294
|
// (e.g. pi-search ↔ pi-web-fetch both registering `web_fetch`, which hard-fails
|
|
288
295
|
// every run). Remove them from pi's registry + disk before (re)installing.
|
|
289
296
|
const pruned = prunePiPackages(DEPRECATED_EXTENSIONS);
|
|
290
|
-
if (pruned.length) warn(
|
|
297
|
+
if (pruned.length) warn(t("ext.pruned", { names: pruned.join(", ") }));
|
|
291
298
|
|
|
292
|
-
log(` ${sym.info}
|
|
299
|
+
log(` ${sym.info} ${t("ext.installing", { count: DEFAULT_EXTENSIONS.length })}`);
|
|
293
300
|
let okc = 0;
|
|
294
301
|
|
|
295
302
|
for (const e of DEFAULT_EXTENSIONS) {
|
|
@@ -306,14 +313,14 @@ export function installDefaults() {
|
|
|
306
313
|
}
|
|
307
314
|
|
|
308
315
|
if (status === 0) {
|
|
309
|
-
ok(
|
|
316
|
+
ok(t("ext.itemOk", { name: e.name, note: e.note }));
|
|
310
317
|
okc++;
|
|
311
318
|
} else {
|
|
312
|
-
warn(
|
|
319
|
+
warn(t("ext.itemFail", { name: e.name }));
|
|
313
320
|
}
|
|
314
321
|
}
|
|
315
322
|
|
|
316
|
-
log(` ${sym.ok}
|
|
323
|
+
log(` ${sym.ok} ${t("ext.summary", { ok: okc, total: DEFAULT_EXTENSIONS.length })}`);
|
|
317
324
|
return okc;
|
|
318
325
|
}
|
|
319
326
|
|
|
@@ -327,11 +334,11 @@ export function installSkills() {
|
|
|
327
334
|
let okc = DEFAULT_SKILLS.length - missing.length;
|
|
328
335
|
|
|
329
336
|
if (missing.length === 0) {
|
|
330
|
-
log(` ${sym.ok}
|
|
337
|
+
log(` ${sym.ok} ${t("skills.alreadyAll", { total: DEFAULT_SKILLS.length })}`);
|
|
331
338
|
return DEFAULT_SKILLS.length;
|
|
332
339
|
}
|
|
333
340
|
|
|
334
|
-
log(` ${sym.info}
|
|
341
|
+
log(` ${sym.info} ${t("skills.installing", { count: missing.length })}`);
|
|
335
342
|
fs.mkdirSync(PI_SKILLS_DIR, { recursive: true });
|
|
336
343
|
|
|
337
344
|
// Bundled skills ship inside this package under ../skills/<name>/.
|
|
@@ -340,12 +347,12 @@ export function installSkills() {
|
|
|
340
347
|
const copySkill = (srcDir, s) => {
|
|
341
348
|
const dst = path.join(PI_SKILLS_DIR, s.name);
|
|
342
349
|
if (!fs.existsSync(path.join(srcDir, "SKILL.md"))) {
|
|
343
|
-
warn(
|
|
350
|
+
warn(t("skills.noSkillMd", { name: s.name, dir: srcDir }));
|
|
344
351
|
return false;
|
|
345
352
|
}
|
|
346
353
|
fs.rmSync(dst, { recursive: true, force: true });
|
|
347
354
|
fs.cpSync(srcDir, dst, { recursive: true });
|
|
348
|
-
ok(
|
|
355
|
+
ok(t("skills.itemOk", { name: s.name, note: s.note }));
|
|
349
356
|
return true;
|
|
350
357
|
};
|
|
351
358
|
|
|
@@ -354,7 +361,7 @@ export function installSkills() {
|
|
|
354
361
|
try {
|
|
355
362
|
if (copySkill(path.join(bundledRoot, s.name), s)) okc++;
|
|
356
363
|
} catch (e) {
|
|
357
|
-
warn(
|
|
364
|
+
warn(t("skills.itemFail", { name: s.name, error: e.message }));
|
|
358
365
|
}
|
|
359
366
|
}
|
|
360
367
|
|
|
@@ -376,13 +383,13 @@ export function installSkills() {
|
|
|
376
383
|
}
|
|
377
384
|
|
|
378
385
|
if (!cloned) {
|
|
379
|
-
warn(
|
|
386
|
+
warn(t("skills.cloneFail"));
|
|
380
387
|
} else {
|
|
381
388
|
for (const s of repoSkills) {
|
|
382
389
|
try {
|
|
383
390
|
if (copySkill(path.join(tmp, ...s.subdir.split("/")), s)) okc++;
|
|
384
391
|
} catch (e) {
|
|
385
|
-
warn(
|
|
392
|
+
warn(t("skills.itemFail", { name: s.name, error: e.message }));
|
|
386
393
|
}
|
|
387
394
|
}
|
|
388
395
|
}
|
|
@@ -391,7 +398,7 @@ export function installSkills() {
|
|
|
391
398
|
}
|
|
392
399
|
}
|
|
393
400
|
|
|
394
|
-
log(` ${sym.ok}
|
|
401
|
+
log(` ${sym.ok} ${t("skills.summary", { ok: okc, total: DEFAULT_SKILLS.length, dir: PI_SKILLS_DIR })}`);
|
|
395
402
|
return okc;
|
|
396
403
|
}
|
|
397
404
|
|
|
@@ -403,11 +410,11 @@ export function installBrowser() {
|
|
|
403
410
|
// Already present?
|
|
404
411
|
const probe = spawnSync("agent-browser", ["--version"], { encoding: "utf8" });
|
|
405
412
|
if (probe.status === 0) {
|
|
406
|
-
ok(
|
|
413
|
+
ok(t("browser.installed", { version: (probe.stdout || "").trim() || "ok" }));
|
|
407
414
|
return true;
|
|
408
415
|
}
|
|
409
416
|
|
|
410
|
-
log(` ${sym.info}
|
|
417
|
+
log(` ${sym.info} ${t("browser.installing")}`);
|
|
411
418
|
|
|
412
419
|
let ok1 = false;
|
|
413
420
|
for (let attempt = 1; attempt <= 2 && !ok1; attempt++) {
|
|
@@ -417,14 +424,14 @@ export function installBrowser() {
|
|
|
417
424
|
}
|
|
418
425
|
|
|
419
426
|
if (!ok1) {
|
|
420
|
-
warn("
|
|
427
|
+
warn(t("browser.installFail"));
|
|
421
428
|
return false;
|
|
422
429
|
}
|
|
423
430
|
|
|
424
431
|
// Download the browser engine (Chrome for Testing). Best-effort.
|
|
425
432
|
const inst = spawnSync("agent-browser", ["install"], { encoding: "utf8", stdio: "ignore" });
|
|
426
|
-
if (inst.status === 0) ok("
|
|
427
|
-
else warn("
|
|
433
|
+
if (inst.status === 0) ok(t("browser.ready"));
|
|
434
|
+
else warn(t("browser.engineMissing"));
|
|
428
435
|
|
|
429
436
|
return true;
|
|
430
437
|
}
|
|
@@ -437,9 +444,9 @@ export function extensions(args) {
|
|
|
437
444
|
}
|
|
438
445
|
|
|
439
446
|
banner();
|
|
440
|
-
log(c.bold(
|
|
447
|
+
log(c.bold(` ${t("ext.bannerTitle")}\n`));
|
|
441
448
|
installDefaults()
|
|
442
|
-
log(`\n ${sym.info}
|
|
449
|
+
log(`\n ${sym.info} ${t("ext.footer", { list: c.lime("baryon extensions list"), remove: c.lime("baryon -- remove <src>") })}\n`)
|
|
443
450
|
return 0;
|
|
444
451
|
}
|
|
445
452
|
|
|
@@ -449,45 +456,46 @@ export function skills(args) {
|
|
|
449
456
|
banner();
|
|
450
457
|
|
|
451
458
|
if (sub === "list" || sub === "ls") {
|
|
452
|
-
log(c.bold(
|
|
459
|
+
log(c.bold(` ${t("skills.bannerListTitle")}\n`));
|
|
453
460
|
for (const s of DEFAULT_SKILLS) {
|
|
454
461
|
const here = fs.existsSync(path.join(PI_SKILLS_DIR, s.name, "SKILL.md"));
|
|
455
|
-
log(` ${here ? sym.ok : sym.info} ${c.lime(s.name)} — ${s.note} ${here ? "" : c.dim(
|
|
462
|
+
log(` ${here ? sym.ok : sym.info} ${c.lime(s.name)} — ${s.note} ${here ? "" : c.dim(t("skills.notInstalled"))}`);
|
|
456
463
|
}
|
|
457
|
-
log(`\n ${sym.info}
|
|
464
|
+
log(`\n ${sym.info} ${t("skills.listFooter", { cmd: c.lime("baryon skills"), dir: c.dim(PI_SKILLS_DIR) })}\n`);
|
|
458
465
|
return 0;
|
|
459
466
|
}
|
|
460
467
|
|
|
461
|
-
log(c.bold(
|
|
468
|
+
log(c.bold(` ${t("skills.bannerInstallTitle")}\n`));
|
|
462
469
|
installSkills();
|
|
463
|
-
log(`\n ${sym.info}
|
|
470
|
+
log(`\n ${sym.info} ${t("skills.installFooter", { call: c.lime("/skill pdf"), list: c.lime("baryon skills list") })}\n`);
|
|
464
471
|
return 0;
|
|
465
472
|
}
|
|
466
473
|
|
|
467
474
|
export function help() {
|
|
468
475
|
banner();
|
|
469
476
|
log(`${c.bold("USAGE")}
|
|
470
|
-
${c.lime("baryon")} ${c.dim("[options] [@files...] [messages...]")}
|
|
477
|
+
${c.lime("baryon")} ${c.dim("[options] [@files...] [messages...]")} ${t("help.usageDesc")}
|
|
471
478
|
|
|
472
479
|
${c.bold("COMMANDS")}
|
|
473
|
-
${c.lime("baryon setup")}
|
|
474
|
-
${c.lime("baryon keys")}
|
|
475
|
-
${c.lime("baryon config")}
|
|
476
|
-
${c.lime("baryon models")}
|
|
477
|
-
${c.lime("baryon extensions")}
|
|
478
|
-
${c.lime("baryon skills")}
|
|
479
|
-
${c.lime("baryon doctor")}
|
|
480
|
-
${c.lime("baryon update")}
|
|
481
|
-
${c.lime("baryon help")}
|
|
480
|
+
${c.lime("baryon setup")} ${t("help.cmd.setup")}
|
|
481
|
+
${c.lime("baryon keys")} ${t("help.cmd.keys")} ${c.dim(t("help.cmd.keysNote"))}
|
|
482
|
+
${c.lime("baryon config")} ${t("help.cmd.config")} ${c.dim(t("help.cmd.configNote"))}
|
|
483
|
+
${c.lime("baryon models")} ${t("help.cmd.models")}
|
|
484
|
+
${c.lime("baryon extensions")} ${t("help.cmd.extensions")} ${c.dim(t("help.cmd.extensionsNote"))}
|
|
485
|
+
${c.lime("baryon skills")} ${t("help.cmd.skills")} ${c.dim(t("help.cmd.skillsNote"))}
|
|
486
|
+
${c.lime("baryon doctor")} ${t("help.cmd.doctor")}
|
|
487
|
+
${c.lime("baryon update")} ${t("help.cmd.update")}
|
|
488
|
+
${c.lime("baryon help")} ${t("help.cmd.help")}
|
|
482
489
|
|
|
483
490
|
${c.bold("EXAMPLES")}
|
|
484
|
-
${c.dim("$")} baryon ${c.dim("
|
|
485
|
-
${c.dim("$")} baryon -p "
|
|
486
|
-
${c.dim("$")} baryon --provider openai ${c.dim("
|
|
487
|
-
${c.dim("$")} baryon --list-models ${c.dim("
|
|
488
|
-
|
|
489
|
-
${c.dim(
|
|
490
|
-
${c.dim(
|
|
491
|
+
${c.dim("$")} baryon ${c.dim(t("help.ex.interactive"))}
|
|
492
|
+
${c.dim("$")} baryon -p "${t("help.ex.oneShotMsg")}" ${c.dim(t("help.ex.oneShot"))}
|
|
493
|
+
${c.dim("$")} baryon --provider openai ${c.dim(t("help.ex.switch"))}
|
|
494
|
+
${c.dim("$")} baryon --list-models ${c.dim(t("help.ex.passthrough"))}
|
|
495
|
+
|
|
496
|
+
${c.dim(t("help.lang", { env: "BARYON_LANG", cmd: "baryon config --lang" }))}
|
|
497
|
+
${c.dim(t("help.passthrough"))}
|
|
498
|
+
${c.dim(t("help.docs", { homepage: HOMEPAGE, email: SUPPORT_EMAIL }))}
|
|
491
499
|
`);
|
|
492
500
|
return 0;
|
|
493
501
|
}
|
|
@@ -495,8 +503,8 @@ ${c.dim(`문서: ${HOMEPAGE} · 문의: ${SUPPORT_EMAIL}`)}
|
|
|
495
503
|
/** Quiet first-run hint shown by postinstall (never fails the install). */
|
|
496
504
|
export function welcome() {
|
|
497
505
|
if (!process.stdout.isTTY) return 0;
|
|
498
|
-
log(`\n${c.lime("✔")} ${c.bold("@baryonlabs/cli")}
|
|
499
|
-
log(` ${c.dim("
|
|
506
|
+
log(`\n${c.lime("✔")} ${t("welcome.installed", { pkg: c.bold("@baryonlabs/cli") })}`);
|
|
507
|
+
log(` ${c.dim(t("welcome.nextLabel"))} ${c.lime("baryon setup")} ${c.dim("→")} ${c.lime("baryon")}`);
|
|
500
508
|
log(` ${c.dim(HOMEPAGE)}\n`);
|
|
501
509
|
return 0;
|
|
502
510
|
}
|
package/src/i18n.js
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
// Tiny zero-dependency ko/en i18n layer for OUR user-facing CLI messages.
|
|
2
|
+
//
|
|
3
|
+
// import { t } from "./i18n.js";
|
|
4
|
+
// t("setup.saved", { file }); // → localized, interpolated string
|
|
5
|
+
//
|
|
6
|
+
// Locale resolution (first hit wins): BARYON_LANG env → `lang` in
|
|
7
|
+
// ~/.baryon/config.json → "ko". Korean is the default & the fallback for any
|
|
8
|
+
// missing key/locale. Resolution NEVER throws.
|
|
9
|
+
import fs from "node:fs";
|
|
10
|
+
import { BARYON_CONFIG } from "./constants.js";
|
|
11
|
+
|
|
12
|
+
/** Normalize "ko", "ko-KR", "en", "en-US", "EN" … → "ko" | "en". Unknown → "ko". */
|
|
13
|
+
export function normalizeLocale(value) {
|
|
14
|
+
const v = String(value || "").trim().toLowerCase();
|
|
15
|
+
if (v.startsWith("en")) return "en";
|
|
16
|
+
if (v.startsWith("ko")) return "ko";
|
|
17
|
+
return "ko";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Read `lang` from ~/.baryon/config.json defensively (never throws). */
|
|
21
|
+
function langFromConfig() {
|
|
22
|
+
try {
|
|
23
|
+
const cfg = JSON.parse(fs.readFileSync(BARYON_CONFIG, "utf8"));
|
|
24
|
+
return cfg && typeof cfg.lang === "string" ? cfg.lang : "";
|
|
25
|
+
} catch {
|
|
26
|
+
return "";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let override = null; // explicit setLocale() wins over env/config when set.
|
|
31
|
+
|
|
32
|
+
/** Resolve the active locale: explicit override → env → config → "ko". */
|
|
33
|
+
export function getLocale() {
|
|
34
|
+
if (override) return override;
|
|
35
|
+
if (process.env.BARYON_LANG) return normalizeLocale(process.env.BARYON_LANG);
|
|
36
|
+
const fromCfg = langFromConfig();
|
|
37
|
+
if (fromCfg) return normalizeLocale(fromCfg);
|
|
38
|
+
return "ko";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Force a locale for the current process (mainly for tests / programmatic use). */
|
|
42
|
+
export function setLocale(value) {
|
|
43
|
+
override = value ? normalizeLocale(value) : null;
|
|
44
|
+
return override;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const MESSAGES = {
|
|
48
|
+
ko: {
|
|
49
|
+
// ── setup ────────────────────────────────────────────────────────────
|
|
50
|
+
"setup.title": "baryon.ai 연결 설정",
|
|
51
|
+
"setup.keyHint": "키 발급·관리: {url}",
|
|
52
|
+
"setup.keyHintSub": " (vibecamp.us 대시보드에서 발급/회수 · 형식 {prefix}…)",
|
|
53
|
+
"setup.keyPrompt": "baryon.ai API key: ",
|
|
54
|
+
"setup.noKey": "API 키 없이 저장합니다. 나중에 `baryon setup --key <KEY>` 로 추가하세요.",
|
|
55
|
+
"setup.badKeyFormat": "키 형식이 {prefix}… 가 아닙니다. 로컬/상용 키라면 무시하세요.",
|
|
56
|
+
"setup.configSaved": "config 저장 → {file}",
|
|
57
|
+
"setup.discovering": "모델 목록을 조회하는 중…",
|
|
58
|
+
"setup.modelsFound": "{count}개 모델 발견 ({list}{more})",
|
|
59
|
+
"setup.modelsFailed": "모델 자동 조회 실패 — 기본 모델 {count}개로 구성 (오프라인/폐쇄망 정상)",
|
|
60
|
+
"setup.providerConfigured": "pi 프로바이더 {provider} 구성 → {file}",
|
|
61
|
+
"setup.skipExtensions": "기본 확장 설치 건너뜀 (--no-extensions)",
|
|
62
|
+
"setup.skipSkills": "기본 스킬 설치 건너뜀 (--no-skills)",
|
|
63
|
+
"setup.skipBrowser": "agent-browser 설치 건너뜀 (--no-browser)",
|
|
64
|
+
"setup.done": "준비 완료. {cmd} 으로 시작하세요.",
|
|
65
|
+
|
|
66
|
+
// ── doctor ───────────────────────────────────────────────────────────
|
|
67
|
+
"doctor.title": "진단 (baryon doctor)",
|
|
68
|
+
"doctor.node": "Node.js {version}",
|
|
69
|
+
"doctor.nodeOld": "Node.js {version} — 22 이상 필요",
|
|
70
|
+
"doctor.piInstalled": "{pkg} 설치됨",
|
|
71
|
+
"doctor.piMissing": "{pkg} 미설치 — npm install -g @baryonlabs/cli",
|
|
72
|
+
"doctor.configFound": "config 존재 → {file}",
|
|
73
|
+
"doctor.configMissing": "config 없음 — `baryon setup` 실행 필요",
|
|
74
|
+
"doctor.apiKeySet": "API 키 설정됨 ({masked})",
|
|
75
|
+
"doctor.apiKeyMissing": "API 키 없음",
|
|
76
|
+
"doctor.cliOutdated": "CLI 구버전 {current} — 최신 {latest}. baryon.ai 사용에 업데이트 필요 (`baryon update`)",
|
|
77
|
+
"doctor.cliCurrent": "CLI 최신 버전 ({current})",
|
|
78
|
+
"doctor.providerRegistered": "pi 프로바이더 {provider} 등록됨 → {file}",
|
|
79
|
+
"doctor.providerMissing": "pi 프로바이더 미등록 — `baryon setup` 실행",
|
|
80
|
+
"doctor.skillsAll": "기본 스킬 {have}/{total} 설치됨 (pdf·pptx·xlsx·agent-browser)",
|
|
81
|
+
"doctor.skillsSome": "기본 스킬 {have}/{total} — `baryon skills` 로 설치",
|
|
82
|
+
"doctor.browserInstalled": "agent-browser 설치됨 ({version})",
|
|
83
|
+
"doctor.browserMissing": "agent-browser 미설치 — `baryon setup`(자동) 또는 `npm i -g agent-browser`",
|
|
84
|
+
"doctor.checkingConn": "연결 확인 중 → {url}",
|
|
85
|
+
"doctor.connOk": "baryon.ai 연결 정상 (HTTP {status})",
|
|
86
|
+
"doctor.connStatus": "엔드포인트 응답 HTTP {status} — 키/권한 확인",
|
|
87
|
+
"doctor.connFail": "연결 불가 ({error}) — 오프라인이면 로컬 LLM 사용 가능",
|
|
88
|
+
"doctor.allPass": "모든 점검 통과",
|
|
89
|
+
"doctor.problems": "{count}건 확인 필요",
|
|
90
|
+
|
|
91
|
+
// ── config ───────────────────────────────────────────────────────────
|
|
92
|
+
"config.updated": "config 업데이트됨",
|
|
93
|
+
"config.title": "현재 설정",
|
|
94
|
+
"config.baseUrl": "base URL {url}",
|
|
95
|
+
"config.default": "default {model}",
|
|
96
|
+
"config.apiKey": "API key {masked}",
|
|
97
|
+
"config.apiKeyNone": "(없음)",
|
|
98
|
+
"config.lang": "language {lang}",
|
|
99
|
+
"config.keysMgmt": "키 관리 {url}",
|
|
100
|
+
"config.file": "config 파일 {file}",
|
|
101
|
+
"config.piModels": "pi models {file}",
|
|
102
|
+
|
|
103
|
+
// ── keys ─────────────────────────────────────────────────────────────
|
|
104
|
+
"keys.title": "키 발급·관리 (vibecamp.us 대시보드):",
|
|
105
|
+
"keys.sub": " 발급/회수/쿼터는 vibecamp.us 가 관리 · 형식 {prefix}…",
|
|
106
|
+
"keys.after": " 발급 후:",
|
|
107
|
+
"keys.or": "또는",
|
|
108
|
+
|
|
109
|
+
// ── update ───────────────────────────────────────────────────────────
|
|
110
|
+
"update.stage1": "1/2 CLI·코어 업데이트: {cmd}",
|
|
111
|
+
"update.npmFail": "npm 실행 실패 — 수동으로 위 명령을 실행하세요.",
|
|
112
|
+
"update.stage2": "2/2 pi 패키지 업데이트: {cmd}",
|
|
113
|
+
"update.done": "업데이트 완료. {hint}",
|
|
114
|
+
"update.doneHint": "baryon doctor 로 점검 가능",
|
|
115
|
+
|
|
116
|
+
// ── extensions install ───────────────────────────────────────────────
|
|
117
|
+
"ext.piMissing": "{pkg} 미설치 — 확장 건너뜀",
|
|
118
|
+
"ext.pruned": "충돌 확장 제거: {names} (자가 치유)",
|
|
119
|
+
"ext.installing": "기본 확장 설치 중 ({count}종 · git clone, 잠시 걸립니다)…",
|
|
120
|
+
"ext.itemOk": "{name} — {note}",
|
|
121
|
+
"ext.itemFail": "{name} 설치 실패(네트워크/git 확인) — 건너뜀",
|
|
122
|
+
"ext.summary": "확장 {ok}/{total} 설치",
|
|
123
|
+
"ext.bannerTitle": "Baryon 기본 확장",
|
|
124
|
+
"ext.footer": "목록: {list} · 제거: {remove}",
|
|
125
|
+
|
|
126
|
+
// ── skills install ───────────────────────────────────────────────────
|
|
127
|
+
"skills.alreadyAll": "기본 스킬 {total}/{total} (이미 설치됨)",
|
|
128
|
+
"skills.installing": "기본 스킬 설치 중 ({count}종)…",
|
|
129
|
+
"skills.noSkillMd": "{name} — SKILL.md 없음({dir}), 건너뜀",
|
|
130
|
+
"skills.itemOk": "skill: {name} — {note}",
|
|
131
|
+
"skills.itemFail": "{name} 스킬 설치 실패 — 건너뜀 ({error})",
|
|
132
|
+
"skills.cloneFail": "스킬 저장소 clone 실패(네트워크/git 확인) — 일부 스킬 건너뜀",
|
|
133
|
+
"skills.summary": "기본 스킬 {ok}/{total} 설치 → {dir}",
|
|
134
|
+
"skills.bannerListTitle": "Baryon 기본 스킬 팩",
|
|
135
|
+
"skills.notInstalled": "(미설치)",
|
|
136
|
+
"skills.listFooter": "설치/동기화: {cmd} · 위치: {dir}",
|
|
137
|
+
"skills.bannerInstallTitle": "Baryon 기본 스킬 설치",
|
|
138
|
+
"skills.installFooter": "사용: pi 에이전트에서 {call} 처럼 호출 · 목록: {list}",
|
|
139
|
+
|
|
140
|
+
// ── browser install ──────────────────────────────────────────────────
|
|
141
|
+
"browser.installed": "agent-browser 설치됨 ({version})",
|
|
142
|
+
"browser.installing": "agent-browser 설치 중 (웹/ERP 자동화 · 최초 1회, 브라우저 다운로드 포함)…",
|
|
143
|
+
"browser.installFail": "agent-browser 설치 실패(네트워크/npm 확인) — 건너뜀. 나중에 `npm i -g agent-browser && agent-browser install`",
|
|
144
|
+
"browser.ready": "agent-browser — 웹/ERP 브라우저 자동화 준비됨",
|
|
145
|
+
"browser.engineMissing": "agent-browser 바이너리는 설치됨 · 브라우저 다운로드 미완 — 최초 사용 시 `agent-browser install`",
|
|
146
|
+
|
|
147
|
+
// ── help ─────────────────────────────────────────────────────────────
|
|
148
|
+
"help.usageDesc": "코딩 에이전트 시작 (baryon.ai 기본)",
|
|
149
|
+
"help.cmd.setup": "baryon.ai API 키 등록 + pi 프로바이더 구성",
|
|
150
|
+
"help.cmd.keys": "키 발급·관리 대시보드 열기",
|
|
151
|
+
"help.cmd.keysNote": "(vibecamp.us)",
|
|
152
|
+
"help.cmd.config": "현재 설정 보기",
|
|
153
|
+
"help.cmd.configNote": "(--key/--base-url/--model/--lang 로 변경)",
|
|
154
|
+
"help.cmd.models": "사용 가능한 모델 목록",
|
|
155
|
+
"help.cmd.extensions": "기본 확장 설치(서브에이전트·캔버스·셸·웹)",
|
|
156
|
+
"help.cmd.extensionsNote": "· list 로 목록",
|
|
157
|
+
"help.cmd.skills": "기본 스킬 설치(pdf·pptx·xlsx)",
|
|
158
|
+
"help.cmd.skillsNote": "· list 로 목록",
|
|
159
|
+
"help.cmd.doctor": "설치·연결 진단",
|
|
160
|
+
"help.cmd.update": "CLI + pi 에이전트 업데이트",
|
|
161
|
+
"help.cmd.help": "이 도움말",
|
|
162
|
+
"help.ex.interactive": "# 대화형 시작",
|
|
163
|
+
"help.ex.oneShot": "# 단발 실행",
|
|
164
|
+
"help.ex.oneShotMsg": "CSV 분석해 차트 만들어줘",
|
|
165
|
+
"help.ex.switch": "# 다른 모델로 전환·비교",
|
|
166
|
+
"help.ex.passthrough": "# pi 패스스루",
|
|
167
|
+
"help.lang": "언어 설정: 환경변수 {env} 또는 {cmd} (ko·en)",
|
|
168
|
+
"help.passthrough": "그 외 모든 옵션은 pi 에이전트로 그대로 전달됩니다.",
|
|
169
|
+
"help.docs": "문서: {homepage} · 문의: {email}",
|
|
170
|
+
|
|
171
|
+
// ── welcome (postinstall) ────────────────────────────────────────────
|
|
172
|
+
"welcome.installed": "{pkg} 설치 완료",
|
|
173
|
+
"welcome.nextLabel": "다음 단계:",
|
|
174
|
+
|
|
175
|
+
// ── runtime / bin ────────────────────────────────────────────────────
|
|
176
|
+
"bin.outdated": "업데이트 필요: @baryonlabs/cli {current} → {latest}",
|
|
177
|
+
"bin.outdatedSub": "baryon.ai 사용에 최신 버전이 필요합니다.",
|
|
178
|
+
"bin.outdatedRun": "를 실행하세요.",
|
|
179
|
+
"pi.notInstalled": "{pkg} is not installed. Run: npm install -g @baryonlabs/cli",
|
|
180
|
+
"bin.piVersion": "pi {version}",
|
|
181
|
+
"bin.unconfiguredTTY": "아직 설정되지 않았습니다.",
|
|
182
|
+
"bin.unconfiguredTTYRun": "을 먼저 실행합니다.",
|
|
183
|
+
"bin.unconfigured": "설정이 없습니다.",
|
|
184
|
+
"bin.unconfiguredRun": "을 먼저 실행하세요.",
|
|
185
|
+
"bin.prunedConflicts": "충돌 확장 정리됨: {names}",
|
|
186
|
+
"bin.room": "🏫 {project} · 좌석 {seat}",
|
|
187
|
+
"bin.roomInactive": "🚫 {project} (비활성) · 좌석 {seat}",
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
en: {
|
|
191
|
+
// ── setup ────────────────────────────────────────────────────────────
|
|
192
|
+
"setup.title": "baryon.ai connection setup",
|
|
193
|
+
"setup.keyHint": "Issue / manage keys: {url}",
|
|
194
|
+
"setup.keyHintSub": " (issue/revoke at the vibecamp.us dashboard · format {prefix}…)",
|
|
195
|
+
"setup.keyPrompt": "baryon.ai API key: ",
|
|
196
|
+
"setup.noKey": "Saving without an API key. Add one later with `baryon setup --key <KEY>`.",
|
|
197
|
+
"setup.badKeyFormat": "Key does not match {prefix}… — ignore this if it's a local/commercial key.",
|
|
198
|
+
"setup.configSaved": "config saved → {file}",
|
|
199
|
+
"setup.discovering": "Fetching model list…",
|
|
200
|
+
"setup.modelsFound": "Found {count} models ({list}{more})",
|
|
201
|
+
"setup.modelsFailed": "Model auto-discovery failed — using {count} default models (normal when offline/air-gapped)",
|
|
202
|
+
"setup.providerConfigured": "pi provider {provider} configured → {file}",
|
|
203
|
+
"setup.skipExtensions": "Skipping default extensions (--no-extensions)",
|
|
204
|
+
"setup.skipSkills": "Skipping default skills (--no-skills)",
|
|
205
|
+
"setup.skipBrowser": "Skipping agent-browser (--no-browser)",
|
|
206
|
+
"setup.done": "All set. Start with {cmd}.",
|
|
207
|
+
|
|
208
|
+
// ── doctor ───────────────────────────────────────────────────────────
|
|
209
|
+
"doctor.title": "Diagnostics (baryon doctor)",
|
|
210
|
+
"doctor.node": "Node.js {version}",
|
|
211
|
+
"doctor.nodeOld": "Node.js {version} — 22 or newer required",
|
|
212
|
+
"doctor.piInstalled": "{pkg} installed",
|
|
213
|
+
"doctor.piMissing": "{pkg} not installed — npm install -g @baryonlabs/cli",
|
|
214
|
+
"doctor.configFound": "config found → {file}",
|
|
215
|
+
"doctor.configMissing": "config missing — run `baryon setup`",
|
|
216
|
+
"doctor.apiKeySet": "API key set ({masked})",
|
|
217
|
+
"doctor.apiKeyMissing": "No API key",
|
|
218
|
+
"doctor.cliOutdated": "CLI outdated {current} — latest {latest}. Update required to use baryon.ai (`baryon update`)",
|
|
219
|
+
"doctor.cliCurrent": "CLI up to date ({current})",
|
|
220
|
+
"doctor.providerRegistered": "pi provider {provider} registered → {file}",
|
|
221
|
+
"doctor.providerMissing": "pi provider not registered — run `baryon setup`",
|
|
222
|
+
"doctor.skillsAll": "Default skills {have}/{total} installed (pdf·pptx·xlsx·agent-browser)",
|
|
223
|
+
"doctor.skillsSome": "Default skills {have}/{total} — install with `baryon skills`",
|
|
224
|
+
"doctor.browserInstalled": "agent-browser installed ({version})",
|
|
225
|
+
"doctor.browserMissing": "agent-browser not installed — `baryon setup` (auto) or `npm i -g agent-browser`",
|
|
226
|
+
"doctor.checkingConn": "Checking connection → {url}",
|
|
227
|
+
"doctor.connOk": "baryon.ai reachable (HTTP {status})",
|
|
228
|
+
"doctor.connStatus": "Endpoint returned HTTP {status} — check key/permissions",
|
|
229
|
+
"doctor.connFail": "Cannot connect ({error}) — a local LLM works if you're offline",
|
|
230
|
+
"doctor.allPass": "All checks passed",
|
|
231
|
+
"doctor.problems": "{count} item(s) need attention",
|
|
232
|
+
|
|
233
|
+
// ── config ───────────────────────────────────────────────────────────
|
|
234
|
+
"config.updated": "config updated",
|
|
235
|
+
"config.title": "Current settings",
|
|
236
|
+
"config.baseUrl": "base URL {url}",
|
|
237
|
+
"config.default": "default {model}",
|
|
238
|
+
"config.apiKey": "API key {masked}",
|
|
239
|
+
"config.apiKeyNone": "(none)",
|
|
240
|
+
"config.lang": "language {lang}",
|
|
241
|
+
"config.keysMgmt": "key mgmt {url}",
|
|
242
|
+
"config.file": "config file {file}",
|
|
243
|
+
"config.piModels": "pi models {file}",
|
|
244
|
+
|
|
245
|
+
// ── keys ─────────────────────────────────────────────────────────────
|
|
246
|
+
"keys.title": "Issue / manage keys (vibecamp.us dashboard):",
|
|
247
|
+
"keys.sub": " issuance/revocation/quota managed by vibecamp.us · format {prefix}…",
|
|
248
|
+
"keys.after": " after issuing:",
|
|
249
|
+
"keys.or": "or",
|
|
250
|
+
|
|
251
|
+
// ── update ───────────────────────────────────────────────────────────
|
|
252
|
+
"update.stage1": "1/2 update CLI & core: {cmd}",
|
|
253
|
+
"update.npmFail": "npm failed — run the command above manually.",
|
|
254
|
+
"update.stage2": "2/2 update pi packages: {cmd}",
|
|
255
|
+
"update.done": "Update complete. {hint}",
|
|
256
|
+
"update.doneHint": "run baryon doctor to verify",
|
|
257
|
+
|
|
258
|
+
// ── extensions install ───────────────────────────────────────────────
|
|
259
|
+
"ext.piMissing": "{pkg} not installed — skipping extensions",
|
|
260
|
+
"ext.pruned": "Removed conflicting extensions: {names} (self-heal)",
|
|
261
|
+
"ext.installing": "Installing default extensions ({count} · git clone, may take a moment)…",
|
|
262
|
+
"ext.itemOk": "{name} — {note}",
|
|
263
|
+
"ext.itemFail": "{name} install failed (check network/git) — skipped",
|
|
264
|
+
"ext.summary": "Extensions {ok}/{total} installed",
|
|
265
|
+
"ext.bannerTitle": "Baryon default extensions",
|
|
266
|
+
"ext.footer": "list: {list} · remove: {remove}",
|
|
267
|
+
|
|
268
|
+
// ── skills install ───────────────────────────────────────────────────
|
|
269
|
+
"skills.alreadyAll": "Default skills {total}/{total} (already installed)",
|
|
270
|
+
"skills.installing": "Installing default skills ({count})…",
|
|
271
|
+
"skills.noSkillMd": "{name} — no SKILL.md ({dir}), skipped",
|
|
272
|
+
"skills.itemOk": "skill: {name} — {note}",
|
|
273
|
+
"skills.itemFail": "{name} skill install failed — skipped ({error})",
|
|
274
|
+
"skills.cloneFail": "Skill repo clone failed (check network/git) — some skills skipped",
|
|
275
|
+
"skills.summary": "Default skills {ok}/{total} installed → {dir}",
|
|
276
|
+
"skills.bannerListTitle": "Baryon default skills pack",
|
|
277
|
+
"skills.notInstalled": "(not installed)",
|
|
278
|
+
"skills.listFooter": "install/sync: {cmd} · location: {dir}",
|
|
279
|
+
"skills.bannerInstallTitle": "Baryon default skills install",
|
|
280
|
+
"skills.installFooter": "use: invoke like {call} in the pi agent · list: {list}",
|
|
281
|
+
|
|
282
|
+
// ── browser install ──────────────────────────────────────────────────
|
|
283
|
+
"browser.installed": "agent-browser installed ({version})",
|
|
284
|
+
"browser.installing": "Installing agent-browser (web/ERP automation · first run, includes browser download)…",
|
|
285
|
+
"browser.installFail": "agent-browser install failed (check network/npm) — skipped. Later: `npm i -g agent-browser && agent-browser install`",
|
|
286
|
+
"browser.ready": "agent-browser — web/ERP browser automation ready",
|
|
287
|
+
"browser.engineMissing": "agent-browser binary installed · browser download incomplete — on first use run `agent-browser install`",
|
|
288
|
+
|
|
289
|
+
// ── help ─────────────────────────────────────────────────────────────
|
|
290
|
+
"help.usageDesc": "Start the coding agent (baryon.ai by default)",
|
|
291
|
+
"help.cmd.setup": "Register baryon.ai API key + configure pi provider",
|
|
292
|
+
"help.cmd.keys": "Open the key issuance/management dashboard",
|
|
293
|
+
"help.cmd.keysNote": "(vibecamp.us)",
|
|
294
|
+
"help.cmd.config": "Show current settings",
|
|
295
|
+
"help.cmd.configNote": "(change with --key/--base-url/--model/--lang)",
|
|
296
|
+
"help.cmd.models": "List available models",
|
|
297
|
+
"help.cmd.extensions": "Install default extensions (sub-agents·canvas·shell·web)",
|
|
298
|
+
"help.cmd.extensionsNote": "· list to view",
|
|
299
|
+
"help.cmd.skills": "Install default skills (pdf·pptx·xlsx)",
|
|
300
|
+
"help.cmd.skillsNote": "· list to view",
|
|
301
|
+
"help.cmd.doctor": "Diagnose install & connectivity",
|
|
302
|
+
"help.cmd.update": "Update CLI + pi agent",
|
|
303
|
+
"help.cmd.help": "This help",
|
|
304
|
+
"help.ex.interactive": "# interactive start",
|
|
305
|
+
"help.ex.oneShot": "# one-shot run",
|
|
306
|
+
"help.ex.oneShotMsg": "analyze the CSV and make a chart",
|
|
307
|
+
"help.ex.switch": "# switch/compare other models",
|
|
308
|
+
"help.ex.passthrough": "# pi passthrough",
|
|
309
|
+
"help.lang": "Language: env var {env} or {cmd} (ko·en)",
|
|
310
|
+
"help.passthrough": "All other options are passed straight through to the pi agent.",
|
|
311
|
+
"help.docs": "Docs: {homepage} · Support: {email}",
|
|
312
|
+
|
|
313
|
+
// ── welcome (postinstall) ────────────────────────────────────────────
|
|
314
|
+
"welcome.installed": "{pkg} installed",
|
|
315
|
+
"welcome.nextLabel": "Next:",
|
|
316
|
+
|
|
317
|
+
// ── runtime / bin ────────────────────────────────────────────────────
|
|
318
|
+
"bin.outdated": "Update required: @baryonlabs/cli {current} → {latest}",
|
|
319
|
+
"bin.outdatedSub": "baryon.ai requires the latest version.",
|
|
320
|
+
"bin.outdatedRun": "to update.",
|
|
321
|
+
"pi.notInstalled": "{pkg} is not installed. Run: npm install -g @baryonlabs/cli",
|
|
322
|
+
"bin.piVersion": "pi {version}",
|
|
323
|
+
"bin.unconfiguredTTY": "Not configured yet.",
|
|
324
|
+
"bin.unconfiguredTTYRun": "will run first.",
|
|
325
|
+
"bin.unconfigured": "No configuration found.",
|
|
326
|
+
"bin.unconfiguredRun": "first.",
|
|
327
|
+
"bin.prunedConflicts": "Cleaned up conflicting extensions: {names}",
|
|
328
|
+
"bin.room": "🏫 {project} · seat {seat}",
|
|
329
|
+
"bin.roomInactive": "🚫 {project} (inactive) · seat {seat}",
|
|
330
|
+
},
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
/** Interpolate {name}-style placeholders from `vars`. Missing → left as-is. */
|
|
334
|
+
function interpolate(str, vars) {
|
|
335
|
+
return str.replace(/\{(\w+)\}/g, (m, k) =>
|
|
336
|
+
Object.prototype.hasOwnProperty.call(vars, k) ? String(vars[k]) : m,
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Look up `key` for the active locale, interpolate `vars`, and fall back to
|
|
342
|
+
* Korean (then to the key string itself) if missing. Never throws.
|
|
343
|
+
*/
|
|
344
|
+
export function t(key, vars = {}) {
|
|
345
|
+
let locale;
|
|
346
|
+
try {
|
|
347
|
+
locale = getLocale();
|
|
348
|
+
} catch {
|
|
349
|
+
locale = "ko";
|
|
350
|
+
}
|
|
351
|
+
const fromLocale = MESSAGES[locale]?.[key];
|
|
352
|
+
const fromKo = MESSAGES.ko[key];
|
|
353
|
+
const template = fromLocale != null ? fromLocale : fromKo != null ? fromKo : key;
|
|
354
|
+
try {
|
|
355
|
+
return interpolate(template, vars || {});
|
|
356
|
+
} catch {
|
|
357
|
+
return template;
|
|
358
|
+
}
|
|
359
|
+
}
|
package/src/pi.js
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
CLIENT_VERSION,
|
|
17
17
|
} from "./constants.js";
|
|
18
18
|
import { ensurePiSessionHeader } from "./config.js";
|
|
19
|
+
import { t } from "./i18n.js";
|
|
19
20
|
|
|
20
21
|
const require = createRequire(import.meta.url);
|
|
21
22
|
|
|
@@ -84,11 +85,7 @@ function userOverridesTargeting(args) {
|
|
|
84
85
|
export function runPi(args, config, { injectTargeting = true } = {}) {
|
|
85
86
|
const entry = resolvePiEntry();
|
|
86
87
|
if (!entry) {
|
|
87
|
-
return Promise.reject(
|
|
88
|
-
new Error(
|
|
89
|
-
`${PI_PACKAGE} is not installed. Run: npm install -g @baryonlabs/cli`,
|
|
90
|
-
),
|
|
91
|
-
);
|
|
88
|
+
return Promise.reject(new Error(t("pi.notInstalled", { pkg: PI_PACKAGE })));
|
|
92
89
|
}
|
|
93
90
|
|
|
94
91
|
const finalArgs = [...args];
|