agen-vektor 0.1.0

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.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +212 -0
  3. package/dist/agent/agent.js +90 -0
  4. package/dist/agent/context.js +106 -0
  5. package/dist/agent/loop.js +152 -0
  6. package/dist/agent/memory.js +87 -0
  7. package/dist/agent/planner.js +38 -0
  8. package/dist/agent/prompts.js +41 -0
  9. package/dist/agent/session.js +125 -0
  10. package/dist/cli/index.js +304 -0
  11. package/dist/cli/keyboard.js +283 -0
  12. package/dist/config/config.js +92 -0
  13. package/dist/config/credentials.js +127 -0
  14. package/dist/config/models.js +47 -0
  15. package/dist/providers/anthropic.js +276 -0
  16. package/dist/providers/custom.js +24 -0
  17. package/dist/providers/factory.js +58 -0
  18. package/dist/providers/gemini.js +223 -0
  19. package/dist/providers/ollama.js +195 -0
  20. package/dist/providers/openai-compat.js +296 -0
  21. package/dist/providers/openai.js +17 -0
  22. package/dist/providers/openrouter.js +23 -0
  23. package/dist/providers/provider.js +39 -0
  24. package/dist/security/command-policy.js +99 -0
  25. package/dist/security/permissions.js +66 -0
  26. package/dist/tools/filesystem.js +297 -0
  27. package/dist/tools/git.js +66 -0
  28. package/dist/tools/registry.js +39 -0
  29. package/dist/tools/search.js +184 -0
  30. package/dist/tools/shell.js +108 -0
  31. package/dist/tools/web.js +76 -0
  32. package/dist/tui/app.js +913 -0
  33. package/dist/tui/chat.js +76 -0
  34. package/dist/tui/components.js +85 -0
  35. package/dist/tui/diff.js +105 -0
  36. package/dist/tui/input.js +121 -0
  37. package/dist/tui/statusbar.js +32 -0
  38. package/dist/utils/logger.js +96 -0
  39. package/dist/utils/paths.js +90 -0
  40. package/dist/utils/terminal.js +191 -0
  41. package/package.json +56 -0
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runShell = runShell;
4
+ exports.createShellTool = createShellTool;
5
+ /**
6
+ * Shell tool — run commands in the project directory.
7
+ * Every command is classified by the command policy and gated by permissions.
8
+ */
9
+ const node_child_process_1 = require("node:child_process");
10
+ function runShell(command, cwd, opts = {}) {
11
+ return new Promise((resolve) => {
12
+ const timeoutMs = opts.timeoutMs || 120_000;
13
+ const child = (0, node_child_process_1.spawn)(command, {
14
+ cwd,
15
+ shell: '/bin/sh',
16
+ env: { ...process.env, ...opts.env },
17
+ stdio: ['ignore', 'pipe', 'pipe'],
18
+ });
19
+ let stdout = '';
20
+ let stderr = '';
21
+ let timedOut = false;
22
+ const timer = setTimeout(() => {
23
+ timedOut = true;
24
+ child.kill('SIGKILL');
25
+ }, timeoutMs);
26
+ child.stdout.on('data', (d) => {
27
+ stdout += d.toString();
28
+ if (stdout.length > 2_000_000)
29
+ child.kill('SIGKILL');
30
+ });
31
+ child.stderr.on('data', (d) => {
32
+ stderr += d.toString();
33
+ if (stderr.length > 2_000_000)
34
+ child.kill('SIGKILL');
35
+ });
36
+ child.on('close', (code) => {
37
+ clearTimeout(timer);
38
+ resolve({ stdout, stderr, exitCode: code, timedOut });
39
+ });
40
+ child.on('error', (e) => {
41
+ clearTimeout(timer);
42
+ resolve({ stdout, stderr: `spawn error: ${e.message}`, exitCode: -1, timedOut });
43
+ });
44
+ });
45
+ }
46
+ function truncate(text, max) {
47
+ if (text.length <= max)
48
+ return text;
49
+ return text.slice(0, max) + `\n... [truncated ${text.length - max} chars]`;
50
+ }
51
+ function createShellTool() {
52
+ return {
53
+ definition: {
54
+ name: 'shell',
55
+ description: 'Run a shell command in the project directory. The command is classified for safety; risky commands require permission. Use for building, testing, installing, git, or any command execution. Long output is truncated.',
56
+ parameters: {
57
+ type: 'object',
58
+ properties: {
59
+ command: { type: 'string', description: 'The shell command to run (single line; use && to chain)' },
60
+ timeout_ms: { type: 'number', description: 'Timeout in ms (default 120000)' },
61
+ },
62
+ required: ['command'],
63
+ },
64
+ },
65
+ async execute(args, ctx) {
66
+ const command = String(args.command || '').trim();
67
+ if (!command)
68
+ return { output: 'ERROR: empty command' };
69
+ ctx.onActivity?.('shell', `$ ${command}`);
70
+ const level = ctx.permissions.classifyCommand(command);
71
+ if (level === 'blocked') {
72
+ return {
73
+ output: `BLOCKED: command is not permitted by VECTOR security policy:\n${command}`,
74
+ summary: 'blocked by policy',
75
+ };
76
+ }
77
+ const allowed = await ctx.permissions.decide({
78
+ tool: 'shell',
79
+ summary: command,
80
+ level,
81
+ });
82
+ if (!allowed) {
83
+ return {
84
+ output: `Permission denied by user:\n${command}`,
85
+ summary: 'denied by user',
86
+ };
87
+ }
88
+ const result = await runShell(command, ctx.cwd, {
89
+ timeoutMs: Number(args.timeout_ms) || 120_000,
90
+ });
91
+ const maxOut = ctx.maxOutput || 30_000;
92
+ let out = '';
93
+ if (result.stdout)
94
+ out += truncate(result.stdout, maxOut);
95
+ if (result.stderr)
96
+ out += (out ? '\n[stderr]\n' : '') + truncate(result.stderr, Math.min(maxOut, 10_000));
97
+ if (result.timedOut)
98
+ out += '\n[command timed out and was killed]';
99
+ const status = result.exitCode === 0 ? 'exit 0' : `exit ${result.exitCode ?? '?'}`;
100
+ out = `${status}${out ? '\n' + out : ''}`;
101
+ return {
102
+ output: out,
103
+ summary: `$ ${command} → ${status}`,
104
+ data: { exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr },
105
+ };
106
+ },
107
+ };
108
+ }
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createWebTool = createWebTool;
4
+ async function fetchText(url, maxChars) {
5
+ const controller = new AbortController();
6
+ const timer = setTimeout(() => controller.abort(), 20_000);
7
+ try {
8
+ const res = await fetch(url, {
9
+ signal: controller.signal,
10
+ headers: { 'User-Agent': 'VECTOR-AI-Agent/0.1' },
11
+ redirect: 'follow',
12
+ });
13
+ if (!res.ok)
14
+ return `ERROR: HTTP ${res.status} for ${url}`;
15
+ const contentType = res.headers.get('content-type') || '';
16
+ if (contentType.includes('application/json')) {
17
+ const text = await res.text();
18
+ return text.slice(0, maxChars);
19
+ }
20
+ if (contentType.includes('text') || contentType.includes('html')) {
21
+ const html = await res.text();
22
+ return stripHtml(html).slice(0, maxChars);
23
+ }
24
+ const buf = Buffer.from(await res.arrayBuffer());
25
+ return buf.toString('utf8').slice(0, maxChars);
26
+ }
27
+ catch (e) {
28
+ return `ERROR: fetch failed: ${e.message}`;
29
+ }
30
+ finally {
31
+ clearTimeout(timer);
32
+ }
33
+ }
34
+ function stripHtml(html) {
35
+ return html
36
+ .replace(/<script[\s\S]*?<\/script>/gi, ' ')
37
+ .replace(/<style[\s\S]*?<\/style>/gi, ' ')
38
+ .replace(/<noscript[\s\S]*?<\/noscript>/gi, ' ')
39
+ .replace(/<[^>]+>/g, ' ')
40
+ .replace(/&amp;/g, '&')
41
+ .replace(/&lt;/g, '<')
42
+ .replace(/&gt;/g, '>')
43
+ .replace(/&quot;/g, '"')
44
+ .replace(/&#39;/g, "'")
45
+ .replace(/&nbsp;/g, ' ')
46
+ .replace(/\s+/g, ' ')
47
+ .trim();
48
+ }
49
+ function createWebTool() {
50
+ return {
51
+ definition: {
52
+ name: 'web_fetch',
53
+ description: 'Fetch a URL and return its readable text content. Use for documentation, errors, or any page needed to solve the task. Web search engines are not built in.',
54
+ parameters: {
55
+ type: 'object',
56
+ properties: {
57
+ url: { type: 'string', description: 'The http(s) URL to fetch' },
58
+ max_chars: { type: 'number', description: 'Max characters to return (default 8000)' },
59
+ },
60
+ required: ['url'],
61
+ },
62
+ },
63
+ async execute(args, ctx) {
64
+ const url = String(args.url || '');
65
+ if (!/^https?:\/\//i.test(url))
66
+ return { output: `ERROR: invalid URL: ${url}` };
67
+ const maxChars = Math.min(30_000, Math.max(1000, Number(args.max_chars) || 8000));
68
+ ctx.onActivity?.('web', `fetching ${url}`);
69
+ const text = await fetchText(url, maxChars);
70
+ return {
71
+ output: text,
72
+ summary: `fetched ${url}`,
73
+ };
74
+ },
75
+ };
76
+ }