@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.
- package/dist/agent/agent.js +14 -3
- package/dist/agent/executor.js +17 -6
- package/dist/index.js +52 -43
- package/dist/runtime/logger.js +118 -4
- package/dist/services/emrApi.js +0 -4
- package/package.json +1 -1
package/dist/agent/agent.js
CHANGED
|
@@ -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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
}
|
package/dist/agent/executor.js
CHANGED
|
@@ -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)(
|
|
18
|
+
: await (0, confirm_1.confirm)(`ā ę§č”é«é£é© Tool: ${tool.name} ${JSON.stringify(step.input)}`);
|
|
16
19
|
if (!ok) {
|
|
17
|
-
(0, logger_1.logStep)(i,
|
|
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,
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
llm
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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();
|
package/dist/runtime/logger.js
CHANGED
|
@@ -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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
}
|
package/dist/services/emrApi.js
CHANGED
|
@@ -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