@agent-smith/cli 0.0.102 → 0.0.104

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.
@@ -2,9 +2,32 @@ import { allOptions } from "../options.js";
2
2
  import { executeTaskCmd } from "../lib/tasks/cmd.js";
3
3
  import { executeActionCmd } from "../lib/actions/cmd.js";
4
4
  import { executeWorkflowCmd } from "../lib/workflows/cmd.js";
5
+ import { executeAgentCmd } from "../lib/agents/cmd.js";
5
6
  function initCommandsFromAliases(program, aliases, features) {
6
7
  aliases.forEach((alias) => {
7
8
  switch (alias.type) {
9
+ case "agent":
10
+ const agcmd = program.command(`${alias.name} [prompt_and_vars...]`)
11
+ .description("agent: " + alias.name)
12
+ .action(async (...args) => {
13
+ await executeAgentCmd(alias.name, args);
14
+ });
15
+ allOptions.forEach(o => agcmd.addOption(o));
16
+ if (features.agent[alias.name]?.variables) {
17
+ const rtv = features.agent[alias.name].variables?.required;
18
+ if (rtv) {
19
+ for (const name of Object.keys(rtv)) {
20
+ agcmd.option(`--${name} <value>`);
21
+ }
22
+ }
23
+ const otv = features.agent[alias.name].variables?.optional;
24
+ if (otv) {
25
+ for (const name of Object.keys(otv)) {
26
+ agcmd.option(`--${name} <value>`);
27
+ }
28
+ }
29
+ }
30
+ break;
8
31
  case "task":
9
32
  const tcmd = program.command(`${alias.name} [prompt_and_vars...]`)
10
33
  .description("task: " + alias.name)
@@ -15,8 +15,8 @@ function createCacheFileContent(cmdFeats) {
15
15
  ++i;
16
16
  });
17
17
  const finalImports = imports.join("\n");
18
- const cmds = `const cmds = [ ${cmdNames.join(", ")} ]`;
19
- const end = "export { cmds }";
18
+ const cmds = `const cmds = [ ${cmdNames.join(", ")} ];\nconst isCacheReady = true;`;
19
+ const end = "export { isCacheReady, cmds }";
20
20
  return `${finalImports}\n\n${cmds}\n\n${end}`;
21
21
  }
22
22
  function ensureUserCmdsCacheFileExists(cacheFilePath) {
@@ -1,29 +1,24 @@
1
1
  import colors from "ansi-colors";
2
2
  import path from "path";
3
- import { pathToFileURL } from 'url';
4
3
  import YAML from 'yaml';
5
4
  import { cacheFilePath, dbPath } from "../../conf.js";
6
5
  import { readFeaturePaths, readFeaturesType, readTaskSetting } from "../../db/read.js";
7
6
  import { cleanupFeaturePaths, deleteTaskSetting, updateAliases, updateFeatures, upsertTaskSettings } from "../../db/write.js";
7
+ import { isCacheReady, cmds } from "../../state/auto/usercmds.js";
8
8
  import { getFeatureSpec, readFeaturesDirs } from "../../state/features.js";
9
9
  import { readPluginsPaths } from "../../state/plugins.js";
10
10
  import { runMode } from "../../state/state.js";
11
11
  import { initTaskSettings, isTaskSettingsInitialized, tasksSettings } from '../../state/tasks.js';
12
- import { cmds } from "../../state/auto/usercmds.js";
13
12
  import { deleteFileIfExists } from "../sys/delete_file.js";
14
13
  import { readCmd } from "../sys/read_cmds.js";
15
14
  import { readTask } from "../sys/read_task.js";
16
15
  import { updateUserCmdsCache } from './cache.js';
17
16
  async function initUserCmds(cmdFeats) {
18
17
  const features = Object.values(cmdFeats);
19
- if (features.length == 0) {
20
- return [];
21
- }
22
18
  let endCmds = cmds;
23
- if (cmds.length == 0) {
19
+ if (!isCacheReady) {
24
20
  updateUserCmdsCache(cacheFilePath, features);
25
- const url = pathToFileURL(cacheFilePath).href;
26
- const usrCmds = new Array();
21
+ const usrCmds = [];
27
22
  for (const feat of features) {
28
23
  const cmdPath = path.join(feat.path, feat.name + "." + feat.ext);
29
24
  const c = await readCmd(feat.name, cmdPath);
@@ -0,0 +1,3 @@
1
+ import type { TaskOutput } from "@agent-smith/task";
2
+ declare function executeAgentCmd(name: string, targs?: Array<any>): Promise<TaskOutput>;
3
+ export { executeAgentCmd, };
@@ -0,0 +1,10 @@
1
+ import { parseCommandArgs } from "../options_parsers.js";
2
+ import { getTaskPrompt } from "../tasks/utils.js";
3
+ import { executeTask } from "../tasks/cmd.js";
4
+ async function executeAgentCmd(name, targs = []) {
5
+ const ca = parseCommandArgs(targs);
6
+ const prompt = await getTaskPrompt(name, ca.args, ca.options);
7
+ ca.options.isAgent = true;
8
+ return await executeTask(name, { prompt: prompt }, ca.options);
9
+ }
10
+ export { executeAgentCmd, };
@@ -10,7 +10,7 @@ import { initTaskSettings, isTaskSettingsInitialized, tasksSettings } from "../.
10
10
  import { chat, program } from "../../cmds.js";
11
11
  import { parseCommandArgs } from "../options_parsers.js";
12
12
  import { runtimeDataError, runtimeError, runtimeWarning } from "../user_msgs.js";
13
- import { formatStats, processOutput } from "../utils.js";
13
+ import { processOutput } from "../utils.js";
14
14
  import { readTask } from "./read.js";
15
15
  import { getTaskPrompt } from "./utils.js";
16
16
  async function executeTask(name, payload, options) {
@@ -86,17 +86,18 @@ async function executeTask(name, payload, options) {
86
86
  console.log("Task model:", model);
87
87
  console.log("Task vars:", vars);
88
88
  }
89
+ let emittedTokens = 0;
89
90
  const printToken = (t) => {
90
91
  if (options?.tokens === true) {
91
92
  let txt = t;
92
93
  txt = c ? t : `\x1b[100m${t}\x1b[0m`;
93
94
  process.stdout.write(txt);
94
- ++i;
95
95
  c = !c;
96
96
  }
97
97
  else {
98
98
  process.stdout.write(t);
99
99
  }
100
+ ++emittedTokens;
100
101
  };
101
102
  let hasTools = false;
102
103
  if (task.def?.tools) {
@@ -113,12 +114,11 @@ async function executeTask(name, payload, options) {
113
114
  return `${ts} ${color.bold(i.toString())} ${te}`;
114
115
  };
115
116
  const perfTimer = usePerfTimer(false);
116
- let i = 0;
117
117
  const processToken = (t) => {
118
- if (i == 0) {
118
+ if (emittedTokens == 0) {
119
119
  perfTimer.start();
120
120
  }
121
- spinner.text = formatTokenCount(i);
121
+ spinner.text = formatTokenCount(emittedTokens);
122
122
  if (!options?.verbose && !options?.debug) {
123
123
  if (hasThink && tpl) {
124
124
  if (t == tpl.tags.think?.start) {
@@ -129,7 +129,7 @@ async function executeTask(name, payload, options) {
129
129
  else if (t == tpl.tags.think?.end) {
130
130
  continueWrite = true;
131
131
  skipNextEmptyLinesToken = true;
132
- let msg = color.dim("Thinking:") + ` ${i} ${color.dim("tokens")}`;
132
+ let msg = color.dim("Thinking:") + ` ${emittedTokens} ${color.dim("tokens")}`;
133
133
  msg = msg + " " + color.dim(perfTimer.time());
134
134
  spinner.info(msg);
135
135
  return;
@@ -139,7 +139,7 @@ async function executeTask(name, payload, options) {
139
139
  else {
140
140
  if (tpl) {
141
141
  if (t == tpl.tags.think?.end) {
142
- let msg = color.dim("Thinking:") + ` ${i} ${color.dim("tokens")}`;
142
+ let msg = color.dim("Thinking:") + ` ${emittedTokens} ${color.dim("tokens")}`;
143
143
  msg = msg + " " + color.dim(perfTimer.time());
144
144
  console.log(msg);
145
145
  }
@@ -165,17 +165,15 @@ async function executeTask(name, payload, options) {
165
165
  }
166
166
  printToken(t);
167
167
  }
168
- ++i;
168
+ ++emittedTokens;
169
169
  };
170
- const spinnerInit = (name) => ora(`Executing ${name} tool ...\n`);
171
- let tcspinner;
172
170
  const onToolCall = (tc) => {
173
171
  console.log("⚒️ ", color.bold(name), "=>", `${color.yellowBright(tc.name)}`, tc.arguments);
174
- tcspinner = spinnerInit(tc.name);
175
- tcspinner.start();
176
172
  };
177
173
  const onToolCallEnd = (tr) => {
178
- tcspinner.stop();
174
+ if (options?.debug) {
175
+ console.log(tr);
176
+ }
179
177
  };
180
178
  if (options?.onToken) {
181
179
  task.agent.lm.onToken = options.onToken;
@@ -250,7 +248,7 @@ async function executeTask(name, payload, options) {
250
248
  }
251
249
  if (options?.debug === true || options?.verbose === true) {
252
250
  try {
253
- console.log("\n", formatStats(out.answer.stats));
251
+ console.log(emittedTokens.toString(), color.dim("tokens"), out.answer.stats.tokensPerSecond, color.dim("tps"));
254
252
  if (options?.debug === true) {
255
253
  console.log(out.answer.stats);
256
254
  }
@@ -259,7 +257,7 @@ async function executeTask(name, payload, options) {
259
257
  runtimeWarning("Error formating stats:", `${e}`);
260
258
  }
261
259
  }
262
- if (options?.backend) {
260
+ if (options?.backend || settings?.backend) {
263
261
  agent.lm = backend.value;
264
262
  }
265
263
  return out;
@@ -16,7 +16,7 @@ async function readTask(name, payload, options, agent) {
16
16
  console.log("Payload:", payload);
17
17
  console.log("Task options:", options);
18
18
  }
19
- const { taskFileSpec, taskPath } = openTaskSpec(name);
19
+ const { taskFileSpec, taskPath } = openTaskSpec(name, options?.isAgent);
20
20
  const taskDir = path.dirname(taskPath);
21
21
  const opts = payload?.inferParams ? { ...options, ...payload.inferParams } : options;
22
22
  const conf = parseTaskConfigOptions(opts);
@@ -98,9 +98,19 @@ async function readTask(name, payload, options, agent) {
98
98
  return res;
99
99
  case "task":
100
100
  options.isToolCall = true;
101
+ options.isAgent = false;
101
102
  const tres = await executeTask(toolName, params, options);
102
103
  options.isToolCall = false;
103
104
  return tres.answer.text;
105
+ case "agent":
106
+ options.isToolCall = true;
107
+ options.isAgent = true;
108
+ const agres = await executeTask(toolName, params, options);
109
+ options.isToolCall = false;
110
+ if (agres?.answer?.text) {
111
+ return agres.answer.text;
112
+ }
113
+ return agres;
104
114
  case "workflow":
105
115
  const wres = await executeWorkflow(toolName, params, options);
106
116
  return wres;
@@ -1,5 +1,5 @@
1
1
  import { LmTaskFileSpec } from "../../../interfaces.js";
2
- declare function openTaskSpec(name: string): {
2
+ declare function openTaskSpec(name: string, isAgent?: boolean): {
3
3
  taskFileSpec: LmTaskFileSpec;
4
4
  taskPath: string;
5
5
  };
@@ -4,14 +4,15 @@ import { readTask } from "../../../cmd/sys/read_task.js";
4
4
  import { getFeatureSpec } from "../../../state/features.js";
5
5
  import { runtimeDataError } from '../user_msgs.js';
6
6
  import { readPromptFile } from '../utils.js';
7
- function openTaskSpec(name) {
8
- const { found, path } = getFeatureSpec(name, "task");
7
+ function openTaskSpec(name, isAgent = false) {
8
+ const ft = isAgent ? "agent" : "task";
9
+ const { found, path } = getFeatureSpec(name, ft);
9
10
  if (!found) {
10
- throw new Error(`Task ${name} not found`);
11
+ throw new Error(`${ft} ${name} not found`);
11
12
  }
12
13
  const res = readTask(path);
13
14
  if (!res.found) {
14
- throw new Error(`Task ${name}, ${path} not found`);
15
+ throw new Error(`${ft} ${name}, ${path} not found`);
15
16
  }
16
17
  const taskFileSpec = YAML.parse(res.ymlTask);
17
18
  taskFileSpec.name = name;
@@ -1,5 +1,3 @@
1
- import { InferenceStats } from "@locallm/types";
2
1
  declare function readPromptFile(): string;
3
2
  declare function processOutput(res: any): Promise<void>;
4
- declare function formatStats(stats: InferenceStats): string;
5
- export { formatStats, processOutput, readPromptFile, };
3
+ export { processOutput, readPromptFile, };
@@ -46,12 +46,4 @@ async function processOutput(res) {
46
46
  }
47
47
  }
48
48
  }
49
- function formatStats(stats) {
50
- const buf = new Array();
51
- buf.push(`${stats.tokensPerSecond} tps`);
52
- buf.push(`- ${stats.totalTimeSeconds}s`);
53
- buf.push(`(${stats.ingestionTimeSeconds}s ingestion /`);
54
- buf.push(`${stats.inferenceTimeSeconds}s inference)`);
55
- return buf.join(" ");
56
- }
57
- export { formatStats, processOutput, readPromptFile, };
49
+ export { processOutput, readPromptFile, };
@@ -5,6 +5,9 @@ import { executeTask } from "../tasks/cmd.js";
5
5
  import { getTaskPrompt } from "../tasks/utils.js";
6
6
  import { readWorkflow } from "./read.js";
7
7
  import colors from "ansi-colors";
8
+ import { getFeatureSpec } from "../../../state/features.js";
9
+ import { pathToFileURL } from "node:url";
10
+ import { runtimeError } from "../user_msgs.js";
8
11
  async function executeWorkflow(wname, args, options = {}) {
9
12
  const { workflow, found } = await readWorkflow(wname);
10
13
  if (!found) {
@@ -27,26 +30,46 @@ async function executeWorkflow(wname, args, options = {}) {
27
30
  switch (step.type) {
28
31
  case "task":
29
32
  try {
30
- let pr = null;
33
+ let tdata = taskRes;
31
34
  if (i == 0) {
32
- pr = await getTaskPrompt(step.name, taskRes.cmdArgs, options);
35
+ tdata.prompt = await getTaskPrompt(step.name, taskRes.cmdArgs, options);
33
36
  }
34
37
  else {
35
38
  if (prevStepType) {
36
39
  if (prevStepType == "task") {
37
- pr = taskRes.answer.text;
40
+ tdata.prompt = taskRes.answer.text;
38
41
  }
39
42
  }
40
- if (!pr) {
41
- if (taskRes?.prompt) {
42
- pr = taskRes.prompt;
43
+ }
44
+ if (!tdata?.prompt) {
45
+ throw new Error(`Workflow ${wname} step ${i + 1}: provide a prompt for the task ${step.name}`);
46
+ }
47
+ const tr = await executeTask(step.name, tdata, options);
48
+ taskRes = { ...tr, ...taskRes };
49
+ }
50
+ catch (e) {
51
+ throw new Error(`workflow task ${i + 1}: ${e}`);
52
+ }
53
+ break;
54
+ case "agent":
55
+ try {
56
+ let tdata = taskRes;
57
+ if (i == 0) {
58
+ tdata.prompt = await getTaskPrompt(step.name, taskRes.cmdArgs, options);
59
+ }
60
+ else {
61
+ if (prevStepType) {
62
+ if (prevStepType == "task") {
63
+ tdata.prompt = taskRes.answer.text;
43
64
  }
44
65
  }
45
66
  }
46
- if (!pr) {
67
+ if (!tdata?.prompt) {
47
68
  throw new Error(`Workflow ${wname} step ${i + 1}: provide a prompt for the task ${step.name}`);
48
69
  }
49
- const tr = await executeTask(step.name, { prompt: pr }, options);
70
+ options.isAgent = true;
71
+ const tr = await executeTask(step.name, tdata, options);
72
+ options.isAgent = false;
50
73
  taskRes = { ...tr, ...taskRes };
51
74
  }
52
75
  catch (e) {
@@ -79,7 +102,7 @@ async function executeWorkflow(wname, args, options = {}) {
79
102
  taskRes.args = adres;
80
103
  }
81
104
  else {
82
- taskRes = { ...adres, ...taskRes };
105
+ taskRes = { ...adres };
83
106
  }
84
107
  if (i == finalTaskIndex) {
85
108
  console.log(taskRes);
@@ -89,8 +112,32 @@ async function executeWorkflow(wname, args, options = {}) {
89
112
  throw new Error(`workflow adaptater ${i + 1}: ${e}`);
90
113
  }
91
114
  break;
115
+ case "cmd":
116
+ try {
117
+ const { found, path } = getFeatureSpec(step.name, "cmd");
118
+ if (!found) {
119
+ throw new Error(`Command ${step.name} not found`);
120
+ }
121
+ const url = pathToFileURL(path).href;
122
+ const jsa = await import(url);
123
+ if (!jsa?.runCmd) {
124
+ runtimeError(`workflow ${wname}: can not import the runCmd function from step ${i} for command ${step.name}: please add a runCmd function export`);
125
+ return;
126
+ }
127
+ const cres = await jsa.runCmd(args, options);
128
+ if (typeof cres == "string" || Array.isArray(cres)) {
129
+ taskRes.args = cres;
130
+ }
131
+ else {
132
+ taskRes = { ...cres, ...taskRes };
133
+ }
134
+ }
135
+ catch (e) {
136
+ throw new Error(`workflow command ${i + 1}: ${e}`);
137
+ }
138
+ break;
92
139
  default:
93
- throw new Error(`unknown task type ${step.type} in workflow ${name}`);
140
+ throw new Error(`unknown workflow step type ${step.type} in workflow ${wname}`);
94
141
  }
95
142
  prevStepType = step.type;
96
143
  ++i;
@@ -1,104 +1,17 @@
1
- import { Agent } from '@agent-smith/agent';
2
- import { Task } from '@agent-smith/task';
3
1
  import { default as fs } from "fs";
4
2
  import YAML from 'yaml';
5
- import { backend } from '../../../state/backends.js';
6
3
  import { getFeatureSpec } from '../../../state/features.js';
7
- import { readTask } from "../../sys/read_task.js";
8
- import { pythonAction, systemAction } from '../actions/cmd.js';
9
- import { createJsAction } from '../actions/read.js';
10
- import { pathToFileURL } from 'url';
11
4
  async function _createWorkflowFromSpec(spec) {
12
5
  const steps = [];
13
- let i = 1;
14
6
  for (const step of spec.steps) {
15
7
  const type = Object.keys(step)[0];
16
8
  const sval = step[type];
17
9
  const name = sval;
18
- if (type == "action") {
19
- const { found, path, ext } = getFeatureSpec(name, "action");
20
- if (!found) {
21
- throw new Error(`Action ${name} not found`);
22
- }
23
- switch (ext) {
24
- case "js":
25
- const url = pathToFileURL(path).href;
26
- const { action } = await import(url);
27
- const at = action;
28
- const wf = {
29
- name: name,
30
- type: "action",
31
- run: at,
32
- };
33
- steps.push(wf);
34
- break;
35
- case "mjs":
36
- const url2 = pathToFileURL(path).href;
37
- const mjsa = await import(url2);
38
- const act = createJsAction(mjsa.action);
39
- const wf2 = {
40
- name: name,
41
- type: "action",
42
- run: act,
43
- };
44
- steps.push(wf2);
45
- break;
46
- case "yml":
47
- const _t1 = systemAction(path);
48
- const wf3 = {
49
- name: name,
50
- type: "action",
51
- run: _t1,
52
- };
53
- steps.push(wf3);
54
- break;
55
- case "py":
56
- const _t = pythonAction(path);
57
- const wf4 = {
58
- name: name,
59
- type: "action",
60
- run: _t,
61
- };
62
- steps.push(wf4);
63
- break;
64
- default:
65
- throw new Error(`Unknown feature extension ${ext}`);
66
- }
67
- }
68
- else if (type == "adaptater") {
69
- const { found, path } = getFeatureSpec(name, "adaptater");
70
- if (!found) {
71
- throw new Error(`Adaptater ${name} not found`);
72
- }
73
- const url = pathToFileURL(path).href;
74
- const jsa = await import(url);
75
- const act = createJsAction(jsa.action);
76
- const wf = {
77
- name: name,
78
- type: "adaptater",
79
- run: act,
80
- };
81
- steps.push(wf);
82
- }
83
- else {
84
- const { found, path } = getFeatureSpec(name, "task");
85
- if (!found) {
86
- throw new Error(`Task ${name} not found`);
87
- }
88
- const res = readTask(path);
89
- if (!res.found) {
90
- throw new Error(`Unable to read task ${name} ${path}`);
91
- }
92
- const agent = new Agent(backend.value);
93
- const tsk = Task.fromYaml(agent, res.ymlTask);
94
- const wf = {
95
- name: name,
96
- type: "task",
97
- run: tsk.run,
98
- };
99
- steps.push(wf);
100
- }
101
- ++i;
10
+ const wf = {
11
+ name: name,
12
+ type: type == "command" ? "cmd" : type,
13
+ };
14
+ steps.push(wf);
102
15
  }
103
16
  return steps;
104
17
  }
@@ -6,10 +6,8 @@ function _readDir(dir, ext) {
6
6
  const filepath = path.join(dir, filename);
7
7
  const isDir = fs.statSync(filepath).isDirectory();
8
8
  if (!isDir) {
9
- for (let extension of ext) {
10
- if (filename.endsWith(extension)) {
11
- fileNames.push(filename);
12
- }
9
+ if (ext.includes(path.extname(filename))) {
10
+ fileNames.push(filename);
13
11
  }
14
12
  }
15
13
  });
@@ -22,6 +20,7 @@ function readFeaturesDir(dir) {
22
20
  cmd: [],
23
21
  workflow: [],
24
22
  adaptater: [],
23
+ agent: [],
25
24
  };
26
25
  let dirpath = path.join(dir, "tasks");
27
26
  if (fs.existsSync(dirpath)) {
@@ -37,6 +36,20 @@ function readFeaturesDir(dir) {
37
36
  });
38
37
  });
39
38
  }
39
+ dirpath = path.join(dir, "agents");
40
+ if (fs.existsSync(dirpath)) {
41
+ const data = _readDir(dirpath, [".yml"]);
42
+ data.forEach((filename) => {
43
+ const parts = filename.split(".");
44
+ const ext = parts.pop();
45
+ const name = parts.join("");
46
+ feats.agent.push({
47
+ name: name,
48
+ path: path.join(dirpath),
49
+ ext: ext,
50
+ });
51
+ });
52
+ }
40
53
  dirpath = path.join(dir, "workflows");
41
54
  if (fs.existsSync(dirpath)) {
42
55
  const data = _readDir(dirpath, [".yml"]);
package/dist/db/read.js CHANGED
@@ -43,8 +43,9 @@ function readFeaturesType(type) {
43
43
  }
44
44
  function readFeatures() {
45
45
  const feats = {
46
- task: {}, action: {}, cmd: {}, workflow: {}, adaptater: {}
46
+ task: {}, action: {}, cmd: {}, workflow: {}, adaptater: {}, agent: {}
47
47
  };
48
+ feats.agent = readFeaturesType("agent");
48
49
  feats.task = readFeaturesType("task");
49
50
  feats.action = readFeaturesType("action");
50
51
  feats.cmd = readFeaturesType("cmd");
@@ -19,6 +19,13 @@ const tasks = `CREATE TABLE IF NOT EXISTS task (
19
19
  variables TEXT,
20
20
  ext TEXT NOT NULL CHECK ( ext IN ('yml') )
21
21
  );`;
22
+ const agents = `CREATE TABLE IF NOT EXISTS agent (
23
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
24
+ name TEXT UNIQUE NOT NULL,
25
+ path TEXT NOT NULL,
26
+ variables TEXT,
27
+ ext TEXT NOT NULL CHECK ( ext IN ('yml') )
28
+ );`;
22
29
  const workflow = `CREATE TABLE IF NOT EXISTS workflow (
23
30
  id INTEGER PRIMARY KEY AUTOINCREMENT,
24
31
  name TEXT UNIQUE NOT NULL,
@@ -51,12 +58,12 @@ const tool = `CREATE TABLE IF NOT EXISTS tool (
51
58
  id INTEGER PRIMARY KEY AUTOINCREMENT,
52
59
  name TEXT UNIQUE NOT NULL,
53
60
  spec TEXT NOT NULL,
54
- type TEXT NOT NULL CHECK ( type IN ('task', 'action', 'workflow') )
61
+ type TEXT NOT NULL CHECK ( type IN ('agent', 'task', 'action', 'workflow') )
55
62
  );`;
56
63
  const alias = `CREATE TABLE IF NOT EXISTS aliases (
57
64
  id INTEGER PRIMARY KEY AUTOINCREMENT,
58
65
  name TEXT UNIQUE NOT NULL,
59
- type TEXT NOT NULL CHECK ( type IN ('task', 'action', 'workflow') )
66
+ type TEXT NOT NULL CHECK ( type IN ('agent', 'task', 'action', 'workflow') )
60
67
  );`;
61
68
  const backend = `CREATE TABLE IF NOT EXISTS backend (
62
69
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -93,5 +100,6 @@ const schemas = [
93
100
  adaptater,
94
101
  backend,
95
102
  tasksSettings,
103
+ agents,
96
104
  ];
97
105
  export { schemas };
package/dist/db/write.js CHANGED
@@ -96,6 +96,9 @@ function updateAliases(feats) {
96
96
  const deleteStmt = db.prepare("DELETE FROM aliases");
97
97
  deleteStmt.run();
98
98
  let existingAliases = new Array();
99
+ feats.agent.forEach((feat) => {
100
+ existingAliases = _updateAlias(existingAliases, feat.name, "agent");
101
+ });
99
102
  feats.task.forEach((feat) => {
100
103
  existingAliases = _updateAlias(existingAliases, feat.name, "task");
101
104
  });
@@ -158,6 +161,16 @@ function upsertTool(name, type, toolDoc) {
158
161
  }
159
162
  }
160
163
  function updateFeatures(feats) {
164
+ upsertAndCleanFeatures(feats.agent, "agent");
165
+ feats.agent.forEach((feat) => {
166
+ const { toolDoc, variables } = extractTaskToolDocAndVariables(feat.name, feat.ext, feat.path);
167
+ if (toolDoc.length > 0) {
168
+ upsertTool(feat.name, "agent", toolDoc);
169
+ }
170
+ if (Object.keys(variables.required).length > 0 || Object.keys(variables.optional).length > 0) {
171
+ updateVariables(feat.name, JSON.stringify(variables, null, " "));
172
+ }
173
+ });
161
174
  upsertAndCleanFeatures(feats.task, "task");
162
175
  feats.task.forEach((feat) => {
163
176
  const { toolDoc, variables } = extractTaskToolDocAndVariables(feat.name, feat.ext, feat.path);
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import { query } from "./cli.js";
4
4
  import { buildCmds, parseCmd } from './cmd/cmds.js';
5
5
  import { formatMode, init, inputMode, isChatMode, outputMode, runMode } from './state/state.js';
6
6
  import { updateConfCmd } from './cmd/clicmds/updateconf.js';
7
+ import { resetDbCmd } from './cmd/clicmds/cmds.js';
7
8
  async function main() {
8
9
  const nargs = argv.length;
9
10
  if (nargs == 2) {
@@ -14,6 +15,10 @@ async function main() {
14
15
  await updateConfCmd(argv.slice(-1));
15
16
  return;
16
17
  }
18
+ else if (argv[2] == "reset") {
19
+ await resetDbCmd();
20
+ return;
21
+ }
17
22
  }
18
23
  await init();
19
24
  const program = await buildCmds();
@@ -8,6 +8,11 @@ interface FeatureSpec {
8
8
  variables?: TaskVariables;
9
9
  }
10
10
  interface Features {
11
+ agent: Array<{
12
+ name: string;
13
+ path: string;
14
+ ext: AgentExtension;
15
+ }>;
11
16
  task: Array<{
12
17
  name: string;
13
18
  path: string;
@@ -100,7 +105,6 @@ interface FinalLmTaskConfig {
100
105
  interface WorkflowStep {
101
106
  name: string;
102
107
  type: string;
103
- run: FeatureExecutor;
104
108
  }
105
109
  interface McpServerSpec {
106
110
  command: string;
@@ -136,14 +140,15 @@ type OutputMode = "txt" | "clipboard";
136
140
  type RunMode = "cli" | "cmd";
137
141
  type FormatMode = "text" | "markdown";
138
142
  type VerbosityMode = "quiet" | "verbose" | "debug";
139
- type FeatureType = "task" | "action" | "cmd" | "workflow" | "adaptater";
140
- type ToolType = "task" | "action" | "cmd" | "workflow";
143
+ type FeatureType = "task" | "agent" | "action" | "cmd" | "workflow" | "adaptater";
144
+ type ToolType = "task" | "agent" | "action" | "cmd" | "workflow";
141
145
  type ActionExtension = "js" | "mjs" | "py" | "yml";
142
146
  type TaskExtension = "yml";
147
+ type AgentExtension = "yml";
143
148
  type AdaptaterExtension = "js";
144
149
  type WorkflowExtension = "yml";
145
150
  type CmdExtension = "js";
146
- type FeatureExtension = TaskExtension | CmdExtension | ActionExtension | WorkflowExtension;
147
- type AliasType = "task" | "action" | "workflow";
151
+ type FeatureExtension = TaskExtension | AgentExtension | CmdExtension | ActionExtension | WorkflowExtension;
152
+ type AliasType = "task" | "agent" | "action" | "workflow";
148
153
  type FeatureExecutor<I = any, O = any> = (params: I, options: Record<string, any>) => Promise<O>;
149
- export { InputMode, VerbosityMode, OutputMode, RunMode, FormatMode, FeatureType, ActionExtension, TaskExtension, WorkflowExtension, AdaptaterExtension, CmdExtension, FeatureSpec, Features, ConfigFile, FeatureExtension, AliasType, ToolType, Settings, DbModelDef, ModelSpec, ModelfileSpec, ModelPack, LmTaskFileSpec, LmTaskConfig, FinalLmTaskConfig, McpServerSpec, McpServerTool, InferenceBackend, ConfInferenceBackend, FeatureExecutor, WorkflowStep, TaskSettings, };
154
+ export { InputMode, VerbosityMode, OutputMode, RunMode, FormatMode, FeatureType, ActionExtension, TaskExtension, AgentExtension, WorkflowExtension, AdaptaterExtension, CmdExtension, FeatureSpec, Features, ConfigFile, FeatureExtension, AliasType, ToolType, Settings, DbModelDef, ModelSpec, ModelfileSpec, ModelPack, LmTaskFileSpec, LmTaskConfig, FinalLmTaskConfig, McpServerSpec, McpServerTool, InferenceBackend, ConfInferenceBackend, FeatureExecutor, WorkflowStep, TaskSettings, };
@@ -1 +1,4 @@
1
- export const cmds: any[];
1
+ import { Command } from "commander";
2
+ declare const cmds: Command[];
3
+ declare const isCacheReady = false;
4
+ export { cmds, isCacheReady, };
@@ -1,2 +1,3 @@
1
1
  const cmds = new Array();
2
- export { cmds };
2
+ const isCacheReady = false;
3
+ export { cmds, isCacheReady, };
@@ -8,9 +8,11 @@ function readFeaturesDirs(featuresPaths) {
8
8
  cmd: [],
9
9
  workflow: [],
10
10
  adaptater: [],
11
+ agent: [],
11
12
  };
12
13
  featuresPaths.forEach((dir) => {
13
14
  const _f = readFeaturesDir(dir);
15
+ _f.agent.forEach((item) => feats.agent.push(item));
14
16
  _f.task.forEach((item) => feats.task.push(item));
15
17
  _f.action.forEach((item) => feats.action.push(item));
16
18
  _f.cmd.forEach((item) => feats.cmd.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.102",
5
+ "version": "0.0.104",
6
6
  "scripts": {
7
7
  "buildrl": "rm -rf dist/* && rollup -c",
8
8
  "build": "rm -rf dist/* && tsc",
@@ -17,7 +17,7 @@
17
17
  "@inquirer/prompts": "^8.1.0",
18
18
  "@intrinsicai/gbnfgen": "0.12.0",
19
19
  "@locallm/api": "^0.7.3",
20
- "@modelcontextprotocol/sdk": "^1.25.1",
20
+ "@modelcontextprotocol/sdk": "^1.25.2",
21
21
  "@vue/reactivity": "^3.5.26",
22
22
  "ansi-colors": "^4.1.3",
23
23
  "better-sqlite3": "^12.5.0",
@@ -40,7 +40,7 @@
40
40
  "@types/node": "^25.0.3",
41
41
  "openai": "^6.15.0",
42
42
  "restmix": "^0.6.1",
43
- "rollup": "^4.54.0",
43
+ "rollup": "^4.55.1",
44
44
  "ts-node": "^10.9.2",
45
45
  "tslib": "2.8.1",
46
46
  "typescript": "^5.9.3"