@baryonlabs/cli 0.3.5 → 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 +127 -104
- 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"
|
|
@@ -246,17 +253,32 @@ export function keys() {
|
|
|
246
253
|
|
|
247
254
|
export function update() {
|
|
248
255
|
return new Promise((resolve) => {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
err("
|
|
256
|
+
// 1/2 — CLI + pi core via npm (gets the latest pi binary, e.g. 0.80.x).
|
|
257
|
+
log(` ${sym.info} ${t("update.stage1", { cmd: c.lime(`npm install -g @baryonlabs/cli ${PI_PACKAGE}`) })}\n`);
|
|
258
|
+
const npm = spawn("npm", ["install", "-g", "@baryonlabs/cli", PI_PACKAGE], {
|
|
259
|
+
stdio: "inherit",
|
|
260
|
+
shell: process.platform === "win32",
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
npm.on("error", () => {
|
|
264
|
+
err(t("update.npmFail"));
|
|
258
265
|
resolve(1);
|
|
259
266
|
});
|
|
267
|
+
|
|
268
|
+
npm.on("exit", (code) => {
|
|
269
|
+
// 2/2 — pi's own packages (pi-mcp-adapter, pi-dynamic-workflows, …) are
|
|
270
|
+
// managed by `pi update`, not npm. Run it so those notices clear too.
|
|
271
|
+
const entry = resolvePiEntry();
|
|
272
|
+
if (!entry) return resolve(code ?? 0);
|
|
273
|
+
|
|
274
|
+
log(`\n ${sym.info} ${t("update.stage2", { cmd: c.lime("pi update") })}\n`);
|
|
275
|
+
const pu = spawn(process.execPath, [entry, "update"], { stdio: "inherit" });
|
|
276
|
+
pu.on("error", () => resolve(code ?? 0));
|
|
277
|
+
pu.on("exit", () => {
|
|
278
|
+
log(`\n ${sym.ok} ${t("update.done", { hint: c.dim(t("update.doneHint")) })}`);
|
|
279
|
+
resolve(code ?? 0);
|
|
280
|
+
});
|
|
281
|
+
});
|
|
260
282
|
});
|
|
261
283
|
}
|
|
262
284
|
|
|
@@ -264,7 +286,7 @@ export function installDefaults() {
|
|
|
264
286
|
const entry = resolvePiEntry();
|
|
265
287
|
|
|
266
288
|
if (!entry) {
|
|
267
|
-
warn(
|
|
289
|
+
warn(t("ext.piMissing", { pkg: PI_PACKAGE }));
|
|
268
290
|
return 0;
|
|
269
291
|
}
|
|
270
292
|
|
|
@@ -272,9 +294,9 @@ export function installDefaults() {
|
|
|
272
294
|
// (e.g. pi-search ↔ pi-web-fetch both registering `web_fetch`, which hard-fails
|
|
273
295
|
// every run). Remove them from pi's registry + disk before (re)installing.
|
|
274
296
|
const pruned = prunePiPackages(DEPRECATED_EXTENSIONS);
|
|
275
|
-
if (pruned.length) warn(
|
|
297
|
+
if (pruned.length) warn(t("ext.pruned", { names: pruned.join(", ") }));
|
|
276
298
|
|
|
277
|
-
log(` ${sym.info}
|
|
299
|
+
log(` ${sym.info} ${t("ext.installing", { count: DEFAULT_EXTENSIONS.length })}`);
|
|
278
300
|
let okc = 0;
|
|
279
301
|
|
|
280
302
|
for (const e of DEFAULT_EXTENSIONS) {
|
|
@@ -291,14 +313,14 @@ export function installDefaults() {
|
|
|
291
313
|
}
|
|
292
314
|
|
|
293
315
|
if (status === 0) {
|
|
294
|
-
ok(
|
|
316
|
+
ok(t("ext.itemOk", { name: e.name, note: e.note }));
|
|
295
317
|
okc++;
|
|
296
318
|
} else {
|
|
297
|
-
warn(
|
|
319
|
+
warn(t("ext.itemFail", { name: e.name }));
|
|
298
320
|
}
|
|
299
321
|
}
|
|
300
322
|
|
|
301
|
-
log(` ${sym.ok}
|
|
323
|
+
log(` ${sym.ok} ${t("ext.summary", { ok: okc, total: DEFAULT_EXTENSIONS.length })}`);
|
|
302
324
|
return okc;
|
|
303
325
|
}
|
|
304
326
|
|
|
@@ -312,11 +334,11 @@ export function installSkills() {
|
|
|
312
334
|
let okc = DEFAULT_SKILLS.length - missing.length;
|
|
313
335
|
|
|
314
336
|
if (missing.length === 0) {
|
|
315
|
-
log(` ${sym.ok}
|
|
337
|
+
log(` ${sym.ok} ${t("skills.alreadyAll", { total: DEFAULT_SKILLS.length })}`);
|
|
316
338
|
return DEFAULT_SKILLS.length;
|
|
317
339
|
}
|
|
318
340
|
|
|
319
|
-
log(` ${sym.info}
|
|
341
|
+
log(` ${sym.info} ${t("skills.installing", { count: missing.length })}`);
|
|
320
342
|
fs.mkdirSync(PI_SKILLS_DIR, { recursive: true });
|
|
321
343
|
|
|
322
344
|
// Bundled skills ship inside this package under ../skills/<name>/.
|
|
@@ -325,12 +347,12 @@ export function installSkills() {
|
|
|
325
347
|
const copySkill = (srcDir, s) => {
|
|
326
348
|
const dst = path.join(PI_SKILLS_DIR, s.name);
|
|
327
349
|
if (!fs.existsSync(path.join(srcDir, "SKILL.md"))) {
|
|
328
|
-
warn(
|
|
350
|
+
warn(t("skills.noSkillMd", { name: s.name, dir: srcDir }));
|
|
329
351
|
return false;
|
|
330
352
|
}
|
|
331
353
|
fs.rmSync(dst, { recursive: true, force: true });
|
|
332
354
|
fs.cpSync(srcDir, dst, { recursive: true });
|
|
333
|
-
ok(
|
|
355
|
+
ok(t("skills.itemOk", { name: s.name, note: s.note }));
|
|
334
356
|
return true;
|
|
335
357
|
};
|
|
336
358
|
|
|
@@ -339,7 +361,7 @@ export function installSkills() {
|
|
|
339
361
|
try {
|
|
340
362
|
if (copySkill(path.join(bundledRoot, s.name), s)) okc++;
|
|
341
363
|
} catch (e) {
|
|
342
|
-
warn(
|
|
364
|
+
warn(t("skills.itemFail", { name: s.name, error: e.message }));
|
|
343
365
|
}
|
|
344
366
|
}
|
|
345
367
|
|
|
@@ -361,13 +383,13 @@ export function installSkills() {
|
|
|
361
383
|
}
|
|
362
384
|
|
|
363
385
|
if (!cloned) {
|
|
364
|
-
warn(
|
|
386
|
+
warn(t("skills.cloneFail"));
|
|
365
387
|
} else {
|
|
366
388
|
for (const s of repoSkills) {
|
|
367
389
|
try {
|
|
368
390
|
if (copySkill(path.join(tmp, ...s.subdir.split("/")), s)) okc++;
|
|
369
391
|
} catch (e) {
|
|
370
|
-
warn(
|
|
392
|
+
warn(t("skills.itemFail", { name: s.name, error: e.message }));
|
|
371
393
|
}
|
|
372
394
|
}
|
|
373
395
|
}
|
|
@@ -376,7 +398,7 @@ export function installSkills() {
|
|
|
376
398
|
}
|
|
377
399
|
}
|
|
378
400
|
|
|
379
|
-
log(` ${sym.ok}
|
|
401
|
+
log(` ${sym.ok} ${t("skills.summary", { ok: okc, total: DEFAULT_SKILLS.length, dir: PI_SKILLS_DIR })}`);
|
|
380
402
|
return okc;
|
|
381
403
|
}
|
|
382
404
|
|
|
@@ -388,11 +410,11 @@ export function installBrowser() {
|
|
|
388
410
|
// Already present?
|
|
389
411
|
const probe = spawnSync("agent-browser", ["--version"], { encoding: "utf8" });
|
|
390
412
|
if (probe.status === 0) {
|
|
391
|
-
ok(
|
|
413
|
+
ok(t("browser.installed", { version: (probe.stdout || "").trim() || "ok" }));
|
|
392
414
|
return true;
|
|
393
415
|
}
|
|
394
416
|
|
|
395
|
-
log(` ${sym.info}
|
|
417
|
+
log(` ${sym.info} ${t("browser.installing")}`);
|
|
396
418
|
|
|
397
419
|
let ok1 = false;
|
|
398
420
|
for (let attempt = 1; attempt <= 2 && !ok1; attempt++) {
|
|
@@ -402,14 +424,14 @@ export function installBrowser() {
|
|
|
402
424
|
}
|
|
403
425
|
|
|
404
426
|
if (!ok1) {
|
|
405
|
-
warn("
|
|
427
|
+
warn(t("browser.installFail"));
|
|
406
428
|
return false;
|
|
407
429
|
}
|
|
408
430
|
|
|
409
431
|
// Download the browser engine (Chrome for Testing). Best-effort.
|
|
410
432
|
const inst = spawnSync("agent-browser", ["install"], { encoding: "utf8", stdio: "ignore" });
|
|
411
|
-
if (inst.status === 0) ok("
|
|
412
|
-
else warn("
|
|
433
|
+
if (inst.status === 0) ok(t("browser.ready"));
|
|
434
|
+
else warn(t("browser.engineMissing"));
|
|
413
435
|
|
|
414
436
|
return true;
|
|
415
437
|
}
|
|
@@ -422,9 +444,9 @@ export function extensions(args) {
|
|
|
422
444
|
}
|
|
423
445
|
|
|
424
446
|
banner();
|
|
425
|
-
log(c.bold(
|
|
447
|
+
log(c.bold(` ${t("ext.bannerTitle")}\n`));
|
|
426
448
|
installDefaults()
|
|
427
|
-
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`)
|
|
428
450
|
return 0;
|
|
429
451
|
}
|
|
430
452
|
|
|
@@ -434,45 +456,46 @@ export function skills(args) {
|
|
|
434
456
|
banner();
|
|
435
457
|
|
|
436
458
|
if (sub === "list" || sub === "ls") {
|
|
437
|
-
log(c.bold(
|
|
459
|
+
log(c.bold(` ${t("skills.bannerListTitle")}\n`));
|
|
438
460
|
for (const s of DEFAULT_SKILLS) {
|
|
439
461
|
const here = fs.existsSync(path.join(PI_SKILLS_DIR, s.name, "SKILL.md"));
|
|
440
|
-
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"))}`);
|
|
441
463
|
}
|
|
442
|
-
log(`\n ${sym.info}
|
|
464
|
+
log(`\n ${sym.info} ${t("skills.listFooter", { cmd: c.lime("baryon skills"), dir: c.dim(PI_SKILLS_DIR) })}\n`);
|
|
443
465
|
return 0;
|
|
444
466
|
}
|
|
445
467
|
|
|
446
|
-
log(c.bold(
|
|
468
|
+
log(c.bold(` ${t("skills.bannerInstallTitle")}\n`));
|
|
447
469
|
installSkills();
|
|
448
|
-
log(`\n ${sym.info}
|
|
470
|
+
log(`\n ${sym.info} ${t("skills.installFooter", { call: c.lime("/skill pdf"), list: c.lime("baryon skills list") })}\n`);
|
|
449
471
|
return 0;
|
|
450
472
|
}
|
|
451
473
|
|
|
452
474
|
export function help() {
|
|
453
475
|
banner();
|
|
454
476
|
log(`${c.bold("USAGE")}
|
|
455
|
-
${c.lime("baryon")} ${c.dim("[options] [@files...] [messages...]")}
|
|
477
|
+
${c.lime("baryon")} ${c.dim("[options] [@files...] [messages...]")} ${t("help.usageDesc")}
|
|
456
478
|
|
|
457
479
|
${c.bold("COMMANDS")}
|
|
458
|
-
${c.lime("baryon setup")}
|
|
459
|
-
${c.lime("baryon keys")}
|
|
460
|
-
${c.lime("baryon config")}
|
|
461
|
-
${c.lime("baryon models")}
|
|
462
|
-
${c.lime("baryon extensions")}
|
|
463
|
-
${c.lime("baryon skills")}
|
|
464
|
-
${c.lime("baryon doctor")}
|
|
465
|
-
${c.lime("baryon update")}
|
|
466
|
-
${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")}
|
|
467
489
|
|
|
468
490
|
${c.bold("EXAMPLES")}
|
|
469
|
-
${c.dim("$")} baryon ${c.dim("
|
|
470
|
-
${c.dim("$")} baryon -p "
|
|
471
|
-
${c.dim("$")} baryon --provider openai ${c.dim("
|
|
472
|
-
${c.dim("$")} baryon --list-models ${c.dim("
|
|
473
|
-
|
|
474
|
-
${c.dim(
|
|
475
|
-
${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 }))}
|
|
476
499
|
`);
|
|
477
500
|
return 0;
|
|
478
501
|
}
|
|
@@ -480,8 +503,8 @@ ${c.dim(`문서: ${HOMEPAGE} · 문의: ${SUPPORT_EMAIL}`)}
|
|
|
480
503
|
/** Quiet first-run hint shown by postinstall (never fails the install). */
|
|
481
504
|
export function welcome() {
|
|
482
505
|
if (!process.stdout.isTTY) return 0;
|
|
483
|
-
log(`\n${c.lime("✔")} ${c.bold("@baryonlabs/cli")}
|
|
484
|
-
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")}`);
|
|
485
508
|
log(` ${c.dim(HOMEPAGE)}\n`);
|
|
486
509
|
return 0;
|
|
487
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];
|