@vierratale/ai 0.1.0-beta.14 → 0.1.0-beta.16

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 CHANGED
@@ -4,20 +4,11 @@ Intelligent terminal assistant that runs AI models locally and in the cloud.
4
4
 
5
5
  ## Install
6
6
 
7
- Install requirements and run from source:
8
-
9
- ```bash
10
- git clone <your-repo-url>/vierratale-ai.git
11
- cd vierratale-ai
12
-
13
- ./install.sh --node # installs requirements + links the commands
14
- vierratale # start chatting
15
- ```
16
-
17
- Or run directly from npm:
18
-
19
7
  ```bash
8
+ # From npm
20
9
  npm install -g @vierratale/ai
10
+
11
+ # Or run directly
21
12
  npx @vierratale/ai
22
13
  ```
23
14
 
@@ -32,7 +23,7 @@ vierrataleai --provider cortex # Use local models
32
23
  vierrataleai --provider openai # Use cloud models (OpenAI)
33
24
  vierrataleai --provider anthropic # Use cloud models (Claude)
34
25
  vierrataleai --provider gemini # Use cloud models (Gemini)
35
- vierrataleai --model VRTL-6.pro # Use specific model
26
+ vierrataleai --model vierratale-pro # Use specific model
36
27
  ```
37
28
 
38
29
  ## Models
@@ -41,27 +32,23 @@ Local models run through the **Cortex** engine:
41
32
 
42
33
  | Model | Backend |
43
34
  |-------|---------|
44
- | VRTL-1.lite | qwen3:0.6b |
45
- | VRTL-2.fast | gemma3:1b |
46
- | VRTL-3.small | llama3.2:1b |
47
- | VRTL-4.balanced | qwen2.5:1.5b |
48
- | VRTL-5.plus | qwen3:1.7b |
49
- | VRTL-6.pro | qwen2.5:3b |
35
+ | vierratale-lite | qwen3:0.6b |
36
+ | vierratale-fast | gemma3:1b |
37
+ | vierratale-small | llama3.2:1b |
38
+ | vierratale-balanced | qwen2.5:1.5b |
39
+ | vierratale-plus | qwen3:1.7b |
40
+ | vierratale-pro | qwen2.5:3b |
50
41
 
51
42
  Cloud models are available when the matching provider + API key is configured:
52
43
 
53
44
  | Model | Backend |
54
45
  |-------|---------|
55
- | VRTL-7.cloud-mini | gpt-4o-mini (OpenAI) |
56
- | VRTL-8.cloud | gpt-4o (OpenAI) |
57
- | VRTL-9.cloud-fast | claude-3-5-haiku-20241022 (Anthropic) |
58
- | VRTL-10.cloud-pro | claude-sonnet-4-20250514 (Anthropic) |
59
- | VRTL-11.cloud-lite | gemini-2.0-flash (Gemini) |
60
- | VRTL-12.cloud-plus | gemini-1.5-pro (Gemini) |
61
-
62
- > Legacy `vierratale-*` model names (e.g. `vierratale-fast`, `vierratale-cloud`)
63
-
64
- > still work and are stored as VRTL names.
46
+ | vierratale-cloud-mini | gpt-4o-mini (OpenAI) |
47
+ | vierratale-cloud | gpt-4o (OpenAI) |
48
+ | vierratale-cloud-fast | claude-3-5-haiku-20241022 (Anthropic) |
49
+ | vierratale-cloud-pro | claude-sonnet-4-20250514 (Anthropic) |
50
+ | vierratale-cloud-lite | gemini-2.0-flash (Gemini) |
51
+ | vierratale-cloud-plus | gemini-1.5-pro (Gemini) |
65
52
 
66
53
  ## Commands
67
54
 
@@ -71,8 +58,6 @@ Cloud models are available when the matching provider + API key is configured:
71
58
  - `/models` - List available models
72
59
  - `/system [text]` - Set a custom system prompt / persona
73
60
  - `/search <query>` - Search the web and summarize with AI
74
- - `/fetch <url>` - Open a link and summarize its content
75
- - `/log [n|path]` - Show the last n log entries (default 30) or the log file path
76
61
  - `/clear` - Clear screen
77
62
  - `/new` - Start a new conversation (clear memory)
78
63
  - `/quit` - Exit
@@ -80,112 +65,14 @@ Cloud models are available when the matching provider + API key is configured:
80
65
  ## Smart Search
81
66
 
82
67
  Asking a question (Who/What/When/Where/Why/How...?) automatically searches the
83
- web and summarizes the results with AI. Bare mentions of specific topics also
84
- trigger a search — e.g. `timun mas from indonesia`, `the legend of roro
85
- jonggrang`. For example:
68
+ web and summarizes the results with AI. For example:
86
69
 
87
70
  ```
88
71
  > Who is Cristiano Ronaldo?
89
- > timun mas from indonesia
90
72
  ```
91
73
 
92
- triggers a live web search and answers from the results. If no web results come
93
- back, the AI answers from its own knowledge instead of going quiet. Use
94
- `/search <query>` to force a search explicitly.
95
-
96
- Story requests about any subject work the same way — no matter how they're
97
- phrased (`a story about X`, `the legend of X`, `tell me about X`, `narrate the
98
- tale of X`, `write X into a txt file`). The subject is pulled out of the
99
- sentence, searched first, and the reply is saved to a `<subject>.txt` file.
100
- A generic `tell me a story` (no subject) is told directly from the model — and
101
- is also saved to a `.txt` file.
102
-
103
- Greetings (`hi`, `hello`, `hey`, `good morning`, ...) are answered instantly
104
- with a short fixed reply — they never reach the model.
105
-
106
- ## Writing Files
107
-
108
- Ask the AI to create code, configs, scripts, web pages, or a whole project. When it
109
- responds, it lists each file with a `FILE: <path>` header followed by a code
110
- fence (and `FOLDER: <path>` for empty folders) — just running in the chat writes
111
- them to your disk in the current working directory. Any file type is supported,
112
- including JSON config files and HTML pages. Nested folders are created automatically, existing
113
- files are skipped unless you confirm to overwrite, and nothing is ever written
114
- outside the working directory.
115
-
116
- If the AI ever answers with the code but forgets the `FILE:` header (or writes an
117
- HTML page without a fence), the assistant rescues it: any `FILE: <path>` line in
118
- the reply is honored even without a fence, otherwise the request is used to
119
- infer a filename and the code block is saved anyway. Filename inference covers
120
- many formats, not just web pages:
121
-
122
- | Request contains… | Saved as |
123
- |--------------------|----------|
124
- | `html` / `webpage` / `website` / `page` | `index.html` |
125
- | `css` | `style.css` |
126
- | `python` / `py` | `script.py` |
127
- | `flask` / `django` / `fastapi` / `streamlit` / `app` | `app.py` |
128
- | `javascript` / `js` / `script` | `script.js` |
129
- | `typescript` / `ts` | `script.ts` |
130
- | `bash` / `zsh` / `shell` | `script.sh` |
131
- | `json` / `yaml` / `yml` / `csv` / `sql` | `output.json` / `.yml` / `.csv` / `.sql` |
132
-
133
- When the request has no hint at all, the fence language in the reply picks the
134
- name (```python → `script.py`, ```css → `style.css`, …). Saving also kicks in
135
- whenever the reply itself contains a `FILE:`/`FOLDER:` line, or when a reply is
136
- basically just one substantial code block, even if the request phrasing wasn't
137
- matched.
138
-
139
- For file requests, a short format instruction is silently attached to your
140
- message so the model emits complete `FILE:` blocks with closed fences. And if
141
- the model ever answers a file request *without any code* (free-style prose,
142
- interrupted before a fence), nothing is saved and you get a notice telling you
143
- to ask again — a `.py` file full of chatter is never created.
144
-
145
- Example of what the AI emits:
146
-
147
- ```
148
- FILE: config.json
149
- ```json
150
- {
151
- "name": "my-app",
152
- "port": 3000
153
- }
154
- ```
155
-
156
- FILE: index.html
157
- ```html
158
- <!doctype html>
159
- <html><body>Hello</body></html>
160
- ```
161
-
162
- FILE: src/hello.js
163
- ```js
164
- console.log('Hello VierrataleAI');
165
- ```
166
-
167
- ## Chat UI
168
-
169
- The chat runs in a clean, minimal full-screen interface: your turns are labelled
170
- `You` and the assistant's `AI`, with plain wrapped text in between. Code blocks
171
- are the exception — they render inside a green bordered box with their language
172
- tag (`╭─ html ─╮`), so files stand out at a glance. The latest reply stays pinned
173
- to the bottom of the terminal while it streams in (no screen flashing), and
174
- internal search/fetch context stays hidden.
175
-
176
- ## Automatic Logging
177
-
178
- Everything that happens in a session is written automatically to a per-day log
179
- file in `~/.config/vierrataleai/logs/` (e.g. `vierrataleai-20260101.log`):
180
- app/session start, every user message, every AI reply, every file write or
181
- skip, and any errors — with a timestamp. The logs are plain text and safe to
182
- grep. To inspect them from inside the chat:
183
-
184
- ```
185
- /log # show the last 30 entries
186
- /log 100 # show the last 100 entries
187
- /log path # print the log file path
188
- ```
74
+ triggers a live web search and answers from the results. Use `/search <query>`
75
+ to force a search explicitly.
189
76
 
190
77
  ## Conversation Memory
191
78
 
@@ -1,78 +1,3 @@
1
1
  #!/usr/bin/env node
2
- // VierrataleAI launcher + installer.
3
- //
4
- // Running without flags starts the assistant and auto-detects dependencies:
5
- // if the AI engine (ollama) or the model is missing, they are installed first.
6
- // Running with --install (or --setup / install) additionally creates a global
7
- // "vierrataleai" / "vierratale" command, then starts the assistant.
8
- //
9
- // Installation progress is always the fake animated bar — real engine/model
10
- // output is deliberately hidden so first-run feels quick and clean.
11
2
  import { run } from '../src/cli.js';
12
- import { Engine } from '../src/engine.js';
13
- import { Config } from '../src/config.js';
14
- import { Branding } from '../src/ui/branding.js';
15
-
16
- const C = Branding.colors;
17
-
18
- const INSTALL_STEPS = [
19
- 'Checking the AI engine',
20
- 'Installing dependencies',
21
- 'Downloading the model',
22
- 'Linking the vierrataleai command',
23
- 'Optimizing for this device',
24
- ];
25
-
26
- const READY_STEPS = ['Checking engine', 'Installing dependencies', 'Downloading model', 'Optimizing'];
27
-
28
- function delay(ms) {
29
- return new Promise((r) => setTimeout(r, ms));
30
- }
31
-
32
- async function fakeProgress(steps, work) {
33
- const frames = ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'];
34
- let i = 0;
35
- const tty = process.stdout.isTTY;
36
- const timer = setInterval(() => {
37
- if (!tty) return;
38
- i++;
39
- const stage = steps[Math.floor((i / 10) % steps.length)];
40
- const pct = String(8 + ((i * 7) % 85)).padStart(3, ' ');
41
- const bar = frames[i % frames.length];
42
- const fillLen = 1 + (i % 20);
43
- const fill = '█'.repeat(fillLen) + '░'.repeat(Math.max(0, 20 - fillLen));
44
- process.stdout.write(`\r ${C.accent}${bar}${C.reset} ${C.bold}${pct}%${C.reset} ${C.dim}${stage}${C.reset} [${C.accent}${fill}${C.reset}]`);
45
- }, 110);
46
- try {
47
- return await work;
48
- } finally {
49
- clearInterval(timer);
50
- if (tty) process.stdout.write('\r\x1b[2K');
51
- process.stdout.write(` ${C.success}✔${C.reset} ${C.bold}${C.dim}100%${C.reset} ${C.dim}Ready${C.reset}\n`);
52
- }
53
- }
54
-
55
- async function main() {
56
- const args = process.argv.slice(2);
57
- const doInstall = args.includes('--install') || args.includes('--setup') || args.includes('install');
58
- const quick = args.includes('--version') || args.includes('-v') || args.includes('--help') || args.includes('-h');
59
-
60
- Config.load();
61
-
62
- if (doInstall) {
63
- console.log(`\n ${C.bold}${C.primary}${Branding.APP_NAME} ${Branding.VERSION}${C.reset} ${C.dim}— installer${C.reset}\n`);
64
- await fakeProgress(INSTALL_STEPS, Engine.ensure());
65
- console.log();
66
- } else if (!quick) {
67
- // Auto-detect: install anything that's missing (engine, model) before starting.
68
- await fakeProgress(READY_STEPS, Engine.ensure());
69
- console.log();
70
- }
71
-
72
- return run();
73
- }
74
-
75
- main().catch((err) => {
76
- console.error(err);
77
- process.exit(1);
78
- });
3
+ run();
package/build.sh ADDED
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+ # Build VierrataleAI Node.js version for packaging
3
+ set -e
4
+
5
+ cd "$(dirname "$0")"
6
+
7
+ echo "Installing dependencies..."
8
+ npm install
9
+
10
+ echo "Testing..."
11
+ node bin/vierrataleai.js --version
12
+
13
+ echo "Packaging..."
14
+ npm pack
15
+
16
+ echo "Build complete!"
17
+ echo "To publish: npm publish --tag beta"
package/package.json CHANGED
@@ -1,31 +1,25 @@
1
1
  {
2
2
  "name": "@vierratale/ai",
3
- "version": "0.1.0-beta.14",
3
+ "version": "0.1.0-beta.16",
4
4
  "description": "VierrataleAI - Intelligent terminal assistant",
5
5
  "type": "module",
6
- "license": "MIT",
7
- "engines": {
8
- "node": ">=18"
9
- },
10
6
  "bin": {
11
- "vierrataleai": "./bin/vierrataleai.js",
12
- "vierratale": "./bin/vierrataleai.js"
7
+ "vierrataleai": "./bin/vierrataleai.js"
8
+ },
9
+ "main": "./src/index.js",
10
+ "exports": {
11
+ ".": "./src/index.js"
13
12
  },
14
13
  "scripts": {
14
+ "start": "node bin/vierrataleai.js",
15
+ "test": "node --test test/",
15
16
  "postinstall": "node scripts/postinstall.js"
16
17
  },
17
- "files": [
18
- "bin",
19
- "src",
20
- "scripts",
21
- "LICENSE",
22
- "README.md"
23
- ],
24
- "keywords": [
25
- "ai",
26
- "chatbot",
27
- "terminal",
28
- "assistant",
29
- "llm"
30
- ]
31
- }
18
+ "keywords": ["ai", "chatbot", "terminal", "assistant", "llm"],
19
+ "author": "Vierratale",
20
+ "license": "MIT",
21
+ "engines": {
22
+ "node": ">=18.0.0"
23
+ },
24
+ "dependencies": {}
25
+ }
package/src/catalog.js CHANGED
@@ -1,36 +1,16 @@
1
- // Model catalog. Display names use the countable VRTL branding:
2
- // VRTL-<number>.<word>, e.g. VRTL-2.fast, VRTL-7.cloud-mini.
3
1
  const MODELS = {
4
- 'qwen3:0.6b': 'VRTL-1.lite',
5
- 'gemma3:1b': 'VRTL-2.fast',
6
- 'llama3.2:1b': 'VRTL-3.small',
7
- 'qwen2.5:1.5b': 'VRTL-4.balanced',
8
- 'qwen2.5-coder:1.5b': 'VRTL-4.coder',
9
- 'qwen3:1.7b': 'VRTL-5.plus',
10
- 'qwen2.5:3b': 'VRTL-6.pro',
11
- 'gpt-4o-mini': 'VRTL-7.cloud-mini',
12
- 'gpt-4o': 'VRTL-8.cloud',
13
- 'claude-3-5-haiku-20241022': 'VRTL-9.cloud-fast',
14
- 'claude-sonnet-4-20250514': 'VRTL-10.cloud-pro',
15
- 'gemini-2.0-flash': 'VRTL-11.cloud-lite',
16
- 'gemini-1.5-pro': 'VRTL-12.cloud-plus',
17
- };
18
-
19
- // Older `vierratale-<word>` names, accepted everywhere for backwards
20
- // compatibility (existing config files may still contain them).
21
- const LEGACY_DISPLAY = {
22
- 'vierratale-lite': 'VRTL-1.lite',
23
- 'vierratale-fast': 'VRTL-2.fast',
24
- 'vierratale-small': 'VRTL-3.small',
25
- 'vierratale-balanced': 'VRTL-4.balanced',
26
- 'vierratale-plus': 'VRTL-5.plus',
27
- 'vierratale-pro': 'VRTL-6.pro',
28
- 'vierratale-cloud-mini': 'VRTL-7.cloud-mini',
29
- 'vierratale-cloud': 'VRTL-8.cloud',
30
- 'vierratale-cloud-fast': 'VRTL-9.cloud-fast',
31
- 'vierratale-cloud-pro': 'VRTL-10.cloud-pro',
32
- 'vierratale-cloud-lite': 'VRTL-11.cloud-lite',
33
- 'vierratale-cloud-plus': 'VRTL-12.cloud-plus',
2
+ 'qwen3:0.6b': 'vierratale-lite',
3
+ 'gemma3:1b': 'vierratale-fast',
4
+ 'llama3.2:1b': 'vierratale-small',
5
+ 'qwen2.5:1.5b': 'vierratale-balanced',
6
+ 'qwen3:1.7b': 'vierratale-plus',
7
+ 'qwen2.5:3b': 'vierratale-pro',
8
+ 'gpt-4o-mini': 'vierratale-cloud-mini',
9
+ 'gpt-4o': 'vierratale-cloud',
10
+ 'claude-3-5-haiku-20241022': 'vierratale-cloud-fast',
11
+ 'claude-sonnet-4-20250514': 'vierratale-cloud-pro',
12
+ 'gemini-2.0-flash': 'vierratale-cloud-lite',
13
+ 'gemini-1.5-pro': 'vierratale-cloud-plus',
34
14
  };
35
15
 
36
16
  const REVERSE = Object.fromEntries(
@@ -38,48 +18,26 @@ const REVERSE = Object.fromEntries(
38
18
  );
39
19
 
40
20
  const LOCAL_MODELS = [
41
- 'VRTL-1.lite',
42
- 'VRTL-2.fast',
43
- 'VRTL-3.small',
44
- 'VRTL-4.balanced',
45
- 'VRTL-4.coder',
46
- 'VRTL-5.plus',
47
- 'VRTL-6.pro',
21
+ 'vierratale-lite',
22
+ 'vierratale-fast',
23
+ 'vierratale-small',
24
+ 'vierratale-balanced',
25
+ 'vierratale-plus',
26
+ 'vierratale-pro',
48
27
  ];
49
28
 
50
29
  const CLOUD_MODELS = [
51
- 'VRTL-7.cloud-mini',
52
- 'VRTL-8.cloud',
53
- 'VRTL-9.cloud-fast',
54
- 'VRTL-10.cloud-pro',
55
- 'VRTL-11.cloud-lite',
56
- 'VRTL-12.cloud-plus',
30
+ 'vierratale-cloud-mini',
31
+ 'vierratale-cloud',
32
+ 'vierratale-cloud-fast',
33
+ 'vierratale-cloud-pro',
34
+ 'vierratale-cloud-lite',
35
+ 'vierratale-cloud-plus',
57
36
  ];
58
37
 
59
- const TIERS = {
60
- 'VRTL-1.lite': 'minimal',
61
- 'VRTL-2.fast': 'fast',
62
- 'VRTL-3.small': 'small',
63
- 'VRTL-4.balanced': 'balanced',
64
- 'VRTL-4.coder': 'coder',
65
- 'VRTL-5.plus': 'plus',
66
- 'VRTL-6.pro': 'professional',
67
- 'VRTL-7.cloud-mini': 'cloud-mini',
68
- 'VRTL-8.cloud': 'cloud',
69
- 'VRTL-9.cloud-fast': 'cloud-fast',
70
- 'VRTL-10.cloud-pro': 'cloud-pro',
71
- 'VRTL-11.cloud-lite': 'cloud-lite',
72
- 'VRTL-12.cloud-plus': 'cloud-plus',
73
- };
74
-
75
38
  export const Catalog = {
76
- // Map any known name (new or legacy) to the current VRTL display name.
77
- normalize(displayName) {
78
- return LEGACY_DISPLAY[displayName] || displayName;
79
- },
80
-
81
39
  getRealModel(displayName) {
82
- return REVERSE[this.normalize(displayName)] || displayName;
40
+ return REVERSE[displayName] || displayName;
83
41
  },
84
42
 
85
43
  getDisplayName(realModel) {
@@ -99,23 +57,23 @@ export const Catalog = {
99
57
  },
100
58
 
101
59
  getDefaultModel() {
102
- return 'VRTL-2.fast';
60
+ return 'vierratale-fast';
103
61
  },
104
62
 
105
63
  getDefaultCloudModel() {
106
- return 'VRTL-7.cloud-mini';
64
+ return 'vierratale-cloud-mini';
107
65
  },
108
66
 
109
67
  isLocalModel(displayName) {
110
- return LOCAL_MODELS.includes(this.normalize(displayName));
68
+ return LOCAL_MODELS.includes(displayName);
111
69
  },
112
70
 
113
71
  isCloudModel(displayName) {
114
- return CLOUD_MODELS.includes(this.normalize(displayName));
72
+ return CLOUD_MODELS.includes(displayName);
115
73
  },
116
74
 
117
75
  getVendorForCloudModel(displayName) {
118
- const real = REVERSE[this.normalize(displayName)];
76
+ const real = REVERSE[displayName];
119
77
  if (real && real.startsWith('claude-')) return 'anthropic';
120
78
  if (real && real.startsWith('gemini-')) return 'gemini';
121
79
  if (real && real.startsWith('gpt-')) return 'openai';
@@ -123,17 +81,30 @@ export const Catalog = {
123
81
  },
124
82
 
125
83
  getModelInfo(displayName) {
126
- const name = this.normalize(displayName);
127
- const real = REVERSE[name];
84
+ const real = REVERSE[displayName];
128
85
  if (!real) return null;
129
- const isLocal = LOCAL_MODELS.includes(name);
130
- const isCloud = CLOUD_MODELS.includes(name);
86
+ const isLocal = LOCAL_MODELS.includes(displayName);
87
+ const isCloud = CLOUD_MODELS.includes(displayName);
88
+ const tiers = {
89
+ 'vierratale-lite': 'minimal',
90
+ 'vierratale-fast': 'fast',
91
+ 'vierratale-small': 'small',
92
+ 'vierratale-balanced': 'balanced',
93
+ 'vierratale-plus': 'plus',
94
+ 'vierratale-pro': 'professional',
95
+ 'vierratale-cloud-mini': 'cloud-mini',
96
+ 'vierratale-cloud': 'cloud',
97
+ 'vierratale-cloud-fast': 'cloud-fast',
98
+ 'vierratale-cloud-pro': 'cloud-pro',
99
+ 'vierratale-cloud-lite': 'cloud-lite',
100
+ 'vierratale-cloud-plus': 'cloud-plus',
101
+ };
131
102
  return {
132
103
  displayName,
133
104
  realModel: real,
134
105
  isLocal,
135
106
  isCloud,
136
- tier: TIERS[name] || 'unknown',
107
+ tier: tiers[displayName] || 'unknown',
137
108
  };
138
109
  },
139
- };
110
+ };