@volc-emr/emr-cli 0.1.0-beta.0 → 0.1.0-beta.1

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.
@@ -3,16 +3,27 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Agent = void 0;
4
4
  const planner_1 = require("./planner");
5
5
  const executor_1 = require("./executor");
6
+ const logger_1 = require("../runtime/logger");
6
7
  class Agent {
7
8
  constructor(ctx) {
8
9
  this.ctx = ctx;
9
10
  }
10
11
  async run(task, options = {}) {
12
+ logger_1.ui.section(`Task`);
13
+ logger_1.ui.info(task);
11
14
  const plan = await (0, planner_1.planTask)(task);
12
- console.log("\nšŸ“‹ Plan:");
13
- console.log(plan);
14
- if (options.dryRun)
15
+ logger_1.ui.section(`Plan (${plan.length} step${plan.length > 1 ? "s" : ""})`);
16
+ plan.forEach((step, i) => {
17
+ logger_1.ui.raw(` ${i + 1}. ${step.tool}`);
18
+ if (step.input && Object.keys(step.input).length > 0) {
19
+ logger_1.ui.dim(` ${JSON.stringify(step.input)}`);
20
+ }
21
+ });
22
+ if (options.dryRun) {
23
+ logger_1.ui.divider();
24
+ logger_1.ui.info("dry-run mode: no Tool will be executed");
15
25
  return;
26
+ }
16
27
  await (0, executor_1.executePlan)(plan, this.ctx, { autoApprove: options.autoApprove });
17
28
  }
18
29
  }
@@ -5,21 +5,32 @@ const registry_1 = require("../tools/registry");
5
5
  const confirm_1 = require("../runtime/confirm");
6
6
  const logger_1 = require("../runtime/logger");
7
7
  async function executePlan(plan, ctx, options = {}) {
8
+ logger_1.ui.section(`Execute (${plan.length} step${plan.length > 1 ? "s" : ""})`);
8
9
  for (const [i, step] of plan.entries()) {
9
10
  const tool = registry_1.toolList.find((t) => t.name === step.tool);
10
- if (!tool)
11
+ if (!tool) {
12
+ (0, logger_1.logStep)(i, "fail", step.tool, { error: "Tool not found" });
11
13
  throw new Error(`Tool not found: ${step.tool}`);
14
+ }
12
15
  if (tool.riskLevel === "high") {
13
16
  const ok = options.autoApprove
14
17
  ? true
15
- : await (0, confirm_1.confirm)(`āš ļø ę‰§č”Œ ${tool.name} (input=${JSON.stringify(step.input)})?`);
18
+ : await (0, confirm_1.confirm)(`⚠ ę‰§č”Œé«˜é£Žé™© Tool: ${tool.name} ${JSON.stringify(step.input)}`);
16
19
  if (!ok) {
17
- (0, logger_1.logStep)(i, `Skipped ${tool.name}`);
20
+ (0, logger_1.logStep)(i, "skip", tool.name, { reason: "user cancelled" });
18
21
  continue;
19
22
  }
20
23
  }
21
- (0, logger_1.logStep)(i, `Running ${tool.name}`, step.input);
22
- const result = await tool.execute(step.input, ctx);
23
- (0, logger_1.logStep)(i, `Done ${tool.name}`, result);
24
+ (0, logger_1.logStep)(i, "run", tool.name, { input: step.input });
25
+ try {
26
+ const result = await tool.execute(step.input, ctx);
27
+ (0, logger_1.logStep)(i, "done", tool.name, { output: result });
28
+ }
29
+ catch (err) {
30
+ (0, logger_1.logStep)(i, "fail", tool.name, { error: err?.message || String(err) });
31
+ throw err;
32
+ }
24
33
  }
34
+ logger_1.ui.divider();
35
+ logger_1.ui.success("Execute finished");
25
36
  }
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ const registry_1 = require("./tools/registry");
7
7
  const memory_1 = require("./runtime/memory");
8
8
  const config_1 = require("./runtime/config");
9
9
  const confirm_1 = require("./runtime/confirm");
10
+ const logger_1 = require("./runtime/logger");
10
11
  const program = new commander_1.Command();
11
12
  program
12
13
  .name("volc-emr-agent")
@@ -25,15 +26,23 @@ program
25
26
  process.env.VOLC_SECRETKEY = opts.secretKey;
26
27
  if (opts.region)
27
28
  process.env.VOLC_REGION = opts.region;
28
- (0, config_1.resolveCredentials)();
29
- const agent = new agent_1.Agent({
30
- api: registry_1.apiRegistry,
31
- memory: memory_1.memory
32
- });
33
- await agent.run(task, {
34
- dryRun: opts.dryRun,
35
- autoApprove: opts.yes
36
- });
29
+ try {
30
+ const creds = (0, config_1.resolveCredentials)();
31
+ const cfg = (0, config_1.readLocalConfig)();
32
+ logger_1.ui.dim(`region=${creds.region} llm=${cfg.llm?.endpoint ? "configured" : "not configured"}`);
33
+ const agent = new agent_1.Agent({
34
+ api: registry_1.apiRegistry,
35
+ memory: memory_1.memory
36
+ });
37
+ await agent.run(task, {
38
+ dryRun: opts.dryRun,
39
+ autoApprove: opts.yes
40
+ });
41
+ }
42
+ catch (err) {
43
+ logger_1.ui.error(err?.message || String(err));
44
+ process.exitCode = 1;
45
+ }
37
46
  });
38
47
  program
39
48
  .command("init")
@@ -49,10 +58,10 @@ program
49
58
  const existing = (0, config_1.readLocalConfig)();
50
59
  const hasExisting = !!(existing.accessKey || existing.secretKey);
51
60
  if (hasExisting && !opts.force) {
52
- console.log(`Detected existing config: ${(0, config_1.configFilePath)()}`);
61
+ logger_1.ui.info(`Detected existing config: ${(0, config_1.configFilePath)()}`);
53
62
  const ok = await (0, confirm_1.confirm)("Overwrite existing credentials?");
54
63
  if (!ok) {
55
- console.log("Cancelled. No changes made.");
64
+ logger_1.ui.warn("Cancelled. No changes made.");
56
65
  return;
57
66
  }
58
67
  }
@@ -64,14 +73,14 @@ program
64
73
  defaultValue: existing.accessKey
65
74
  }));
66
75
  if (!accessKey) {
67
- console.error("Access key is required.");
76
+ logger_1.ui.error("Access key is required.");
68
77
  process.exitCode = 1;
69
78
  return;
70
79
  }
71
80
  const secretKey = opts.secretKey ||
72
81
  (await session.ask("VOLC Secret Key", { silent: true }));
73
82
  if (!secretKey) {
74
- console.error("Secret key is required.");
83
+ logger_1.ui.error("Secret key is required.");
75
84
  process.exitCode = 1;
76
85
  return;
77
86
  }
@@ -109,20 +118,21 @@ program
109
118
  };
110
119
  }
111
120
  const file = (0, config_1.writeLocalConfig)(payload);
112
- console.log(`\nāœ“ Saved to ${file}`);
113
- console.log({
114
- accessKey: `${accessKey.slice(0, 4)}****`,
115
- secretKey: "********",
116
- region,
117
- llm: llmEndpoint
118
- ? {
119
- endpoint: llmEndpoint,
120
- apiKey: payload.llm.apiKey ? "********" : undefined,
121
- model: payload.llm.model || undefined
122
- }
123
- : "(not configured)"
124
- });
125
- console.log("\nTip: run `volc-emr-agent run \"åˆ—å‡ŗé›†ē¾¤\"` to verify.");
121
+ logger_1.ui.success(`Saved to ${file}`);
122
+ logger_1.ui.kv("accessKey", `${accessKey.slice(0, 4)}****`);
123
+ logger_1.ui.kv("secretKey", "********");
124
+ logger_1.ui.kv("region", region);
125
+ if (llmEndpoint) {
126
+ logger_1.ui.kv("llm.endpoint", llmEndpoint);
127
+ if (payload.llm.apiKey)
128
+ logger_1.ui.kv("llm.apiKey", "********");
129
+ if (payload.llm.model)
130
+ logger_1.ui.kv("llm.model", payload.llm.model);
131
+ }
132
+ else {
133
+ logger_1.ui.kv("llm", "(not configured)");
134
+ }
135
+ logger_1.ui.dim(`Tip: run \`volc-emr-agent run "åˆ—å‡ŗé›†ē¾¤"\` to verify.`);
126
136
  }
127
137
  finally {
128
138
  session?.close();
@@ -141,7 +151,7 @@ config
141
151
  secretKey: opts.secretKey,
142
152
  region: opts.region
143
153
  });
144
- console.log(`Saved: ${file}`);
154
+ logger_1.ui.success(`Credentials saved: ${file}`);
145
155
  });
146
156
  config
147
157
  .command("set-llm")
@@ -157,26 +167,25 @@ config
157
167
  model: opts.model
158
168
  }
159
169
  });
160
- console.log(`Saved LLM config: ${file}`);
170
+ logger_1.ui.success(`LLM config saved: ${file}`);
161
171
  });
162
172
  config
163
173
  .command("show")
164
174
  .description("Show current local config (secrets are masked)")
165
175
  .action(() => {
166
176
  const cfg = (0, config_1.readLocalConfig)();
167
- const masked = {
168
- ...cfg,
169
- accessKey: cfg.accessKey ? `${cfg.accessKey.slice(0, 4)}****` : undefined,
170
- secretKey: cfg.secretKey ? "********" : undefined,
171
- llm: cfg.llm
172
- ? {
173
- endpoint: cfg.llm.endpoint,
174
- apiKey: cfg.llm.apiKey ? "********" : undefined,
175
- model: cfg.llm.model
176
- }
177
- : undefined
178
- };
179
- console.log("file:", (0, config_1.configFilePath)());
180
- console.log(masked);
177
+ logger_1.ui.section("Local config");
178
+ logger_1.ui.kv("file", (0, config_1.configFilePath)());
179
+ logger_1.ui.kv("accessKey", cfg.accessKey ? `${cfg.accessKey.slice(0, 4)}****` : "(missing)");
180
+ logger_1.ui.kv("secretKey", cfg.secretKey ? "********" : "(missing)");
181
+ logger_1.ui.kv("region", cfg.region || "(missing)");
182
+ if (cfg.llm?.endpoint) {
183
+ logger_1.ui.kv("llm.endpoint", cfg.llm.endpoint);
184
+ logger_1.ui.kv("llm.apiKey", cfg.llm.apiKey ? "********" : "(missing)");
185
+ logger_1.ui.kv("llm.model", cfg.llm.model || "(missing)");
186
+ }
187
+ else {
188
+ logger_1.ui.kv("llm", "(not configured)");
189
+ }
181
190
  });
182
191
  program.parse();
@@ -1,8 +1,122 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ui = void 0;
3
4
  exports.logStep = logStep;
4
- function logStep(i, msg, data) {
5
- console.log(`Step ${i + 1}: ${msg}`);
6
- if (data)
7
- console.log(" ↳", data);
5
+ const useColor = process.stdout.isTTY && process.env.NO_COLOR === undefined && process.env.TERM !== "dumb";
6
+ const c = (code) => (s) => (useColor ? `\x1b[${code}m${s}\x1b[0m` : s);
7
+ const color = {
8
+ gray: c("90"),
9
+ red: c("31"),
10
+ green: c("32"),
11
+ yellow: c("33"),
12
+ blue: c("34"),
13
+ magenta: c("35"),
14
+ cyan: c("36"),
15
+ bold: c("1"),
16
+ dim: c("2")
17
+ };
18
+ const SYM = {
19
+ info: "ℹ",
20
+ success: "āœ”",
21
+ warn: "⚠",
22
+ error: "✘",
23
+ skip: "⊘",
24
+ arrow: "→",
25
+ bullet: "•"
26
+ };
27
+ function write(line) {
28
+ process.stdout.write(line.endsWith("\n") ? line : line + "\n");
29
+ }
30
+ function formatInline(val) {
31
+ if (val === undefined)
32
+ return "";
33
+ if (typeof val === "string")
34
+ return val;
35
+ try {
36
+ return JSON.stringify(val);
37
+ }
38
+ catch {
39
+ return String(val);
40
+ }
41
+ }
42
+ function formatFull(val) {
43
+ if (val === undefined)
44
+ return "";
45
+ if (typeof val === "string")
46
+ return val;
47
+ try {
48
+ return JSON.stringify(val, null, 2);
49
+ }
50
+ catch {
51
+ return String(val);
52
+ }
53
+ }
54
+ exports.ui = {
55
+ info(msg) {
56
+ write(`${color.cyan(SYM.info)} ${msg}`);
57
+ },
58
+ success(msg) {
59
+ write(`${color.green(SYM.success)} ${msg}`);
60
+ },
61
+ warn(msg) {
62
+ write(`${color.yellow(SYM.warn)} ${msg}`);
63
+ },
64
+ error(msg) {
65
+ write(`${color.red(SYM.error)} ${msg}`);
66
+ },
67
+ skip(msg) {
68
+ write(`${color.yellow(SYM.skip)} ${msg}`);
69
+ },
70
+ dim(msg) {
71
+ write(color.dim(msg));
72
+ },
73
+ kv(key, value) {
74
+ write(` ${color.gray(key + ":")} ${formatInline(value)}`);
75
+ },
76
+ section(title) {
77
+ write("");
78
+ write(color.bold(title));
79
+ },
80
+ divider() {
81
+ write(color.dim("─".repeat(48)));
82
+ },
83
+ raw(msg) {
84
+ write(msg);
85
+ },
86
+ json(value) {
87
+ write(typeof value === "string" ? value : JSON.stringify(value, null, 2));
88
+ }
89
+ };
90
+ function logStep(i, status, toolName, extra) {
91
+ const idx = color.gray(`[${i + 1}]`);
92
+ if (status === "run") {
93
+ const suffix = extra?.input ? color.dim(` ${formatInline(extra.input)}`) : "";
94
+ write(`${idx} ${color.blue(SYM.arrow)} ${color.bold(toolName)}${suffix}`);
95
+ return;
96
+ }
97
+ if (status === "done") {
98
+ write(`${idx} ${color.green(SYM.success)} ${toolName}`);
99
+ if (extra?.output !== undefined) {
100
+ const out = extra.output;
101
+ if (out && typeof out === "object" && out.Skipped) {
102
+ exports.ui.kv("skipped", out.Reason || "true");
103
+ if (out.Message)
104
+ exports.ui.kv("message", out.Message);
105
+ }
106
+ else {
107
+ write(color.dim(formatFull(extra.output)));
108
+ }
109
+ }
110
+ return;
111
+ }
112
+ if (status === "skip") {
113
+ const reason = extra?.reason ? ` (${extra.reason})` : "";
114
+ write(`${idx} ${color.yellow(SYM.skip)} ${toolName}${color.dim(reason)}`);
115
+ return;
116
+ }
117
+ if (status === "fail") {
118
+ write(`${idx} ${color.red(SYM.error)} ${toolName}`);
119
+ if (extra?.error)
120
+ exports.ui.kv("error", extra.error);
121
+ }
8
122
  }
@@ -64,7 +64,6 @@ async function listClusters(params = {}) {
64
64
  MaxResults: params.MaxResults,
65
65
  NextToken: params.NextToken
66
66
  });
67
- console.log(body);
68
67
  const result = await (0, volcApi_1.callEmr)("ListClusters", body);
69
68
  return {
70
69
  Items: Array.isArray(result?.Items) ? result.Items : [],
@@ -147,8 +146,6 @@ async function releaseCluster(params) {
147
146
  }
148
147
  async function createCluster(params) {
149
148
  const body = compactBody({ ...params });
150
- console.log("createCluster params:", params);
151
- console.log(body);
152
149
  const resp = await (0, volcApi_1.callEmr)("CreateCluster", body);
153
150
  return {
154
151
  ClusterId: resp?.ClusterId || "",
@@ -169,7 +166,6 @@ async function findClustersToCleanup({ olderThanDays = 7, states } = {}) {
169
166
  ClusterStates: targetStates,
170
167
  CreateTimeBefore: threshold
171
168
  });
172
- console.log(items);
173
169
  return items;
174
170
  }
175
171
  exports.emrApi = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volc-emr/emr-cli",
3
- "version": "0.1.0-beta.0",
3
+ "version": "0.1.0-beta.1",
4
4
  "description": "Minimal controllable CLI Agent for Volcengine EMR OpenAPI: Tool-first + Plan/Execute with LLM-driven planner.",
5
5
  "keywords": [
6
6
  "volcengine",