@agent-smith/cli 0.0.104 → 0.0.106

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/cli.js CHANGED
@@ -1,13 +1,16 @@
1
1
  import { input } from '@inquirer/prompts';
2
2
  import { chat } from './cmd/cmds.js';
3
3
  import { isChatMode } from './state/state.js';
4
+ import { Agent } from '@agent-smith/agent';
5
+ import { backend } from './state/backends.js';
4
6
  async function query(program) {
5
7
  const data = { message: "$", default: "" };
6
8
  const q = await input(data);
7
9
  const args = q.split(" ");
8
10
  await program.parseAsync(args, { from: "user" });
9
11
  if (isChatMode.value) {
10
- await chat(program, {});
12
+ const agent = new Agent(backend.value, "chat");
13
+ await chat(program, {}, agent, []);
11
14
  }
12
15
  await query(program);
13
16
  }
@@ -4,7 +4,6 @@ import YAML from 'yaml';
4
4
  import { cacheFilePath, dbPath } from "../../conf.js";
5
5
  import { readFeaturePaths, readFeaturesType, readTaskSetting } from "../../db/read.js";
6
6
  import { cleanupFeaturePaths, deleteTaskSetting, updateAliases, updateFeatures, upsertTaskSettings } from "../../db/write.js";
7
- import { isCacheReady, cmds } from "../../state/auto/usercmds.js";
8
7
  import { getFeatureSpec, readFeaturesDirs } from "../../state/features.js";
9
8
  import { readPluginsPaths } from "../../state/plugins.js";
10
9
  import { runMode } from "../../state/state.js";
@@ -15,18 +14,15 @@ import { readTask } from "../sys/read_task.js";
15
14
  import { updateUserCmdsCache } from './cache.js';
16
15
  async function initUserCmds(cmdFeats) {
17
16
  const features = Object.values(cmdFeats);
18
- let endCmds = cmds;
19
- if (!isCacheReady) {
20
- updateUserCmdsCache(cacheFilePath, features);
21
- const usrCmds = [];
22
- for (const feat of features) {
23
- const cmdPath = path.join(feat.path, feat.name + "." + feat.ext);
24
- const c = await readCmd(feat.name, cmdPath);
17
+ const usrCmds = [];
18
+ for (const feat of features) {
19
+ const cmdPath = path.join(feat.path, feat.name + "." + feat.ext);
20
+ const c = await readCmd(feat.name, cmdPath);
21
+ if (c) {
25
22
  usrCmds.push(c);
26
23
  }
27
- endCmds = usrCmds;
28
24
  }
29
- return endCmds;
25
+ return usrCmds;
30
26
  }
31
27
  async function resetDbCmd() {
32
28
  if (runMode.value == "cli") {
@@ -1,7 +1,9 @@
1
1
  import { InferenceOptions } from "@locallm/types/dist/inference.js";
2
2
  import { Command } from "commander";
3
+ import type { McpClient } from "../main.js";
4
+ import type { Agent } from "@agent-smith/agent";
3
5
  declare const program: Command;
4
- declare function chat(program: Command, options: InferenceOptions): Promise<void>;
6
+ declare function chat(program: Command, options: InferenceOptions, agent: Agent, mcpServers: Array<McpClient>): Promise<void>;
5
7
  declare function buildCmds(): Promise<Command>;
6
8
  declare function parseCmd(program: Command): Promise<void>;
7
9
  export { buildCmds, chat, parseCmd, program };
package/dist/cmd/cmds.js CHANGED
@@ -3,12 +3,12 @@ import { Command } from "commander";
3
3
  import { query } from "../cli.js";
4
4
  import { readAliases, readFeatures } from "../db/read.js";
5
5
  import { chatInferenceParams, chatTemplate } from "../state/chat.js";
6
- import { agent, isChatMode, runMode } from "../state/state.js";
6
+ import { isChatMode, runMode } from "../state/state.js";
7
7
  import { initCommandsFromAliases } from "./clicmds/aliases.js";
8
8
  import { initBaseCommands } from "./clicmds/base.js";
9
9
  import { initUserCmds } from "./clicmds/cmds.js";
10
10
  const program = new Command();
11
- async function chat(program, options) {
11
+ async function chat(program, options, agent, mcpServers) {
12
12
  const data = { message: '>', default: "" };
13
13
  const prompt = await input(data);
14
14
  if (prompt == "/q") {
@@ -17,12 +17,13 @@ async function chat(program, options) {
17
17
  process.exit(0);
18
18
  }
19
19
  else {
20
+ mcpServers.forEach(async (s) => await s.stop());
20
21
  await query(program);
21
22
  }
22
23
  }
23
24
  await agent.run(prompt, chatInferenceParams, options, chatTemplate ? chatTemplate : undefined);
24
25
  console.log();
25
- await chat(program, options);
26
+ await chat(program, options, agent, mcpServers);
26
27
  }
27
28
  async function buildCmds() {
28
29
  initBaseCommands(program);
@@ -117,6 +117,7 @@ function pythonAction(path) {
117
117
  final = JSON.parse(txt);
118
118
  }
119
119
  catch (e) {
120
+ console.warn("Can not parse json from python action", path, e);
120
121
  }
121
122
  }
122
123
  return final;
@@ -5,7 +5,7 @@ import ora from 'ora';
5
5
  import { usePerfTimer } from "../../../main.js";
6
6
  import { backend, backends, listBackends } from "../../../state/backends.js";
7
7
  import { setChatInferenceParams, setChatTemplate } from "../../../state/chat.js";
8
- import { agent, isChatMode } from "../../../state/state.js";
8
+ import { isChatMode } from "../../../state/state.js";
9
9
  import { initTaskSettings, isTaskSettingsInitialized, tasksSettings } from "../../../state/tasks.js";
10
10
  import { chat, program } from "../../cmds.js";
11
11
  import { parseCommandArgs } from "../options_parsers.js";
@@ -13,10 +13,12 @@ import { runtimeDataError, runtimeError, runtimeWarning } from "../user_msgs.js"
13
13
  import { processOutput } from "../utils.js";
14
14
  import { readTask } from "./read.js";
15
15
  import { getTaskPrompt } from "./utils.js";
16
+ import { Agent } from "@agent-smith/agent";
16
17
  async function executeTask(name, payload, options) {
17
18
  if (!isTaskSettingsInitialized.value) {
18
19
  initTaskSettings();
19
20
  }
21
+ const agent = new Agent(backend.value, name);
20
22
  const hasSettings = Object.keys(tasksSettings).includes(name);
21
23
  let settings = {};
22
24
  if (hasSettings) {
@@ -35,9 +37,20 @@ async function executeTask(name, payload, options) {
35
37
  agent.lm = backends[settings.backend];
36
38
  }
37
39
  if (options?.debug || options?.backend) {
38
- console.log("Agent:", colors.bold(agent.lm.name), "( " + agent.lm.providerType + " backend type)");
40
+ console.log("Agent:", colors.bold(agent.name), "( " + agent.lm.providerType + " backend type)");
39
41
  }
40
42
  const { task, model, conf, vars, mcpServers, taskDir } = await readTask(name, payload, options, agent);
43
+ if (options?.debug && mcpServers.length > 0) {
44
+ console.log("Starting", mcpServers.length, "mcp servers");
45
+ }
46
+ for (const mcp of mcpServers) {
47
+ await mcp.start();
48
+ const tools = await mcp.extractTools();
49
+ tools.forEach(t => task.def.tools?.push(t));
50
+ if (options?.debug) {
51
+ console.log("MCP start", mcp.name);
52
+ }
53
+ }
41
54
  if (hasSettings) {
42
55
  if (!model?.inferParams) {
43
56
  model.inferParams = {};
@@ -163,7 +176,9 @@ async function executeTask(name, payload, options) {
163
176
  return;
164
177
  }
165
178
  }
166
- printToken(t);
179
+ if (!options?.quiet) {
180
+ printToken(t);
181
+ }
167
182
  }
168
183
  ++emittedTokens;
169
184
  };
@@ -222,10 +237,22 @@ async function executeTask(name, payload, options) {
222
237
  throw new Error(errMsg);
223
238
  }
224
239
  }
225
- if (!out.answer.text.endsWith("\n")) {
226
- console.log();
240
+ if (!options?.isToolCall) {
241
+ if (!out.answer.text.endsWith("\n")) {
242
+ console.log();
243
+ }
244
+ }
245
+ if (!isChatMode.value || options?.isToolCall) {
246
+ if (options?.debug && mcpServers.length > 0) {
247
+ console.log("Closing", mcpServers.length, "mcp server(s)");
248
+ }
249
+ mcpServers.forEach((s) => {
250
+ s.stop();
251
+ if (options?.debug) {
252
+ console.log("MCP stop", s.name);
253
+ }
254
+ });
227
255
  }
228
- mcpServers.forEach(async (s) => await s.stop());
229
256
  await processOutput(out);
230
257
  if (!options?.isToolCall && isChatMode.value) {
231
258
  if (tpl) {
@@ -244,7 +271,7 @@ async function executeTask(name, payload, options) {
244
271
  options.assistant = task.def.template.assistant;
245
272
  }
246
273
  setChatInferenceParams(initialInferParams);
247
- await chat(program, options);
274
+ await chat(program, options, agent, mcpServers);
248
275
  }
249
276
  if (options?.debug === true || options?.verbose === true) {
250
277
  try {
@@ -55,6 +55,22 @@ async function readTask(name, payload, options, agent) {
55
55
  if (!taskSpec?.tools) {
56
56
  taskSpec.tools = [];
57
57
  }
58
+ const mcpServersArgs = {};
59
+ if (options?.mcp) {
60
+ options.mcp.forEach(v => {
61
+ const s = v.split(":");
62
+ if (s.length < 2) {
63
+ throw new Error(`Malformed mcp option ${v}: use --mcp servername:arg1,arg2`);
64
+ }
65
+ const sn = s[0];
66
+ const sa = s[1];
67
+ const _margs = sa.split(",");
68
+ mcpServersArgs[sn] = _margs;
69
+ });
70
+ if (options?.debug) {
71
+ console.log("Opening", options.mcp.length, "server(s)");
72
+ }
73
+ }
58
74
  if (taskFileSpec?.mcp) {
59
75
  for (const [servername, tool] of Object.entries(taskFileSpec.mcp)) {
60
76
  const authorizedTools = new Array();
@@ -69,11 +85,12 @@ async function readTask(name, payload, options, agent) {
69
85
  authorizedTools.push(tn);
70
86
  });
71
87
  }
88
+ const margs = tool.arguments;
89
+ if (servername in mcpServersArgs) {
90
+ margs.push(...mcpServersArgs[servername]);
91
+ }
72
92
  const mcp = new McpClient(servername, tool.command, tool.arguments, authorizedTools.length > 0 ? authorizedTools : null, askUserTools.length > 0 ? askUserTools : null);
73
93
  mcpServers.push(mcp);
74
- await mcp.start();
75
- const tools = await mcp.extractTools();
76
- tools.forEach(t => taskSpec.tools?.push(t));
77
94
  }
78
95
  }
79
96
  if (taskSpec.toolsList) {
@@ -1,3 +1,3 @@
1
1
  declare function executeWorkflow(wname: string, args: any, options?: Record<string, any>): Promise<any>;
2
2
  declare function executeWorkflowCmd(name: string, wargs: Array<any>): Promise<any>;
3
- export { executeWorkflow, executeWorkflowCmd, };
3
+ export { executeWorkflow, executeWorkflowCmd };
@@ -1,13 +1,13 @@
1
+ import colors from "ansi-colors";
2
+ import { pathToFileURL } from "node:url";
3
+ import { getFeatureSpec } from "../../../state/features.js";
1
4
  import { executeAction } from "../actions/cmd.js";
2
5
  import { executeAdaptater } from "../adaptaters/cmd.js";
3
6
  import { parseCommandArgs } from "../options_parsers.js";
4
7
  import { executeTask } from "../tasks/cmd.js";
5
8
  import { getTaskPrompt } from "../tasks/utils.js";
6
- import { readWorkflow } from "./read.js";
7
- import colors from "ansi-colors";
8
- import { getFeatureSpec } from "../../../state/features.js";
9
- import { pathToFileURL } from "node:url";
10
9
  import { runtimeError } from "../user_msgs.js";
10
+ import { readWorkflow } from "./read.js";
11
11
  async function executeWorkflow(wname, args, options = {}) {
12
12
  const { workflow, found } = await readWorkflow(wname);
13
13
  if (!found) {
@@ -39,6 +39,13 @@ async function executeWorkflow(wname, args, options = {}) {
39
39
  if (prevStepType == "task") {
40
40
  tdata.prompt = taskRes.answer.text;
41
41
  }
42
+ else if (prevStepType == "action") {
43
+ if (taskRes?.args) {
44
+ if (typeof taskRes.args == "string") {
45
+ tdata.prompt = taskRes.args;
46
+ }
47
+ }
48
+ }
42
49
  }
43
50
  }
44
51
  if (!tdata?.prompt) {
@@ -62,6 +69,13 @@ async function executeWorkflow(wname, args, options = {}) {
62
69
  if (prevStepType == "task") {
63
70
  tdata.prompt = taskRes.answer.text;
64
71
  }
72
+ else if (prevStepType == "action") {
73
+ if (taskRes?.args) {
74
+ if (typeof taskRes.args == "string") {
75
+ tdata.prompt = taskRes.args;
76
+ }
77
+ }
78
+ }
65
79
  }
66
80
  }
67
81
  if (!tdata?.prompt) {
@@ -148,4 +162,4 @@ async function executeWorkflowCmd(name, wargs) {
148
162
  const { args, options } = parseCommandArgs(wargs);
149
163
  return await executeWorkflow(name, args, options);
150
164
  }
151
- export { executeWorkflow, executeWorkflowCmd, };
165
+ export { executeWorkflow, executeWorkflowCmd };
@@ -14,6 +14,7 @@ const inferenceOptions = [
14
14
  new Option("-t, --temperature <number>", "adjusts randomness in sampling; higher values mean more randomness").argParser(parseFloatValue),
15
15
  new Option("-r, --repeat_penalty <number>", "adjusts penalty for repeated tokens").argParser(parseFloatValue),
16
16
  new Option("-b, --backend <name>", "use a given backend. It must be registered in config").argParser(parseString),
17
+ new Option("--mcp [args...]", "extra arguments for mcp server arguments: --mcp servername:arg1,arg2"),
17
18
  ];
18
19
  const ioOptions = [
19
20
  new Option("--if, --input-file", "use promptfile input mode"),
@@ -1,3 +1,3 @@
1
1
  import { Command } from "commander";
2
- declare function readCmd(name: string, cmdPath: string): Promise<Command>;
2
+ declare function readCmd(name: string, cmdPath: string): Promise<Command | null>;
3
3
  export { readCmd };
@@ -1,12 +1,19 @@
1
1
  import { pathToFileURL } from 'url';
2
+ import { runtimeWarning } from "../lib/user_msgs.js";
2
3
  async function readCmd(name, cmdPath) {
3
- const cmds = new Array();
4
4
  const url = pathToFileURL(cmdPath).href;
5
- const { cmd } = await import(url);
6
- if (!cmd) {
7
- throw new Error(`command ${name} not found at ${cmdPath}`);
5
+ let _cmd = null;
6
+ try {
7
+ const mod = await import(url);
8
+ _cmd = mod.cmd;
8
9
  }
9
- cmds.push(cmd);
10
- return cmd;
10
+ catch (e) {
11
+ runtimeWarning(`command ${name} not found at ${cmdPath}, ${e}`);
12
+ return null;
13
+ }
14
+ if (!_cmd) {
15
+ throw new Error("no cmd");
16
+ }
17
+ return _cmd;
11
18
  }
12
19
  export { readCmd };
@@ -66,7 +66,7 @@ function readFeaturesDir(dir) {
66
66
  }
67
67
  dirpath = path.join(dir, "actions");
68
68
  if (fs.existsSync(dirpath)) {
69
- const data = _readDir(dirpath, ["yml", ".js", "mjs", ".py"]);
69
+ const data = _readDir(dirpath, [".yml", ".js", ".py"]);
70
70
  data.forEach((filename) => {
71
71
  const parts = filename.split(".");
72
72
  const ext = parts.pop();
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { argv } from 'process';
3
3
  import { query } from "./cli.js";
4
+ import { resetDbCmd } from './cmd/clicmds/cmds.js';
5
+ import { updateConfCmd } from './cmd/clicmds/updateconf.js';
4
6
  import { buildCmds, parseCmd } from './cmd/cmds.js';
5
7
  import { formatMode, init, inputMode, isChatMode, outputMode, runMode } from './state/state.js';
6
- import { updateConfCmd } from './cmd/clicmds/updateconf.js';
7
- import { resetDbCmd } from './cmd/clicmds/cmds.js';
8
8
  async function main() {
9
9
  const nargs = argv.length;
10
10
  if (nargs == 2) {
@@ -1,6 +1,5 @@
1
1
  import { PythonShell } from 'python-shell';
2
2
  import { InputMode, RunMode, FormatMode, OutputMode } from "../interfaces.js";
3
- import { Agent } from "@agent-smith/agent";
4
3
  declare let pyShell: PythonShell;
5
4
  declare const inputMode: import("@vue/reactivity").Ref<InputMode, InputMode>;
6
5
  declare const outputMode: import("@vue/reactivity").Ref<OutputMode, OutputMode>;
@@ -10,7 +9,6 @@ declare const isChatMode: import("@vue/reactivity").Ref<boolean, boolean>;
10
9
  declare const promptfilePath: import("@vue/reactivity").Ref<string, string>;
11
10
  declare const dataDirPath: import("@vue/reactivity").Ref<string, string>;
12
11
  declare const isStateReady: import("@vue/reactivity").Ref<boolean, boolean>;
13
- declare let agent: Agent;
14
12
  declare const lastCmd: {
15
13
  name: string;
16
14
  args: Array<string>;
@@ -19,4 +17,4 @@ declare function initFilepaths(): void;
19
17
  declare function init(): Promise<void>;
20
18
  declare function initState(): Promise<void>;
21
19
  declare function pluginDataDir(pluginName: string): string;
22
- export { inputMode, outputMode, isChatMode, runMode, formatMode, lastCmd, promptfilePath, dataDirPath, isStateReady, pluginDataDir, initState, initFilepaths, init, pyShell, agent, };
20
+ export { inputMode, outputMode, isChatMode, runMode, formatMode, lastCmd, promptfilePath, dataDirPath, isStateReady, pluginDataDir, initState, initFilepaths, init, pyShell, };
@@ -4,7 +4,6 @@ import { readFilePaths } from "../db/read.js";
4
4
  import path from "path";
5
5
  import { createDirectoryIfNotExists } from "../cmd/sys/dirs.js";
6
6
  import { backend, initBackends } from "./backends.js";
7
- import { Agent } from "@agent-smith/agent";
8
7
  import { runtimeDataError } from "../utils/user_msgs.js";
9
8
  let pyShell;
10
9
  const inputMode = ref("manual");
@@ -15,7 +14,6 @@ const isChatMode = ref(false);
15
14
  const promptfilePath = ref("");
16
15
  const dataDirPath = ref("");
17
16
  const isStateReady = ref(false);
18
- let agent;
19
17
  const lastCmd = reactive({
20
18
  name: "",
21
19
  args: [],
@@ -39,7 +37,6 @@ async function init() {
39
37
  runtimeDataError("No backend found, can not initialize agent");
40
38
  return;
41
39
  }
42
- agent = new Agent(backend.value);
43
40
  }
44
41
  async function initState() {
45
42
  if (isStateReady.value) {
@@ -61,4 +58,4 @@ function pluginDataDir(pluginName) {
61
58
  createDirectoryIfNotExists(pluginDatapath);
62
59
  return pluginDatapath;
63
60
  }
64
- export { inputMode, outputMode, isChatMode, runMode, formatMode, lastCmd, promptfilePath, dataDirPath, isStateReady, pluginDataDir, initState, initFilepaths, init, pyShell, agent, };
61
+ export { inputMode, outputMode, isChatMode, runMode, formatMode, lastCmd, promptfilePath, dataDirPath, isStateReady, pluginDataDir, initState, initFilepaths, init, pyShell, };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@agent-smith/cli",
3
3
  "description": "Agent Smith: terminal client for language model agents",
4
4
  "repository": "https://github.com/synw/agent-smith",
5
- "version": "0.0.104",
5
+ "version": "0.0.106",
6
6
  "scripts": {
7
7
  "buildrl": "rm -rf dist/* && rollup -c",
8
8
  "build": "rm -rf dist/* && tsc",
@@ -10,17 +10,17 @@
10
10
  "watch": "tsc --noCheck -p . -w"
11
11
  },
12
12
  "dependencies": {
13
- "@agent-smith/agent": "^0.2.0",
14
- "@agent-smith/task": "^0.2.1",
13
+ "@agent-smith/agent": "^0.2.1",
15
14
  "@agent-smith/nodetask": "^0.1.0",
15
+ "@agent-smith/task": "^0.2.2",
16
16
  "@agent-smith/tfm": "^0.2.0",
17
- "@inquirer/prompts": "^8.1.0",
17
+ "@inquirer/prompts": "^8.2.0",
18
18
  "@intrinsicai/gbnfgen": "0.12.0",
19
19
  "@locallm/api": "^0.7.3",
20
20
  "@modelcontextprotocol/sdk": "^1.25.2",
21
- "@vue/reactivity": "^3.5.26",
21
+ "@vue/reactivity": "^3.5.27",
22
22
  "ansi-colors": "^4.1.3",
23
- "better-sqlite3": "^12.5.0",
23
+ "better-sqlite3": "^12.6.2",
24
24
  "clipboardy": "^5.0.2",
25
25
  "commander": "^14.0.2",
26
26
  "marked-terminal": "^7.3.0",
@@ -29,7 +29,6 @@
29
29
  "yaml": "^2.8.2"
30
30
  },
31
31
  "devDependencies": {
32
- "@agent-smith/tmem-jobs": "^0.0.4",
33
32
  "@cfworker/json-schema": "^4.1.1",
34
33
  "@commander-js/extra-typings": "^14.0.0",
35
34
  "@locallm/types": "^0.6.7",
@@ -37,11 +36,11 @@
37
36
  "@rollup/plugin-typescript": "^12.3.0",
38
37
  "@types/better-sqlite3": "^7.6.13",
39
38
  "@types/marked-terminal": "^6.1.1",
40
- "@types/node": "^25.0.3",
41
- "openai": "^6.15.0",
39
+ "@types/node": "^25.0.9",
40
+ "openai": "^6.16.0",
42
41
  "restmix": "^0.6.1",
43
- "rollup": "^4.55.1",
44
- "ts-node": "^10.9.2",
42
+ "rollup": "^4.55.2",
43
+ "ts-node": "^1.7.1",
45
44
  "tslib": "2.8.1",
46
45
  "typescript": "^5.9.3"
47
46
  },