@agent-smith/cli 0.0.46 → 0.0.47

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/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # Agent Smith terminal client
2
+
3
+ A terminal client to use language models
4
+
5
+ :books: Read the [documentation](https://synw.github.io/agent-smith/terminal_client/install)
6
+
7
+ ## Install
8
+
9
+ Install the Agent Smith terminal client globally:
10
+
11
+ ```bash
12
+ npm i -g @agent-smith/cli
13
+ ```
14
+
15
+ A global `lm` command is available once installed.
16
+
17
+ ## Quickstart
18
+
19
+ Install the inference and the vision plugin:
20
+
21
+ ```bash
22
+ npm i -g @agent-smith/feat-inference @agent-smith/feat-vision
23
+ ```
24
+
25
+ Create a `config.yml` file with this content:
26
+
27
+ ```yml
28
+ plugins:
29
+ - "@agent-smith/feat-inference"
30
+ - "@agent-smith/feat-vision"
31
+ - "@agent-smith/feat-models"
32
+ ```
33
+
34
+ Run the conf command to initialize:
35
+
36
+ ```bash
37
+ lm conf ~/path/to/config.yml
38
+ ```
39
+
40
+ ### Inference
41
+
42
+ Run an inference query with the <kbd>q</kbd> command, using an Ollama model that you already have:
43
+
44
+ ```bash
45
+ lm q list the planets of the solar system m="llama3.1:latest"
46
+ ```
47
+
48
+ ### Vision
49
+
50
+ Run a vision query: pull `minicpm-v:8b-2.6-q8_0` from Ollama and run:
51
+
52
+ ```bash
53
+ lm vision imgs/img1.jpeg imgs/img2.jpeg "Compare the images"
54
+ ```
55
+
56
+ ### Tasks
57
+
58
+ List the available tasks:
59
+
60
+ ```bash
61
+ lm tasks
62
+ ```
63
+
64
+ Show a task:
65
+
66
+ ```bash
67
+ lm task think
68
+ ```
69
+
70
+ ### Models
71
+
72
+ Show available models:
73
+
74
+ ```bash
75
+ lm models
76
+ ```
77
+
78
+ Search for a model:
79
+
80
+ ```bash
81
+ lm model qwen
82
+ ```
@@ -3,4 +3,5 @@ declare let cmds: Record<string, Cmd>;
3
3
  declare function initAliases(): Record<string, Cmd>;
4
4
  declare function initCmds(): Promise<Record<string, Cmd>>;
5
5
  declare function pingCmd(args: Array<string> | undefined, options: any): Promise<boolean>;
6
- export { cmds, initCmds, pingCmd, initAliases };
6
+ declare function updateConfCmd(args: Array<string> | undefined, options: any): Promise<any>;
7
+ export { cmds, initCmds, pingCmd, initAliases, updateConfCmd };
@@ -1,17 +1,19 @@
1
1
  import YAML from 'yaml';
2
- import { dataDirPath, formatMode, isChatMode, promptfilePath, runMode } from "../../state/state.js";
2
+ import { dataDirPath, isChatMode, isDebug, promptfilePath, runMode } from "../../state/state.js";
3
3
  import { getFeatureSpec, readFeaturesDirs } from "../../state/features.js";
4
- import { readAliases, readFeatures } from "../../db/read.js";
4
+ import { readAliases, readFeaturePaths, readFeatures } from "../../db/read.js";
5
5
  import { cleanupFeaturePaths, updateAliases, updateDataDirPath, updateFeatures, updatePromptfilePath } from "../../db/write.js";
6
6
  import { processConfPath } from "../../conf.js";
7
7
  import { executeActionCmd } from "../lib/actions/cmd.js";
8
- import { initAgent, marked, taskBuilder } from "../../agent.js";
8
+ import { initAgent, taskBuilder } from "../../agent.js";
9
9
  import { executeTaskCmd } from "../lib/tasks/cmd.js";
10
10
  import { readCmds } from "../sys/read_cmds.js";
11
11
  import { executeWorkflowCmd } from "../lib/workflows/cmd.js";
12
12
  import { readTask } from "../sys/read_task.js";
13
13
  import { deleteFileIfExists } from "../sys/delete_file.js";
14
- import { dbPath } from "../../db/db.js";
14
+ import { dbPath, initDb } from "../../db/db.js";
15
+ import { showModelsCmd, updateModels } from '../lib/models.js';
16
+ import { readPluginsPaths } from '../../state/plugins.js';
15
17
  let cmds = {
16
18
  exit: {
17
19
  cmd: async () => process.exit(0),
@@ -30,8 +32,16 @@ let cmds = {
30
32
  description: "read a task",
31
33
  args: "arguments: \n-task (required): the task name"
32
34
  },
35
+ models: {
36
+ cmd: showModelsCmd,
37
+ description: "list the available models",
38
+ },
39
+ update: {
40
+ cmd: _updateFeatures,
41
+ description: "update the available features: run this after adding a new feature",
42
+ },
33
43
  conf: {
34
- cmd: _updateConfCmd,
44
+ cmd: updateConfCmd,
35
45
  description: "process config file",
36
46
  args: "arguments: \n-path (required): the path to the config.yml file"
37
47
  },
@@ -77,11 +87,25 @@ async function pingCmd(args = [], options) {
77
87
  const isUp = await initAgent();
78
88
  return isUp;
79
89
  }
80
- async function _updateConfCmd(args = [], options) {
90
+ async function _updateFeatures(args = [], options) {
91
+ const fp = readFeaturePaths();
92
+ const pp = await readPluginsPaths();
93
+ const paths = [...fp, ...pp];
94
+ const feats = readFeaturesDirs(paths);
95
+ updateFeatures(feats);
96
+ updateAliases(feats);
97
+ updateModels();
98
+ const deleted = cleanupFeaturePaths(paths);
99
+ for (const el of deleted) {
100
+ console.log("- [feature path]", el);
101
+ }
102
+ }
103
+ async function updateConfCmd(args = [], options) {
81
104
  if (args.length == 0) {
82
105
  console.warn("Provide a config.yml file path");
83
106
  return;
84
107
  }
108
+ initDb(isDebug.value, true);
85
109
  const { paths, pf, dd } = await processConfPath(args[0]);
86
110
  if (pf.length > 0) {
87
111
  updatePromptfilePath(pf);
@@ -94,6 +118,7 @@ async function _updateConfCmd(args = [], options) {
94
118
  const feats = readFeaturesDirs(paths);
95
119
  updateFeatures(feats);
96
120
  updateAliases(feats);
121
+ updateModels();
97
122
  const deleted = cleanupFeaturePaths(paths);
98
123
  for (const el of deleted) {
99
124
  console.log("- [feature path]", el);
@@ -113,13 +138,6 @@ async function _executeTaskCmd(args = [], options) {
113
138
  return;
114
139
  }
115
140
  const res = await executeTaskCmd(args, options);
116
- if (formatMode.value == "markdown") {
117
- console.log("\n------------------\n");
118
- console.log(marked.parse(res.answer.text).trim());
119
- }
120
- else {
121
- console.log();
122
- }
123
141
  if (isChatMode.value) {
124
142
  }
125
143
  return res;
@@ -154,4 +172,4 @@ async function _listTasksCmd(args = [], options) {
154
172
  const ts = Object.keys(readFeatures().task).sort();
155
173
  console.table(ts);
156
174
  }
157
- export { cmds, initCmds, pingCmd, initAliases };
175
+ export { cmds, initCmds, pingCmd, initAliases, updateConfCmd };
@@ -4,7 +4,6 @@ import { readYmlAction } from "../../sys/read_yml_action.js";
4
4
  import { execute } from "../../sys/execute.js";
5
5
  import { runPyScript } from "../../sys/run_python.js";
6
6
  import { pyShell } from "../../../state/state.js";
7
- import { processOutput } from "../utils.js";
8
7
  import { createJsAction } from "./read.js";
9
8
  function systemAction(path) {
10
9
  const action = useAgentTask({
@@ -84,7 +83,6 @@ async function executeActionCmd(args = [], options = {}, quiet = false) {
84
83
  console.log(res);
85
84
  }
86
85
  }
87
- await processOutput(res);
88
86
  return res;
89
87
  }
90
88
  export { executeActionCmd, systemAction, pythonAction };
@@ -1,5 +1,4 @@
1
1
  import { getFeatureSpec } from "../../../state/features.js";
2
- import { processOutput } from "../utils.js";
3
2
  import { createJsAction } from "../actions/read.js";
4
3
  async function executeAdaptaterCmd(args = [], options = {}) {
5
4
  const isWorkflow = !Array.isArray(args);
@@ -31,7 +30,6 @@ async function executeAdaptaterCmd(args = [], options = {}) {
31
30
  if (res?.error) {
32
31
  throw res.error;
33
32
  }
34
- await processOutput(res);
35
33
  return res;
36
34
  }
37
35
  export { executeAdaptaterCmd, };
@@ -1,2 +1,3 @@
1
+ declare function showModelsCmd(args: Array<string>, options: any): Promise<void>;
1
2
  declare function updateModels(): void;
2
- export { updateModels, };
3
+ export { updateModels, showModelsCmd, };
@@ -1,7 +1,28 @@
1
1
  import path from "path";
2
- import { readModelfiles } from "../../db/read.js";
2
+ import { readModelfiles, readModels } from "../../db/read.js";
3
3
  import { readModelsFile } from "../sys/read_modelfile.js";
4
4
  import { upsertModels } from "../../db/write.js";
5
+ import color from "ansi-colors";
6
+ async function showModelsCmd(args, options) {
7
+ let models = readModels();
8
+ models.sort((a, b) => a.name.localeCompare(b.name));
9
+ if (args.length > 0) {
10
+ args.forEach((a) => {
11
+ models = models.filter((m) => m.shortname.includes(a) || m.name.includes(a));
12
+ });
13
+ }
14
+ models.forEach((model) => {
15
+ const ips = model.data.inferParams;
16
+ if (!ips?.max_tokens) {
17
+ throw new Error(`no max tokens in ${model.shortname}`);
18
+ }
19
+ const mt = ips.max_tokens;
20
+ delete ips.max_tokens;
21
+ const vip = Object.keys(ips).length > 0 ? JSON.stringify(ips) : "";
22
+ const m = `- ${color.yellow(model.shortname)}: ${color.bold(model.data.name)} - ${model.data.ctx} ctx / ${mt} max tokens ${vip}`;
23
+ console.log(m);
24
+ });
25
+ }
5
26
  function updateModels() {
6
27
  const mfs = readModelfiles();
7
28
  const modelNames = new Array();
@@ -32,4 +53,4 @@ function updateModels() {
32
53
  upsertModels(modelDefs);
33
54
  });
34
55
  }
35
- export { updateModels, };
56
+ export { updateModels, showModelsCmd, };
@@ -1,9 +1,8 @@
1
- import { useTemplateForModel } from "@agent-smith/tfm";
2
- import { inputMode, outputMode, promptfilePath } from "../../state/state.js";
1
+ import { formatMode, initFilepaths, inputMode, outputMode, promptfilePath } from "../../state/state.js";
3
2
  import { modes } from "../clicmds/modes.js";
4
3
  import { readClipboard, writeToClipboard } from "../sys/clipboard.js";
5
4
  import { readFile } from "../sys/read.js";
6
- const tfm = useTemplateForModel();
5
+ import { marked } from "../../agent.js";
7
6
  async function setOptions(args = [], options) {
8
7
  for (const k of Object.keys(options)) {
9
8
  let opt;
@@ -26,16 +25,16 @@ async function setOptions(args = [], options) {
26
25
  return args;
27
26
  }
28
27
  function readPromptFile() {
28
+ initFilepaths();
29
29
  return readFile(promptfilePath.value);
30
30
  }
31
31
  async function processOutput(res) {
32
- if (!(outputMode.value == "clipboard")) {
33
- return;
34
- }
35
32
  let data = "";
33
+ let hasTextData = false;
36
34
  if (typeof res == "object") {
37
35
  if (res?.answer?.text) {
38
36
  data = res.answer.text;
37
+ hasTextData = true;
39
38
  }
40
39
  else {
41
40
  data = JSON.stringify(res);
@@ -45,11 +44,14 @@ async function processOutput(res) {
45
44
  data = res;
46
45
  }
47
46
  if (outputMode.value == "clipboard") {
48
- if (typeof data == "object") {
49
- data = JSON.stringify(data);
50
- }
51
47
  await writeToClipboard(data);
52
48
  }
49
+ if (formatMode.value == "markdown") {
50
+ if (hasTextData) {
51
+ console.log("\n------------------\n");
52
+ console.log(marked.parse(data).trim());
53
+ }
54
+ }
53
55
  }
54
56
  async function parseInputOptions(options) {
55
57
  let out = null;
package/dist/conf.d.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  declare const confDir: string;
2
2
  declare const dbPath: string;
3
- declare function createConfDirIfNotExists(): boolean;
4
3
  declare function processConfPath(confPath: string): Promise<{
5
4
  paths: Array<string>;
6
5
  pf: string;
7
6
  dd: string;
8
7
  }>;
9
- export { confDir, dbPath, createConfDirIfNotExists, processConfPath, };
8
+ export { confDir, dbPath, processConfPath, };
package/dist/conf.js CHANGED
@@ -1,17 +1,9 @@
1
1
  import path from "path";
2
- import { default as fs } from "fs";
3
2
  import { readConf } from "./cmd/sys/read_conf.js";
4
3
  import { insertFeaturesPathIfNotExists, insertPluginIfNotExists } from "./db/write.js";
5
4
  import { buildPluginsPaths } from "./state/plugins.js";
6
5
  const confDir = path.join(process.env.HOME, ".config/agent-smith/cli");
7
6
  const dbPath = path.join(confDir, "config.db");
8
- function createConfDirIfNotExists() {
9
- if (!fs.existsSync(confDir)) {
10
- fs.mkdirSync(confDir, { recursive: true });
11
- return false;
12
- }
13
- return true;
14
- }
15
7
  async function processConfPath(confPath) {
16
8
  const { found, data } = readConf(confPath);
17
9
  if (!found) {
@@ -45,4 +37,4 @@ async function processConfPath(confPath) {
45
37
  }
46
38
  return { paths: allPaths, pf: pf, dd: dd };
47
39
  }
48
- export { confDir, dbPath, createConfDirIfNotExists, processConfPath, };
40
+ export { confDir, dbPath, processConfPath, };
package/dist/db/db.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Database } from "better-sqlite3";
2
2
  declare const dbPath: string;
3
3
  declare let db: Database;
4
- declare function initDb(isVerbose?: boolean): void;
4
+ declare function initDb(isVerbose: boolean, execSchema?: boolean): void;
5
5
  export { db, dbPath, initDb, };
package/dist/db/db.js CHANGED
@@ -1,16 +1,21 @@
1
1
  import DatabaseConstructor from "better-sqlite3";
2
2
  import { schemas } from "./schemas.js";
3
3
  import path from "path";
4
- const confDir = path.join(process.env.HOME, ".config/agent-smith/cli");
4
+ const confDir = path.join(process.env.HOME ?? "~/", ".config/agent-smith/cli");
5
5
  const dbPath = path.join(confDir, "config.db");
6
6
  let db;
7
- function initDb(isVerbose = false) {
8
- db = new DatabaseConstructor(dbPath, { fileMustExist: false });
9
- schemas.forEach((s) => {
10
- db.exec(s);
11
- if (isVerbose) {
12
- console.log(`Schema executed: ${s}`);
13
- }
14
- });
7
+ function initDb(isVerbose, execSchema = false) {
8
+ if (execSchema) {
9
+ db = new DatabaseConstructor(dbPath, { fileMustExist: false });
10
+ schemas.forEach((s) => {
11
+ db.exec(s);
12
+ if (isVerbose) {
13
+ console.log(`Schema executed: ${s}`);
14
+ }
15
+ });
16
+ }
17
+ else {
18
+ db = new DatabaseConstructor(dbPath);
19
+ }
15
20
  }
16
21
  export { db, dbPath, initDb, };
package/dist/db/read.js CHANGED
@@ -101,7 +101,13 @@ function readModels() {
101
101
  const data = stmt.all();
102
102
  let f = new Array();
103
103
  data.forEach((row) => {
104
- f.push(row);
104
+ const ips = JSON.parse(row.data);
105
+ const mod = {
106
+ name: row.name,
107
+ shortname: row.shortname,
108
+ data: ips,
109
+ };
110
+ f.push(mod);
105
111
  });
106
112
  return f;
107
113
  }
package/dist/index.js CHANGED
@@ -4,10 +4,18 @@ import { query } from "./cli.js";
4
4
  import { initState, runMode } from './state/state.js';
5
5
  import { initAgent } from './agent.js';
6
6
  import { initCliCmds, parseCmd } from './cmd/cmds.js';
7
+ import { updateConfCmd } from './cmd/clicmds/cmds.js';
7
8
  async function main() {
8
- if (argv.length == 2) {
9
+ const nargs = argv.length;
10
+ if (nargs == 2) {
9
11
  runMode.value = "cli";
10
12
  }
13
+ else if (nargs >= 3) {
14
+ if (argv[2] == "conf") {
15
+ await updateConfCmd(argv.slice(-1), {});
16
+ return;
17
+ }
18
+ }
11
19
  await initState();
12
20
  await initAgent();
13
21
  switch (runMode.value) {
@@ -15,7 +15,7 @@ declare const lastCmd: {
15
15
  name: string;
16
16
  args: Array<string>;
17
17
  };
18
- declare function initFeatures(): Promise<void>;
18
+ declare function initFilepaths(): void;
19
19
  declare function initState(): Promise<void>;
20
20
  declare function pluginDataDir(pluginName: string): string;
21
- export { inputMode, outputMode, isChatMode, isShowTokens, runMode, formatMode, lastCmd, isDebug, isVerbose, promptfilePath, dataDirPath, pluginDataDir, initState, initFeatures, pyShell, };
21
+ export { inputMode, outputMode, isChatMode, isShowTokens, runMode, formatMode, lastCmd, isDebug, isVerbose, promptfilePath, dataDirPath, pluginDataDir, initState, initFilepaths, pyShell, };
@@ -1,13 +1,8 @@
1
1
  import { reactive, ref } from "@vue/reactivity";
2
- import { createConfDirIfNotExists, confDir } from "../conf.js";
3
2
  import { initDb } from "../db/db.js";
4
- import { readFeaturePaths, readFilePaths } from "../db/read.js";
5
- import { updateAliases, updateFeatures } from "../db/write.js";
6
- import { readFeaturesDirs } from "./features.js";
7
- import { readPluginsPaths } from "./plugins.js";
3
+ import { readFilePaths } from "../db/read.js";
8
4
  import path from "path";
9
5
  import { createDirectoryIfNotExists } from "../cmd/sys/dirs.js";
10
- import { updateModels } from "../cmd/lib/models.js";
11
6
  let pyShell;
12
7
  const inputMode = ref("manual");
13
8
  const outputMode = ref("txt");
@@ -24,21 +19,7 @@ const lastCmd = reactive({
24
19
  name: "",
25
20
  args: [],
26
21
  });
27
- function initConf() {
28
- const exists = createConfDirIfNotExists();
29
- if (!exists) {
30
- console.log("Created configuration directory", confDir);
31
- }
32
- initDb();
33
- }
34
- async function initFeatures() {
35
- const fp = readFeaturePaths();
36
- const pp = await readPluginsPaths();
37
- const p = [...fp, ...pp];
38
- const feats = readFeaturesDirs(p);
39
- updateFeatures(feats);
40
- updateAliases(feats);
41
- updateModels();
22
+ function initFilepaths() {
42
23
  const filePaths = readFilePaths();
43
24
  for (const fp of filePaths) {
44
25
  switch (fp.name) {
@@ -54,8 +35,7 @@ async function initState() {
54
35
  if (isStateReady.value) {
55
36
  return;
56
37
  }
57
- initConf();
58
- await initFeatures();
38
+ initDb(isDebug.value);
59
39
  isStateReady.value = true;
60
40
  }
61
41
  function _getDataDirPath() {
@@ -70,4 +50,4 @@ function pluginDataDir(pluginName) {
70
50
  createDirectoryIfNotExists(pluginDatapath);
71
51
  return pluginDatapath;
72
52
  }
73
- export { inputMode, outputMode, isChatMode, isShowTokens, runMode, formatMode, lastCmd, isDebug, isVerbose, promptfilePath, dataDirPath, pluginDataDir, initState, initFeatures, pyShell, };
53
+ export { inputMode, outputMode, isChatMode, isShowTokens, runMode, formatMode, lastCmd, isDebug, isVerbose, promptfilePath, dataDirPath, pluginDataDir, initState, initFilepaths, 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.46",
5
+ "version": "0.0.47",
6
6
  "scripts": {
7
7
  "buildrl": "rm -rf dist/* && rollup -c",
8
8
  "build": "rm -rf dist/* && tsc",
@@ -18,6 +18,7 @@
18
18
  "@inquirer/select": "^4.1.1",
19
19
  "@vue/reactivity": "^3.5.13",
20
20
  "@wllama/wllama": "^2.3.0",
21
+ "ansi-colors": "^4.1.3",
21
22
  "better-sqlite3": "^11.9.1",
22
23
  "clipboardy": "^4.0.0",
23
24
  "commander": "^13.1.0",
@@ -60,4 +61,4 @@
60
61
  "registry": "https://registry.npmjs.org/"
61
62
  },
62
63
  "license": "MIT"
63
- }
64
+ }