@agent-smith/cli 0.0.106 → 0.0.107

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,7 +3,7 @@ import { listBackends, setBackend } from "../../state/backends.js";
3
3
  import { parseCommandArgs } from "../lib/options_parsers.js";
4
4
  import { processTaskCmd, processTasksCmd, resetDbCmd, updateFeaturesCmd } from "./cmds.js";
5
5
  import { updateConfCmd } from "./updateconf.js";
6
- import { inferenceOptions } from "../options.js";
6
+ import { displayOptions, inferenceOptions } from "../options.js";
7
7
  function initBaseCommands(program) {
8
8
  program.command("exit")
9
9
  .description("exit the cli")
@@ -34,11 +34,13 @@ function initBaseCommands(program) {
34
34
  .action(async (...args) => {
35
35
  await listBackends();
36
36
  });
37
- program.command("update")
37
+ const updateCmd = program.command("update")
38
38
  .description("update the available features: run this after adding a new feature")
39
39
  .action(async (...args) => {
40
- await updateFeaturesCmd();
40
+ const ca = parseCommandArgs(args);
41
+ await updateFeaturesCmd(ca.options);
41
42
  });
43
+ displayOptions.forEach(o => updateCmd.addOption(o));
42
44
  program.command("conf <path>")
43
45
  .description("process config file")
44
46
  .action(async (...args) => {
@@ -2,7 +2,7 @@ import { Command } from 'commander';
2
2
  import { FeatureSpec } from '../../interfaces.js';
3
3
  declare function initUserCmds(cmdFeats: Record<string, FeatureSpec>): Promise<Array<Command>>;
4
4
  declare function resetDbCmd(): Promise<any>;
5
- declare function updateFeaturesCmd(): Promise<any>;
5
+ declare function updateFeaturesCmd(options: Record<string, any>): Promise<any>;
6
6
  declare function processTasksCmd(args: Array<string>, options: Record<string, any>): Promise<void>;
7
7
  declare function processTaskCmd(args: Array<string>, options: Record<string, any>): Promise<any>;
8
8
  export { initUserCmds, processTaskCmd, processTasksCmd, resetDbCmd, updateFeaturesCmd };
@@ -1,7 +1,7 @@
1
1
  import colors from "ansi-colors";
2
2
  import path from "path";
3
3
  import YAML from 'yaml';
4
- import { cacheFilePath, dbPath } from "../../conf.js";
4
+ import { 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
7
  import { getFeatureSpec, readFeaturesDirs } from "../../state/features.js";
@@ -11,7 +11,6 @@ import { initTaskSettings, isTaskSettingsInitialized, tasksSettings } from '../.
11
11
  import { deleteFileIfExists } from "../sys/delete_file.js";
12
12
  import { readCmd } from "../sys/read_cmds.js";
13
13
  import { readTask } from "../sys/read_task.js";
14
- import { updateUserCmdsCache } from './cache.js';
15
14
  async function initUserCmds(cmdFeats) {
16
15
  const features = Object.values(cmdFeats);
17
16
  const usrCmds = [];
@@ -32,18 +31,17 @@ async function resetDbCmd() {
32
31
  deleteFileIfExists(dbPath);
33
32
  console.log("Config database reset ok. Run the conf command to recreate it");
34
33
  }
35
- async function updateFeaturesCmd() {
34
+ async function updateFeaturesCmd(options) {
36
35
  const fp = readFeaturePaths();
37
36
  const pp = await readPluginsPaths();
38
37
  const paths = [...fp, ...pp];
39
- const feats = readFeaturesDirs(paths);
38
+ const feats = readFeaturesDirs(paths, options?.debug ?? false);
40
39
  updateFeatures(feats);
41
40
  updateAliases(feats);
42
41
  const deleted = cleanupFeaturePaths(paths);
43
42
  for (const el of deleted) {
44
43
  console.log("- [feature path]", el);
45
44
  }
46
- updateUserCmdsCache(cacheFilePath, feats.cmd);
47
45
  }
48
46
  async function processTasksCmd(args, options) {
49
47
  if (options?.conf) {
@@ -1,11 +1,10 @@
1
- import { cacheFilePath, processConfPath } from "../../conf.js";
1
+ import { processConfPath } from "../../conf.js";
2
2
  import { initDb } from "../../db/db.js";
3
3
  import { readFilePath } from "../../db/read.js";
4
4
  import { cleanupFeaturePaths, updateAliases, updateDataDirPath, updateFeatures, updatePromptfilePath, upsertFilePath } from "../../db/write.js";
5
5
  import { readFeaturesDirs } from "../../state/features.js";
6
6
  import { dataDirPath, promptfilePath } from "../../state/state.js";
7
7
  import { runtimeDataError, runtimeInfo } from '../lib/user_msgs.js';
8
- import { updateUserCmdsCache } from "./cache.js";
9
8
  async function updateConfCmd(args) {
10
9
  initDb(false, true);
11
10
  const { found, path } = readFilePath("conf");
@@ -34,13 +33,12 @@ async function updateConfCmd(args) {
34
33
  updateDataDirPath(dd);
35
34
  dataDirPath.value = dd;
36
35
  }
37
- const feats = readFeaturesDirs(paths);
36
+ const feats = readFeaturesDirs(paths, true);
38
37
  updateFeatures(feats);
39
38
  updateAliases(feats);
40
39
  const deleted = cleanupFeaturePaths(paths);
41
40
  for (const el of deleted) {
42
41
  console.log("- [feature path]", el);
43
42
  }
44
- updateUserCmdsCache(cacheFilePath, feats.cmd);
45
43
  }
46
44
  export { updateConfCmd, };
@@ -9,8 +9,15 @@ import { readClipboard } from "../../sys/clipboard.js";
9
9
  import { processOutput, readPromptFile } from "../utils.js";
10
10
  import { parseCommandArgs } from "../options_parsers.js";
11
11
  import { pathToFileURL } from 'url';
12
+ import { getInputFromOptions } from '../tasks/utils.js';
12
13
  async function executeAction(name, payload, options, quiet = false) {
13
14
  let run;
15
+ const inputData = await getInputFromOptions(options);
16
+ if (inputData) {
17
+ if (Array.isArray(payload)) {
18
+ payload.push(inputData);
19
+ }
20
+ }
14
21
  const { found, path, ext } = getFeatureSpec(name, "action");
15
22
  if (!found) {
16
23
  throw new Error(`Action ${name} not found at ${path}`);
@@ -1,11 +1,18 @@
1
1
  import { getFeatureSpec } from "../../../state/features.js";
2
2
  import { createJsAction } from "../actions/read.js";
3
3
  import { pathToFileURL } from 'url';
4
+ import { getInputFromOptions } from "../tasks/utils.js";
4
5
  async function executeAdaptater(name, params, options) {
5
6
  const { found, path } = getFeatureSpec(name, "adaptater");
6
7
  if (!found) {
7
8
  throw new Error(`adaptater ${name} not found`);
8
9
  }
10
+ const inputData = await getInputFromOptions(options);
11
+ if (inputData) {
12
+ if (Array.isArray(params)) {
13
+ params.push(inputData);
14
+ }
15
+ }
9
16
  let run;
10
17
  const url = pathToFileURL(path).href;
11
18
  const jsa = await import(url);
@@ -1,6 +1,6 @@
1
1
  import { compile, serializeGrammar } from "@intrinsicai/gbnfgen";
2
2
  import { default as color, default as colors } from "ansi-colors";
3
- import { PromptTemplate } from "modprompt";
3
+ import { PromptTemplate, templates } from "modprompt";
4
4
  import ora from 'ora';
5
5
  import { usePerfTimer } from "../../../main.js";
6
6
  import { backend, backends, listBackends } from "../../../state/backends.js";
@@ -92,7 +92,12 @@ async function executeTask(name, payload, options) {
92
92
  let hasThink = false;
93
93
  let tpl = null;
94
94
  if (useTemplates) {
95
- tpl = new PromptTemplate(model.template ?? "none");
95
+ try {
96
+ tpl = new PromptTemplate(model.template ?? "none");
97
+ }
98
+ catch (e) {
99
+ throw new Error(`Can not load template ${model.template}\nAvailable templates: ${Object.keys(templates)}\n`);
100
+ }
96
101
  hasThink = tpl.tags?.think ? true : false;
97
102
  }
98
103
  if (options?.debug) {
@@ -110,7 +115,6 @@ async function executeTask(name, payload, options) {
110
115
  else {
111
116
  process.stdout.write(t);
112
117
  }
113
- ++emittedTokens;
114
118
  };
115
119
  let hasTools = false;
116
120
  if (task.def?.tools) {
@@ -177,7 +181,9 @@ async function executeTask(name, payload, options) {
177
181
  }
178
182
  }
179
183
  if (!options?.quiet) {
180
- printToken(t);
184
+ if (!options?.isToolCall || (options?.debug || options.verbose)) {
185
+ printToken(t);
186
+ }
181
187
  }
182
188
  }
183
189
  ++emittedTokens;
@@ -226,7 +232,11 @@ async function executeTask(name, payload, options) {
226
232
  return;
227
233
  }
228
234
  else if (errMsg.includes("404 Not Found")) {
229
- runtimeError("The server answered with a 404 Not Found error. That usually mean that the model you are requesting does not exist on the server.");
235
+ runtimeError("The server answered with a 404 Not Found error. That might mean that the model you are requesting does not exist on the server.");
236
+ return;
237
+ }
238
+ else if (errMsg.includes("400 Bad Request")) {
239
+ runtimeError("The server answered with a 400 Bad Request error. That might mean that the model you are requesting does not exist on the server or a parameter is missing in your request.");
230
240
  return;
231
241
  }
232
242
  else if (errMsg.includes("fetch failed")) {
@@ -123,13 +123,16 @@ async function readTask(name, payload, options, agent) {
123
123
  options.isToolCall = true;
124
124
  options.isAgent = true;
125
125
  const agres = await executeTask(toolName, params, options);
126
+ options.isAgent = false;
126
127
  options.isToolCall = false;
127
128
  if (agres?.answer?.text) {
128
129
  return agres.answer.text;
129
130
  }
130
131
  return agres;
131
132
  case "workflow":
133
+ options.isToolCall = true;
132
134
  const wres = await executeWorkflow(toolName, params, options);
135
+ options.isToolCall = false;
133
136
  return wres;
134
137
  default:
135
138
  throw new Error(`unknown tool execution function type: ${type} for ${toolName}`);
@@ -3,5 +3,6 @@ declare function openTaskSpec(name: string, isAgent?: boolean): {
3
3
  taskFileSpec: LmTaskFileSpec;
4
4
  taskPath: string;
5
5
  };
6
+ declare function getInputFromOptions(options: Record<string, any>): Promise<string | null>;
6
7
  declare function getTaskPrompt(name: string, args: Array<string>, options: Record<string, any>): Promise<string>;
7
- export { getTaskPrompt, openTaskSpec };
8
+ export { getTaskPrompt, getInputFromOptions, openTaskSpec, };
@@ -18,23 +18,31 @@ function openTaskSpec(name, isAgent = false) {
18
18
  taskFileSpec.name = name;
19
19
  return { taskFileSpec: taskFileSpec, taskPath: path };
20
20
  }
21
- async function getTaskPrompt(name, args, options) {
22
- let pr;
21
+ async function getInputFromOptions(options) {
22
+ let out = null;
23
23
  if (options?.clipboardInput === true) {
24
- pr = await readClipboard();
24
+ out = await readClipboard();
25
+ options.clipboardInput = false;
25
26
  }
26
27
  else if (options?.inputFile === true) {
27
- pr = readPromptFile();
28
+ out = readPromptFile();
29
+ options.inputFile = false;
30
+ }
31
+ return out;
32
+ }
33
+ async function getTaskPrompt(name, args, options) {
34
+ const ic = await getInputFromOptions(options);
35
+ if (ic) {
36
+ return ic;
37
+ }
38
+ let pr;
39
+ if (args[0] !== undefined) {
40
+ pr = args[0];
28
41
  }
29
42
  else {
30
- if (args[0] !== undefined) {
31
- pr = args[0];
32
- }
33
- else {
34
- runtimeDataError("task", name, "provide a prompt or use input options");
35
- throw new Error();
36
- }
43
+ runtimeDataError(options?.isAgent ? "agent" : "task", name, "provide a prompt or use input options");
44
+ throw new Error();
37
45
  }
38
46
  return pr;
39
47
  }
40
- export { getTaskPrompt, openTaskSpec };
48
+ export { getTaskPrompt, getInputFromOptions, openTaskSpec, };
@@ -5,7 +5,7 @@ import { executeAction } from "../actions/cmd.js";
5
5
  import { executeAdaptater } from "../adaptaters/cmd.js";
6
6
  import { parseCommandArgs } from "../options_parsers.js";
7
7
  import { executeTask } from "../tasks/cmd.js";
8
- import { getTaskPrompt } from "../tasks/utils.js";
8
+ import { getInputFromOptions, getTaskPrompt } from "../tasks/utils.js";
9
9
  import { runtimeError } from "../user_msgs.js";
10
10
  import { readWorkflow } from "./read.js";
11
11
  async function executeWorkflow(wname, args, options = {}) {
@@ -51,6 +51,7 @@ async function executeWorkflow(wname, args, options = {}) {
51
51
  if (!tdata?.prompt) {
52
52
  throw new Error(`Workflow ${wname} step ${i + 1}: provide a prompt for the task ${step.name}`);
53
53
  }
54
+ options.isAgent = false;
54
55
  const tr = await executeTask(step.name, tdata, options);
55
56
  taskRes = { ...tr, ...taskRes };
56
57
  }
@@ -92,17 +93,28 @@ async function executeWorkflow(wname, args, options = {}) {
92
93
  break;
93
94
  case "action":
94
95
  try {
95
- const actArgs = i == 0 ? taskRes.cmdArgs : taskRes;
96
+ let actArgs;
97
+ if (i == 0) {
98
+ actArgs = taskRes.cmdArgs;
99
+ const inputData = await getInputFromOptions(options);
100
+ if (inputData) {
101
+ actArgs.push(inputData);
102
+ }
103
+ }
104
+ else {
105
+ actArgs = taskRes;
106
+ }
96
107
  const ares = await executeAction(step.name, actArgs, options, true);
108
+ if (i == finalTaskIndex && !options?.isToolCall && !options?.quiet) {
109
+ console.log(ares);
110
+ break;
111
+ }
97
112
  if (typeof ares == "string" || Array.isArray(ares)) {
98
113
  taskRes.args = ares;
99
114
  }
100
115
  else {
101
116
  taskRes = { ...ares, ...taskRes };
102
117
  }
103
- if (i == finalTaskIndex) {
104
- console.log(taskRes);
105
- }
106
118
  }
107
119
  catch (e) {
108
120
  throw new Error(`workflow action ${i + 1}: ${e}`);
@@ -110,17 +122,28 @@ async function executeWorkflow(wname, args, options = {}) {
110
122
  break;
111
123
  case "adaptater":
112
124
  try {
113
- const actArgs = i == 0 ? taskRes.cmdArgs : taskRes;
125
+ let actArgs;
126
+ if (i == 0) {
127
+ actArgs = taskRes.cmdArgs;
128
+ const inputData = await getInputFromOptions(options);
129
+ if (inputData) {
130
+ actArgs.push(inputData);
131
+ }
132
+ }
133
+ else {
134
+ actArgs = taskRes;
135
+ }
114
136
  const adres = await executeAdaptater(step.name, actArgs, options);
137
+ if (i == finalTaskIndex && !options?.isToolCall && !options?.quiet) {
138
+ console.log(adres);
139
+ break;
140
+ }
115
141
  if (typeof adres == "string" || Array.isArray(adres)) {
116
142
  taskRes.args = adres;
117
143
  }
118
144
  else {
119
145
  taskRes = { ...adres };
120
146
  }
121
- if (i == finalTaskIndex) {
122
- console.log(taskRes);
123
- }
124
147
  }
125
148
  catch (e) {
126
149
  throw new Error(`workflow adaptater ${i + 1}: ${e}`);
@@ -138,7 +161,18 @@ async function executeWorkflow(wname, args, options = {}) {
138
161
  runtimeError(`workflow ${wname}: can not import the runCmd function from step ${i} for command ${step.name}: please add a runCmd function export`);
139
162
  return;
140
163
  }
141
- const cres = await jsa.runCmd(args, options);
164
+ let cArgs;
165
+ if (i == 0) {
166
+ cArgs = taskRes.cmdArgs;
167
+ const inputData = await getInputFromOptions(options);
168
+ if (inputData) {
169
+ cArgs.push(inputData);
170
+ }
171
+ }
172
+ else {
173
+ cArgs = taskRes;
174
+ }
175
+ const cres = await jsa.runCmd(cArgs, options);
142
176
  if (typeof cres == "string" || Array.isArray(cres)) {
143
177
  taskRes.args = cres;
144
178
  }
package/dist/db/db.js CHANGED
@@ -16,7 +16,7 @@ function initDb(isVerbose, execSchema) {
16
16
  });
17
17
  }
18
18
  else {
19
- db = new DatabaseConstructor(dbPath);
19
+ db = new DatabaseConstructor(dbPath, { fileMustExist: true });
20
20
  }
21
21
  }
22
22
  export { db, initDb, };
@@ -1,5 +1,5 @@
1
1
  import { FeatureExtension, FeatureType, Features } from "../interfaces.js";
2
- declare function readFeaturesDirs(featuresPaths: Array<string>): Features;
2
+ declare function readFeaturesDirs(featuresPaths: Array<string>, isverbose?: boolean): Features;
3
3
  declare function getFeatureSpec(name: string, type: FeatureType): {
4
4
  found: boolean;
5
5
  path: string;
@@ -1,7 +1,7 @@
1
1
  import { default as path } from "path";
2
2
  import { readFeaturesDir } from "../cmd/sys/read_features.js";
3
3
  import { readFeature } from "../db/read.js";
4
- function readFeaturesDirs(featuresPaths) {
4
+ function readFeaturesDirs(featuresPaths, isverbose = false) {
5
5
  const feats = {
6
6
  task: [],
7
7
  action: [],
@@ -11,6 +11,9 @@ function readFeaturesDirs(featuresPaths) {
11
11
  agent: [],
12
12
  };
13
13
  featuresPaths.forEach((dir) => {
14
+ if (isverbose) {
15
+ console.log("Reading feats in", dir);
16
+ }
14
17
  const _f = readFeaturesDir(dir);
15
18
  _f.agent.forEach((item) => feats.agent.push(item));
16
19
  _f.task.forEach((item) => feats.task.push(item));
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.106",
5
+ "version": "0.0.107",
6
6
  "scripts": {
7
7
  "buildrl": "rm -rf dist/* && rollup -c",
8
8
  "build": "rm -rf dist/* && tsc",
@@ -10,21 +10,22 @@
10
10
  "watch": "tsc --noCheck -p . -w"
11
11
  },
12
12
  "dependencies": {
13
- "@agent-smith/agent": "^0.2.1",
14
- "@agent-smith/nodetask": "^0.1.0",
15
- "@agent-smith/task": "^0.2.2",
13
+ "@agent-smith/agent": "^0.2.2",
14
+ "@agent-smith/nodetask": "^0.1.1",
15
+ "@agent-smith/task": "^0.2.3",
16
16
  "@agent-smith/tfm": "^0.2.0",
17
17
  "@inquirer/prompts": "^8.2.0",
18
18
  "@intrinsicai/gbnfgen": "0.12.0",
19
19
  "@locallm/api": "^0.7.3",
20
- "@modelcontextprotocol/sdk": "^1.25.2",
20
+ "@modelcontextprotocol/sdk": "^1.25.3",
21
21
  "@vue/reactivity": "^3.5.27",
22
22
  "ansi-colors": "^4.1.3",
23
23
  "better-sqlite3": "^12.6.2",
24
- "clipboardy": "^5.0.2",
24
+ "clipboardy": "^5.1.0",
25
25
  "commander": "^14.0.2",
26
26
  "marked-terminal": "^7.3.0",
27
- "ora": "^9.0.0",
27
+ "modprompt": "0.13.1",
28
+ "ora": "^9.1.0",
28
29
  "python-shell": "^5.0.0",
29
30
  "yaml": "^2.8.2"
30
31
  },
@@ -36,11 +37,10 @@
36
37
  "@rollup/plugin-typescript": "^12.3.0",
37
38
  "@types/better-sqlite3": "^7.6.13",
38
39
  "@types/marked-terminal": "^6.1.1",
39
- "@types/node": "^25.0.9",
40
+ "@types/node": "^25.0.10",
40
41
  "openai": "^6.16.0",
41
42
  "restmix": "^0.6.1",
42
- "rollup": "^4.55.2",
43
- "ts-node": "^1.7.1",
43
+ "rollup": "^4.56.0",
44
44
  "tslib": "2.8.1",
45
45
  "typescript": "^5.9.3"
46
46
  },
@@ -1,4 +0,0 @@
1
- import { FeatureSpec } from '../../interfaces.js';
2
- declare function ensureUserCmdsCacheFileExists(cacheFilePath: string): string;
3
- declare function updateUserCmdsCache(cacheFilePath: string, cmdFeats: Array<FeatureSpec>): void;
4
- export { ensureUserCmdsCacheFileExists, updateUserCmdsCache, };
@@ -1,39 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { runtimeError } from '../../utils/user_msgs.js';
4
- function createCacheFileContent(cmdFeats) {
5
- const imports = new Array();
6
- const cmdNames = new Array();
7
- let i = 1;
8
- cmdFeats.forEach(feat => {
9
- const fileName = feat.name + "." + feat.ext;
10
- const importPath = path.join(feat.path, fileName);
11
- const cmdId = `c${i}`;
12
- const line = `import { cmd as ${cmdId} } from "file://${importPath}";`;
13
- imports.push(line);
14
- cmdNames.push(cmdId);
15
- ++i;
16
- });
17
- const finalImports = imports.join("\n");
18
- const cmds = `const cmds = [ ${cmdNames.join(", ")} ];\nconst isCacheReady = true;`;
19
- const end = "export { isCacheReady, cmds }";
20
- return `${finalImports}\n\n${cmds}\n\n${end}`;
21
- }
22
- function ensureUserCmdsCacheFileExists(cacheFilePath) {
23
- const fileExists = fs.existsSync(cacheFilePath);
24
- if (!fileExists) {
25
- fs.writeFileSync(cacheFilePath, "const cmds = [];\nexport { cmds }");
26
- }
27
- return cacheFilePath;
28
- }
29
- function updateUserCmdsCache(cacheFilePath, cmdFeats) {
30
- const filePath = ensureUserCmdsCacheFileExists(cacheFilePath);
31
- const cacheFileContent = createCacheFileContent(cmdFeats);
32
- try {
33
- fs.writeFileSync(filePath, cacheFileContent);
34
- }
35
- catch (err) {
36
- runtimeError("Error writing to user commands cache file at " + filePath, `${err}`);
37
- }
38
- }
39
- export { ensureUserCmdsCacheFileExists, updateUserCmdsCache, };