@baryonlabs/cli 0.3.6 → 0.3.8
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 +21 -7
- package/package.json +1 -1
- package/src/api.js +25 -0
- package/src/commands.js +123 -99
- package/src/i18n.js +361 -0
- package/src/pi.js +2 -5
package/bin/baryon.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
keys,
|
|
10
10
|
extensions,
|
|
11
11
|
skills,
|
|
12
|
+
edge,
|
|
12
13
|
update,
|
|
13
14
|
help,
|
|
14
15
|
welcome,
|
|
@@ -16,10 +17,11 @@ import {
|
|
|
16
17
|
import { loadConfig, piProviderConfigured, hasConfig, prunePiPackages } from "../src/config.js";
|
|
17
18
|
import { DEPRECATED_EXTENSIONS } from "../src/constants.js";
|
|
18
19
|
import { runPi, resolvePiEntry } from "../src/pi.js";
|
|
19
|
-
import { checkLatest } from "../src/api.js";
|
|
20
|
+
import { checkLatest, whoami } from "../src/api.js";
|
|
20
21
|
import { spawnSync } from "node:child_process";
|
|
21
22
|
import { createRequire } from "node:module";
|
|
22
23
|
import { c, err, log, sym } from "../src/ui.js";
|
|
24
|
+
import { t } from "../src/i18n.js";
|
|
23
25
|
|
|
24
26
|
/** Best-effort: warn loudly when a newer CLI exists. The gateway enforces the
|
|
25
27
|
* minimum version (426), so cloud use is blocked until you update; this is the
|
|
@@ -28,8 +30,8 @@ async function warnIfOutdated() {
|
|
|
28
30
|
const r = await checkLatest();
|
|
29
31
|
if (r?.outdated) {
|
|
30
32
|
log(
|
|
31
|
-
`\n ${sym.warn} ${c.yellow(
|
|
32
|
-
` ${c.dim("
|
|
33
|
+
`\n ${sym.warn} ${c.yellow(t("bin.outdated", { current: r.current, latest: r.latest }))}\n` +
|
|
34
|
+
` ${c.dim(t("bin.outdatedSub"))} ${c.lime("baryon update")} ${c.dim(t("bin.outdatedRun") + "\n")}`,
|
|
33
35
|
);
|
|
34
36
|
}
|
|
35
37
|
}
|
|
@@ -44,7 +46,7 @@ function showVersion() {
|
|
|
44
46
|
const r = spawnSync(process.execPath, [entry, "--version"], {
|
|
45
47
|
encoding: "utf8",
|
|
46
48
|
});
|
|
47
|
-
if (r.stdout) log(
|
|
49
|
+
if (r.stdout) log(t("bin.piVersion", { version: c.dim(r.stdout.trim()) }));
|
|
48
50
|
}
|
|
49
51
|
return 0;
|
|
50
52
|
}
|
|
@@ -74,6 +76,8 @@ async function main() {
|
|
|
74
76
|
case "skills":
|
|
75
77
|
case "skill":
|
|
76
78
|
return skills(rest);
|
|
79
|
+
case "edge":
|
|
80
|
+
return edge(rest);
|
|
77
81
|
case "update":
|
|
78
82
|
case "upgrade":
|
|
79
83
|
return update();
|
|
@@ -97,12 +101,12 @@ async function main() {
|
|
|
97
101
|
if (unconfigured && !userTargets) {
|
|
98
102
|
if (process.stdin.isTTY) {
|
|
99
103
|
log(
|
|
100
|
-
` ${sym.warn} ${c.yellow("
|
|
104
|
+
` ${sym.warn} ${c.yellow(t("bin.unconfiguredTTY"))} ${c.lime("baryon setup")} ${c.dim(t("bin.unconfiguredTTYRun"))}\n`,
|
|
101
105
|
);
|
|
102
106
|
return setup([]);
|
|
103
107
|
}
|
|
104
108
|
log(
|
|
105
|
-
` ${sym.warn} ${c.yellow("
|
|
109
|
+
` ${sym.warn} ${c.yellow(t("bin.unconfigured"))} ${c.lime("baryon setup")} ${c.dim(t("bin.unconfiguredRun"))}`,
|
|
106
110
|
);
|
|
107
111
|
return 1;
|
|
108
112
|
}
|
|
@@ -112,11 +116,21 @@ async function main() {
|
|
|
112
116
|
try {
|
|
113
117
|
const pruned = prunePiPackages(DEPRECATED_EXTENSIONS);
|
|
114
118
|
if (pruned.length)
|
|
115
|
-
log(` ${sym.info} ${c.dim(
|
|
119
|
+
log(` ${sym.info} ${c.dim(t("bin.prunedConflicts", { names: pruned.join(", ") }))}`);
|
|
116
120
|
} catch {
|
|
117
121
|
/* best-effort */
|
|
118
122
|
}
|
|
119
123
|
const cfg = loadConfig();
|
|
124
|
+
// Show which room (project/분반 · seat) this key is in — best-effort.
|
|
125
|
+
try {
|
|
126
|
+
const who = await whoami(cfg.baseUrl, cfg.apiKey);
|
|
127
|
+
if (who?.project) {
|
|
128
|
+
const key = who.project_status === "active" ? "bin.room" : "bin.roomInactive";
|
|
129
|
+
log(` ${c.teal(t(key, { project: who.project, seat: who.seat || "—" }))}`);
|
|
130
|
+
}
|
|
131
|
+
} catch {
|
|
132
|
+
/* best-effort */
|
|
133
|
+
}
|
|
120
134
|
return runPi(argv, cfg);
|
|
121
135
|
}
|
|
122
136
|
}
|
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"
|
|
@@ -244,17 +251,33 @@ export function keys() {
|
|
|
244
251
|
return 0;
|
|
245
252
|
}
|
|
246
253
|
|
|
254
|
+
// Enterprise: delegate to @baryonlabs/edge's launcher (read-only data sandbox).
|
|
255
|
+
export function edge(args) {
|
|
256
|
+
return new Promise((resolve) => {
|
|
257
|
+
const child = spawn("baryon-edge", args, {
|
|
258
|
+
stdio: "inherit",
|
|
259
|
+
shell: process.platform === "win32",
|
|
260
|
+
});
|
|
261
|
+
child.on("error", () => {
|
|
262
|
+
log(` ${sym.warn} ${t("edge.notInstalled")}`);
|
|
263
|
+
log(` ${c.lime("npm i -g @baryonlabs/edge")}`);
|
|
264
|
+
resolve(1);
|
|
265
|
+
});
|
|
266
|
+
child.on("exit", (code) => resolve(code ?? 0));
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
247
270
|
export function update() {
|
|
248
271
|
return new Promise((resolve) => {
|
|
249
272
|
// 1/2 — CLI + pi core via npm (gets the latest pi binary, e.g. 0.80.x).
|
|
250
|
-
log(` ${sym.info}
|
|
273
|
+
log(` ${sym.info} ${t("update.stage1", { cmd: c.lime(`npm install -g @baryonlabs/cli ${PI_PACKAGE}`) })}\n`);
|
|
251
274
|
const npm = spawn("npm", ["install", "-g", "@baryonlabs/cli", PI_PACKAGE], {
|
|
252
275
|
stdio: "inherit",
|
|
253
276
|
shell: process.platform === "win32",
|
|
254
277
|
});
|
|
255
278
|
|
|
256
279
|
npm.on("error", () => {
|
|
257
|
-
err("
|
|
280
|
+
err(t("update.npmFail"));
|
|
258
281
|
resolve(1);
|
|
259
282
|
});
|
|
260
283
|
|
|
@@ -264,11 +287,11 @@ export function update() {
|
|
|
264
287
|
const entry = resolvePiEntry();
|
|
265
288
|
if (!entry) return resolve(code ?? 0);
|
|
266
289
|
|
|
267
|
-
log(`\n ${sym.info}
|
|
290
|
+
log(`\n ${sym.info} ${t("update.stage2", { cmd: c.lime("pi update") })}\n`);
|
|
268
291
|
const pu = spawn(process.execPath, [entry, "update"], { stdio: "inherit" });
|
|
269
292
|
pu.on("error", () => resolve(code ?? 0));
|
|
270
293
|
pu.on("exit", () => {
|
|
271
|
-
log(`\n ${sym.ok}
|
|
294
|
+
log(`\n ${sym.ok} ${t("update.done", { hint: c.dim(t("update.doneHint")) })}`);
|
|
272
295
|
resolve(code ?? 0);
|
|
273
296
|
});
|
|
274
297
|
});
|
|
@@ -279,7 +302,7 @@ export function installDefaults() {
|
|
|
279
302
|
const entry = resolvePiEntry();
|
|
280
303
|
|
|
281
304
|
if (!entry) {
|
|
282
|
-
warn(
|
|
305
|
+
warn(t("ext.piMissing", { pkg: PI_PACKAGE }));
|
|
283
306
|
return 0;
|
|
284
307
|
}
|
|
285
308
|
|
|
@@ -287,9 +310,9 @@ export function installDefaults() {
|
|
|
287
310
|
// (e.g. pi-search ↔ pi-web-fetch both registering `web_fetch`, which hard-fails
|
|
288
311
|
// every run). Remove them from pi's registry + disk before (re)installing.
|
|
289
312
|
const pruned = prunePiPackages(DEPRECATED_EXTENSIONS);
|
|
290
|
-
if (pruned.length) warn(
|
|
313
|
+
if (pruned.length) warn(t("ext.pruned", { names: pruned.join(", ") }));
|
|
291
314
|
|
|
292
|
-
log(` ${sym.info}
|
|
315
|
+
log(` ${sym.info} ${t("ext.installing", { count: DEFAULT_EXTENSIONS.length })}`);
|
|
293
316
|
let okc = 0;
|
|
294
317
|
|
|
295
318
|
for (const e of DEFAULT_EXTENSIONS) {
|
|
@@ -306,14 +329,14 @@ export function installDefaults() {
|
|
|
306
329
|
}
|
|
307
330
|
|
|
308
331
|
if (status === 0) {
|
|
309
|
-
ok(
|
|
332
|
+
ok(t("ext.itemOk", { name: e.name, note: e.note }));
|
|
310
333
|
okc++;
|
|
311
334
|
} else {
|
|
312
|
-
warn(
|
|
335
|
+
warn(t("ext.itemFail", { name: e.name }));
|
|
313
336
|
}
|
|
314
337
|
}
|
|
315
338
|
|
|
316
|
-
log(` ${sym.ok}
|
|
339
|
+
log(` ${sym.ok} ${t("ext.summary", { ok: okc, total: DEFAULT_EXTENSIONS.length })}`);
|
|
317
340
|
return okc;
|
|
318
341
|
}
|
|
319
342
|
|
|
@@ -327,11 +350,11 @@ export function installSkills() {
|
|
|
327
350
|
let okc = DEFAULT_SKILLS.length - missing.length;
|
|
328
351
|
|
|
329
352
|
if (missing.length === 0) {
|
|
330
|
-
log(` ${sym.ok}
|
|
353
|
+
log(` ${sym.ok} ${t("skills.alreadyAll", { total: DEFAULT_SKILLS.length })}`);
|
|
331
354
|
return DEFAULT_SKILLS.length;
|
|
332
355
|
}
|
|
333
356
|
|
|
334
|
-
log(` ${sym.info}
|
|
357
|
+
log(` ${sym.info} ${t("skills.installing", { count: missing.length })}`);
|
|
335
358
|
fs.mkdirSync(PI_SKILLS_DIR, { recursive: true });
|
|
336
359
|
|
|
337
360
|
// Bundled skills ship inside this package under ../skills/<name>/.
|
|
@@ -340,12 +363,12 @@ export function installSkills() {
|
|
|
340
363
|
const copySkill = (srcDir, s) => {
|
|
341
364
|
const dst = path.join(PI_SKILLS_DIR, s.name);
|
|
342
365
|
if (!fs.existsSync(path.join(srcDir, "SKILL.md"))) {
|
|
343
|
-
warn(
|
|
366
|
+
warn(t("skills.noSkillMd", { name: s.name, dir: srcDir }));
|
|
344
367
|
return false;
|
|
345
368
|
}
|
|
346
369
|
fs.rmSync(dst, { recursive: true, force: true });
|
|
347
370
|
fs.cpSync(srcDir, dst, { recursive: true });
|
|
348
|
-
ok(
|
|
371
|
+
ok(t("skills.itemOk", { name: s.name, note: s.note }));
|
|
349
372
|
return true;
|
|
350
373
|
};
|
|
351
374
|
|
|
@@ -354,7 +377,7 @@ export function installSkills() {
|
|
|
354
377
|
try {
|
|
355
378
|
if (copySkill(path.join(bundledRoot, s.name), s)) okc++;
|
|
356
379
|
} catch (e) {
|
|
357
|
-
warn(
|
|
380
|
+
warn(t("skills.itemFail", { name: s.name, error: e.message }));
|
|
358
381
|
}
|
|
359
382
|
}
|
|
360
383
|
|
|
@@ -376,13 +399,13 @@ export function installSkills() {
|
|
|
376
399
|
}
|
|
377
400
|
|
|
378
401
|
if (!cloned) {
|
|
379
|
-
warn(
|
|
402
|
+
warn(t("skills.cloneFail"));
|
|
380
403
|
} else {
|
|
381
404
|
for (const s of repoSkills) {
|
|
382
405
|
try {
|
|
383
406
|
if (copySkill(path.join(tmp, ...s.subdir.split("/")), s)) okc++;
|
|
384
407
|
} catch (e) {
|
|
385
|
-
warn(
|
|
408
|
+
warn(t("skills.itemFail", { name: s.name, error: e.message }));
|
|
386
409
|
}
|
|
387
410
|
}
|
|
388
411
|
}
|
|
@@ -391,7 +414,7 @@ export function installSkills() {
|
|
|
391
414
|
}
|
|
392
415
|
}
|
|
393
416
|
|
|
394
|
-
log(` ${sym.ok}
|
|
417
|
+
log(` ${sym.ok} ${t("skills.summary", { ok: okc, total: DEFAULT_SKILLS.length, dir: PI_SKILLS_DIR })}`);
|
|
395
418
|
return okc;
|
|
396
419
|
}
|
|
397
420
|
|
|
@@ -403,11 +426,11 @@ export function installBrowser() {
|
|
|
403
426
|
// Already present?
|
|
404
427
|
const probe = spawnSync("agent-browser", ["--version"], { encoding: "utf8" });
|
|
405
428
|
if (probe.status === 0) {
|
|
406
|
-
ok(
|
|
429
|
+
ok(t("browser.installed", { version: (probe.stdout || "").trim() || "ok" }));
|
|
407
430
|
return true;
|
|
408
431
|
}
|
|
409
432
|
|
|
410
|
-
log(` ${sym.info}
|
|
433
|
+
log(` ${sym.info} ${t("browser.installing")}`);
|
|
411
434
|
|
|
412
435
|
let ok1 = false;
|
|
413
436
|
for (let attempt = 1; attempt <= 2 && !ok1; attempt++) {
|
|
@@ -417,14 +440,14 @@ export function installBrowser() {
|
|
|
417
440
|
}
|
|
418
441
|
|
|
419
442
|
if (!ok1) {
|
|
420
|
-
warn("
|
|
443
|
+
warn(t("browser.installFail"));
|
|
421
444
|
return false;
|
|
422
445
|
}
|
|
423
446
|
|
|
424
447
|
// Download the browser engine (Chrome for Testing). Best-effort.
|
|
425
448
|
const inst = spawnSync("agent-browser", ["install"], { encoding: "utf8", stdio: "ignore" });
|
|
426
|
-
if (inst.status === 0) ok("
|
|
427
|
-
else warn("
|
|
449
|
+
if (inst.status === 0) ok(t("browser.ready"));
|
|
450
|
+
else warn(t("browser.engineMissing"));
|
|
428
451
|
|
|
429
452
|
return true;
|
|
430
453
|
}
|
|
@@ -437,9 +460,9 @@ export function extensions(args) {
|
|
|
437
460
|
}
|
|
438
461
|
|
|
439
462
|
banner();
|
|
440
|
-
log(c.bold(
|
|
463
|
+
log(c.bold(` ${t("ext.bannerTitle")}\n`));
|
|
441
464
|
installDefaults()
|
|
442
|
-
log(`\n ${sym.info}
|
|
465
|
+
log(`\n ${sym.info} ${t("ext.footer", { list: c.lime("baryon extensions list"), remove: c.lime("baryon -- remove <src>") })}\n`)
|
|
443
466
|
return 0;
|
|
444
467
|
}
|
|
445
468
|
|
|
@@ -449,45 +472,46 @@ export function skills(args) {
|
|
|
449
472
|
banner();
|
|
450
473
|
|
|
451
474
|
if (sub === "list" || sub === "ls") {
|
|
452
|
-
log(c.bold(
|
|
475
|
+
log(c.bold(` ${t("skills.bannerListTitle")}\n`));
|
|
453
476
|
for (const s of DEFAULT_SKILLS) {
|
|
454
477
|
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(
|
|
478
|
+
log(` ${here ? sym.ok : sym.info} ${c.lime(s.name)} — ${s.note} ${here ? "" : c.dim(t("skills.notInstalled"))}`);
|
|
456
479
|
}
|
|
457
|
-
log(`\n ${sym.info}
|
|
480
|
+
log(`\n ${sym.info} ${t("skills.listFooter", { cmd: c.lime("baryon skills"), dir: c.dim(PI_SKILLS_DIR) })}\n`);
|
|
458
481
|
return 0;
|
|
459
482
|
}
|
|
460
483
|
|
|
461
|
-
log(c.bold(
|
|
484
|
+
log(c.bold(` ${t("skills.bannerInstallTitle")}\n`));
|
|
462
485
|
installSkills();
|
|
463
|
-
log(`\n ${sym.info}
|
|
486
|
+
log(`\n ${sym.info} ${t("skills.installFooter", { call: c.lime("/skill pdf"), list: c.lime("baryon skills list") })}\n`);
|
|
464
487
|
return 0;
|
|
465
488
|
}
|
|
466
489
|
|
|
467
490
|
export function help() {
|
|
468
491
|
banner();
|
|
469
492
|
log(`${c.bold("USAGE")}
|
|
470
|
-
${c.lime("baryon")} ${c.dim("[options] [@files...] [messages...]")}
|
|
493
|
+
${c.lime("baryon")} ${c.dim("[options] [@files...] [messages...]")} ${t("help.usageDesc")}
|
|
471
494
|
|
|
472
495
|
${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")}
|
|
496
|
+
${c.lime("baryon setup")} ${t("help.cmd.setup")}
|
|
497
|
+
${c.lime("baryon keys")} ${t("help.cmd.keys")} ${c.dim(t("help.cmd.keysNote"))}
|
|
498
|
+
${c.lime("baryon config")} ${t("help.cmd.config")} ${c.dim(t("help.cmd.configNote"))}
|
|
499
|
+
${c.lime("baryon models")} ${t("help.cmd.models")}
|
|
500
|
+
${c.lime("baryon extensions")} ${t("help.cmd.extensions")} ${c.dim(t("help.cmd.extensionsNote"))}
|
|
501
|
+
${c.lime("baryon skills")} ${t("help.cmd.skills")} ${c.dim(t("help.cmd.skillsNote"))}
|
|
502
|
+
${c.lime("baryon doctor")} ${t("help.cmd.doctor")}
|
|
503
|
+
${c.lime("baryon update")} ${t("help.cmd.update")}
|
|
504
|
+
${c.lime("baryon help")} ${t("help.cmd.help")}
|
|
482
505
|
|
|
483
506
|
${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(
|
|
507
|
+
${c.dim("$")} baryon ${c.dim(t("help.ex.interactive"))}
|
|
508
|
+
${c.dim("$")} baryon -p "${t("help.ex.oneShotMsg")}" ${c.dim(t("help.ex.oneShot"))}
|
|
509
|
+
${c.dim("$")} baryon --provider openai ${c.dim(t("help.ex.switch"))}
|
|
510
|
+
${c.dim("$")} baryon --list-models ${c.dim(t("help.ex.passthrough"))}
|
|
511
|
+
|
|
512
|
+
${c.dim(t("help.lang", { env: "BARYON_LANG", cmd: "baryon config --lang" }))}
|
|
513
|
+
${c.dim(t("help.passthrough"))}
|
|
514
|
+
${c.dim(t("help.docs", { homepage: HOMEPAGE, email: SUPPORT_EMAIL }))}
|
|
491
515
|
`);
|
|
492
516
|
return 0;
|
|
493
517
|
}
|
|
@@ -495,8 +519,8 @@ ${c.dim(`문서: ${HOMEPAGE} · 문의: ${SUPPORT_EMAIL}`)}
|
|
|
495
519
|
/** Quiet first-run hint shown by postinstall (never fails the install). */
|
|
496
520
|
export function welcome() {
|
|
497
521
|
if (!process.stdout.isTTY) return 0;
|
|
498
|
-
log(`\n${c.lime("✔")} ${c.bold("@baryonlabs/cli")}
|
|
499
|
-
log(` ${c.dim("
|
|
522
|
+
log(`\n${c.lime("✔")} ${t("welcome.installed", { pkg: c.bold("@baryonlabs/cli") })}`);
|
|
523
|
+
log(` ${c.dim(t("welcome.nextLabel"))} ${c.lime("baryon setup")} ${c.dim("→")} ${c.lime("baryon")}`);
|
|
500
524
|
log(` ${c.dim(HOMEPAGE)}\n`);
|
|
501
525
|
return 0;
|
|
502
526
|
}
|
package/src/i18n.js
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
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
|
+
"edge.notInstalled": "Baryon Edge(엔터프라이즈) 미설치 — 읽기전용 데이터 샌드박스:",
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
en: {
|
|
192
|
+
// ── setup ────────────────────────────────────────────────────────────
|
|
193
|
+
"setup.title": "baryon.ai connection setup",
|
|
194
|
+
"setup.keyHint": "Issue / manage keys: {url}",
|
|
195
|
+
"setup.keyHintSub": " (issue/revoke at the vibecamp.us dashboard · format {prefix}…)",
|
|
196
|
+
"setup.keyPrompt": "baryon.ai API key: ",
|
|
197
|
+
"setup.noKey": "Saving without an API key. Add one later with `baryon setup --key <KEY>`.",
|
|
198
|
+
"setup.badKeyFormat": "Key does not match {prefix}… — ignore this if it's a local/commercial key.",
|
|
199
|
+
"setup.configSaved": "config saved → {file}",
|
|
200
|
+
"setup.discovering": "Fetching model list…",
|
|
201
|
+
"setup.modelsFound": "Found {count} models ({list}{more})",
|
|
202
|
+
"setup.modelsFailed": "Model auto-discovery failed — using {count} default models (normal when offline/air-gapped)",
|
|
203
|
+
"setup.providerConfigured": "pi provider {provider} configured → {file}",
|
|
204
|
+
"setup.skipExtensions": "Skipping default extensions (--no-extensions)",
|
|
205
|
+
"setup.skipSkills": "Skipping default skills (--no-skills)",
|
|
206
|
+
"setup.skipBrowser": "Skipping agent-browser (--no-browser)",
|
|
207
|
+
"setup.done": "All set. Start with {cmd}.",
|
|
208
|
+
|
|
209
|
+
// ── doctor ───────────────────────────────────────────────────────────
|
|
210
|
+
"doctor.title": "Diagnostics (baryon doctor)",
|
|
211
|
+
"doctor.node": "Node.js {version}",
|
|
212
|
+
"doctor.nodeOld": "Node.js {version} — 22 or newer required",
|
|
213
|
+
"doctor.piInstalled": "{pkg} installed",
|
|
214
|
+
"doctor.piMissing": "{pkg} not installed — npm install -g @baryonlabs/cli",
|
|
215
|
+
"doctor.configFound": "config found → {file}",
|
|
216
|
+
"doctor.configMissing": "config missing — run `baryon setup`",
|
|
217
|
+
"doctor.apiKeySet": "API key set ({masked})",
|
|
218
|
+
"doctor.apiKeyMissing": "No API key",
|
|
219
|
+
"doctor.cliOutdated": "CLI outdated {current} — latest {latest}. Update required to use baryon.ai (`baryon update`)",
|
|
220
|
+
"doctor.cliCurrent": "CLI up to date ({current})",
|
|
221
|
+
"doctor.providerRegistered": "pi provider {provider} registered → {file}",
|
|
222
|
+
"doctor.providerMissing": "pi provider not registered — run `baryon setup`",
|
|
223
|
+
"doctor.skillsAll": "Default skills {have}/{total} installed (pdf·pptx·xlsx·agent-browser)",
|
|
224
|
+
"doctor.skillsSome": "Default skills {have}/{total} — install with `baryon skills`",
|
|
225
|
+
"doctor.browserInstalled": "agent-browser installed ({version})",
|
|
226
|
+
"doctor.browserMissing": "agent-browser not installed — `baryon setup` (auto) or `npm i -g agent-browser`",
|
|
227
|
+
"doctor.checkingConn": "Checking connection → {url}",
|
|
228
|
+
"doctor.connOk": "baryon.ai reachable (HTTP {status})",
|
|
229
|
+
"doctor.connStatus": "Endpoint returned HTTP {status} — check key/permissions",
|
|
230
|
+
"doctor.connFail": "Cannot connect ({error}) — a local LLM works if you're offline",
|
|
231
|
+
"doctor.allPass": "All checks passed",
|
|
232
|
+
"doctor.problems": "{count} item(s) need attention",
|
|
233
|
+
|
|
234
|
+
// ── config ───────────────────────────────────────────────────────────
|
|
235
|
+
"config.updated": "config updated",
|
|
236
|
+
"config.title": "Current settings",
|
|
237
|
+
"config.baseUrl": "base URL {url}",
|
|
238
|
+
"config.default": "default {model}",
|
|
239
|
+
"config.apiKey": "API key {masked}",
|
|
240
|
+
"config.apiKeyNone": "(none)",
|
|
241
|
+
"config.lang": "language {lang}",
|
|
242
|
+
"config.keysMgmt": "key mgmt {url}",
|
|
243
|
+
"config.file": "config file {file}",
|
|
244
|
+
"config.piModels": "pi models {file}",
|
|
245
|
+
|
|
246
|
+
// ── keys ─────────────────────────────────────────────────────────────
|
|
247
|
+
"keys.title": "Issue / manage keys (vibecamp.us dashboard):",
|
|
248
|
+
"keys.sub": " issuance/revocation/quota managed by vibecamp.us · format {prefix}…",
|
|
249
|
+
"keys.after": " after issuing:",
|
|
250
|
+
"keys.or": "or",
|
|
251
|
+
|
|
252
|
+
// ── update ───────────────────────────────────────────────────────────
|
|
253
|
+
"update.stage1": "1/2 update CLI & core: {cmd}",
|
|
254
|
+
"update.npmFail": "npm failed — run the command above manually.",
|
|
255
|
+
"update.stage2": "2/2 update pi packages: {cmd}",
|
|
256
|
+
"update.done": "Update complete. {hint}",
|
|
257
|
+
"update.doneHint": "run baryon doctor to verify",
|
|
258
|
+
|
|
259
|
+
// ── extensions install ───────────────────────────────────────────────
|
|
260
|
+
"ext.piMissing": "{pkg} not installed — skipping extensions",
|
|
261
|
+
"ext.pruned": "Removed conflicting extensions: {names} (self-heal)",
|
|
262
|
+
"ext.installing": "Installing default extensions ({count} · git clone, may take a moment)…",
|
|
263
|
+
"ext.itemOk": "{name} — {note}",
|
|
264
|
+
"ext.itemFail": "{name} install failed (check network/git) — skipped",
|
|
265
|
+
"ext.summary": "Extensions {ok}/{total} installed",
|
|
266
|
+
"ext.bannerTitle": "Baryon default extensions",
|
|
267
|
+
"ext.footer": "list: {list} · remove: {remove}",
|
|
268
|
+
|
|
269
|
+
// ── skills install ───────────────────────────────────────────────────
|
|
270
|
+
"skills.alreadyAll": "Default skills {total}/{total} (already installed)",
|
|
271
|
+
"skills.installing": "Installing default skills ({count})…",
|
|
272
|
+
"skills.noSkillMd": "{name} — no SKILL.md ({dir}), skipped",
|
|
273
|
+
"skills.itemOk": "skill: {name} — {note}",
|
|
274
|
+
"skills.itemFail": "{name} skill install failed — skipped ({error})",
|
|
275
|
+
"skills.cloneFail": "Skill repo clone failed (check network/git) — some skills skipped",
|
|
276
|
+
"skills.summary": "Default skills {ok}/{total} installed → {dir}",
|
|
277
|
+
"skills.bannerListTitle": "Baryon default skills pack",
|
|
278
|
+
"skills.notInstalled": "(not installed)",
|
|
279
|
+
"skills.listFooter": "install/sync: {cmd} · location: {dir}",
|
|
280
|
+
"skills.bannerInstallTitle": "Baryon default skills install",
|
|
281
|
+
"skills.installFooter": "use: invoke like {call} in the pi agent · list: {list}",
|
|
282
|
+
|
|
283
|
+
// ── browser install ──────────────────────────────────────────────────
|
|
284
|
+
"browser.installed": "agent-browser installed ({version})",
|
|
285
|
+
"browser.installing": "Installing agent-browser (web/ERP automation · first run, includes browser download)…",
|
|
286
|
+
"browser.installFail": "agent-browser install failed (check network/npm) — skipped. Later: `npm i -g agent-browser && agent-browser install`",
|
|
287
|
+
"browser.ready": "agent-browser — web/ERP browser automation ready",
|
|
288
|
+
"browser.engineMissing": "agent-browser binary installed · browser download incomplete — on first use run `agent-browser install`",
|
|
289
|
+
|
|
290
|
+
// ── help ─────────────────────────────────────────────────────────────
|
|
291
|
+
"help.usageDesc": "Start the coding agent (baryon.ai by default)",
|
|
292
|
+
"help.cmd.setup": "Register baryon.ai API key + configure pi provider",
|
|
293
|
+
"help.cmd.keys": "Open the key issuance/management dashboard",
|
|
294
|
+
"help.cmd.keysNote": "(vibecamp.us)",
|
|
295
|
+
"help.cmd.config": "Show current settings",
|
|
296
|
+
"help.cmd.configNote": "(change with --key/--base-url/--model/--lang)",
|
|
297
|
+
"help.cmd.models": "List available models",
|
|
298
|
+
"help.cmd.extensions": "Install default extensions (sub-agents·canvas·shell·web)",
|
|
299
|
+
"help.cmd.extensionsNote": "· list to view",
|
|
300
|
+
"help.cmd.skills": "Install default skills (pdf·pptx·xlsx)",
|
|
301
|
+
"help.cmd.skillsNote": "· list to view",
|
|
302
|
+
"help.cmd.doctor": "Diagnose install & connectivity",
|
|
303
|
+
"help.cmd.update": "Update CLI + pi agent",
|
|
304
|
+
"help.cmd.help": "This help",
|
|
305
|
+
"help.ex.interactive": "# interactive start",
|
|
306
|
+
"help.ex.oneShot": "# one-shot run",
|
|
307
|
+
"help.ex.oneShotMsg": "analyze the CSV and make a chart",
|
|
308
|
+
"help.ex.switch": "# switch/compare other models",
|
|
309
|
+
"help.ex.passthrough": "# pi passthrough",
|
|
310
|
+
"help.lang": "Language: env var {env} or {cmd} (ko·en)",
|
|
311
|
+
"help.passthrough": "All other options are passed straight through to the pi agent.",
|
|
312
|
+
"help.docs": "Docs: {homepage} · Support: {email}",
|
|
313
|
+
|
|
314
|
+
// ── welcome (postinstall) ────────────────────────────────────────────
|
|
315
|
+
"welcome.installed": "{pkg} installed",
|
|
316
|
+
"welcome.nextLabel": "Next:",
|
|
317
|
+
|
|
318
|
+
// ── runtime / bin ────────────────────────────────────────────────────
|
|
319
|
+
"bin.outdated": "Update required: @baryonlabs/cli {current} → {latest}",
|
|
320
|
+
"bin.outdatedSub": "baryon.ai requires the latest version.",
|
|
321
|
+
"bin.outdatedRun": "to update.",
|
|
322
|
+
"pi.notInstalled": "{pkg} is not installed. Run: npm install -g @baryonlabs/cli",
|
|
323
|
+
"bin.piVersion": "pi {version}",
|
|
324
|
+
"bin.unconfiguredTTY": "Not configured yet.",
|
|
325
|
+
"bin.unconfiguredTTYRun": "will run first.",
|
|
326
|
+
"bin.unconfigured": "No configuration found.",
|
|
327
|
+
"bin.unconfiguredRun": "first.",
|
|
328
|
+
"bin.prunedConflicts": "Cleaned up conflicting extensions: {names}",
|
|
329
|
+
"bin.room": "🏫 {project} · seat {seat}",
|
|
330
|
+
"bin.roomInactive": "🚫 {project} (inactive) · seat {seat}",
|
|
331
|
+
"edge.notInstalled": "Baryon Edge (Enterprise) not installed — read-only data sandbox:",
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
/** Interpolate {name}-style placeholders from `vars`. Missing → left as-is. */
|
|
336
|
+
function interpolate(str, vars) {
|
|
337
|
+
return str.replace(/\{(\w+)\}/g, (m, k) =>
|
|
338
|
+
Object.prototype.hasOwnProperty.call(vars, k) ? String(vars[k]) : m,
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Look up `key` for the active locale, interpolate `vars`, and fall back to
|
|
344
|
+
* Korean (then to the key string itself) if missing. Never throws.
|
|
345
|
+
*/
|
|
346
|
+
export function t(key, vars = {}) {
|
|
347
|
+
let locale;
|
|
348
|
+
try {
|
|
349
|
+
locale = getLocale();
|
|
350
|
+
} catch {
|
|
351
|
+
locale = "ko";
|
|
352
|
+
}
|
|
353
|
+
const fromLocale = MESSAGES[locale]?.[key];
|
|
354
|
+
const fromKo = MESSAGES.ko[key];
|
|
355
|
+
const template = fromLocale != null ? fromLocale : fromKo != null ? fromKo : key;
|
|
356
|
+
try {
|
|
357
|
+
return interpolate(template, vars || {});
|
|
358
|
+
} catch {
|
|
359
|
+
return template;
|
|
360
|
+
}
|
|
361
|
+
}
|
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];
|