@vietor/agent-core 0.7.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 (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +849 -0
  3. package/dist/create-session.d.ts +4 -0
  4. package/dist/create-session.js +51 -0
  5. package/dist/index.d.ts +12 -0
  6. package/dist/index.js +5 -0
  7. package/dist/llm/anthropic.d.ts +14 -0
  8. package/dist/llm/anthropic.js +200 -0
  9. package/dist/llm/base.d.ts +10 -0
  10. package/dist/llm/base.js +12 -0
  11. package/dist/llm/client.d.ts +4 -0
  12. package/dist/llm/client.js +61 -0
  13. package/dist/llm/completions.d.ts +8 -0
  14. package/dist/llm/completions.js +88 -0
  15. package/dist/llm/messages.d.ts +50 -0
  16. package/dist/llm/messages.js +28 -0
  17. package/dist/llm/responses.d.ts +14 -0
  18. package/dist/llm/responses.js +130 -0
  19. package/dist/llm/types.d.ts +40 -0
  20. package/dist/llm/types.js +1 -0
  21. package/dist/mcp/client.d.ts +15 -0
  22. package/dist/mcp/client.js +53 -0
  23. package/dist/mcp/manager.d.ts +18 -0
  24. package/dist/mcp/manager.js +155 -0
  25. package/dist/mcp/types.d.ts +26 -0
  26. package/dist/mcp/types.js +1 -0
  27. package/dist/runtime/agent.d.ts +56 -0
  28. package/dist/runtime/agent.js +253 -0
  29. package/dist/runtime/events.d.ts +69 -0
  30. package/dist/runtime/events.js +1 -0
  31. package/dist/runtime/prompts.d.ts +5 -0
  32. package/dist/runtime/prompts.js +45 -0
  33. package/dist/runtime/session-messages.d.ts +43 -0
  34. package/dist/runtime/session-messages.js +174 -0
  35. package/dist/runtime/session.d.ts +102 -0
  36. package/dist/runtime/session.js +375 -0
  37. package/dist/runtime/sub-agent-runner.d.ts +18 -0
  38. package/dist/runtime/sub-agent-runner.js +26 -0
  39. package/dist/runtime/timeline.d.ts +21 -0
  40. package/dist/runtime/timeline.js +146 -0
  41. package/dist/runtime/todo-store.d.ts +8 -0
  42. package/dist/runtime/todo-store.js +15 -0
  43. package/dist/skills/loader.d.ts +6 -0
  44. package/dist/skills/loader.js +43 -0
  45. package/dist/tools/ask-user.d.ts +3 -0
  46. package/dist/tools/ask-user.js +26 -0
  47. package/dist/tools/file-edit.d.ts +2 -0
  48. package/dist/tools/file-edit.js +43 -0
  49. package/dist/tools/file-read.d.ts +2 -0
  50. package/dist/tools/file-read.js +93 -0
  51. package/dist/tools/file-write.d.ts +2 -0
  52. package/dist/tools/file-write.js +25 -0
  53. package/dist/tools/glob.d.ts +2 -0
  54. package/dist/tools/glob.js +31 -0
  55. package/dist/tools/grep.d.ts +2 -0
  56. package/dist/tools/grep.js +67 -0
  57. package/dist/tools/registry.d.ts +30 -0
  58. package/dist/tools/registry.js +107 -0
  59. package/dist/tools/shell.d.ts +2 -0
  60. package/dist/tools/shell.js +57 -0
  61. package/dist/tools/skill.d.ts +3 -0
  62. package/dist/tools/skill.js +30 -0
  63. package/dist/tools/sub-agent.d.ts +7 -0
  64. package/dist/tools/sub-agent.js +81 -0
  65. package/dist/tools/todo-write.d.ts +3 -0
  66. package/dist/tools/todo-write.js +72 -0
  67. package/dist/tools/types.d.ts +32 -0
  68. package/dist/tools/types.js +4 -0
  69. package/dist/tools/web-fetch.d.ts +2 -0
  70. package/dist/tools/web-fetch.js +104 -0
  71. package/dist/util/async.d.ts +19 -0
  72. package/dist/util/async.js +93 -0
  73. package/dist/util/constants.d.ts +25 -0
  74. package/dist/util/constants.js +27 -0
  75. package/dist/util/emitter.d.ts +5 -0
  76. package/dist/util/emitter.js +15 -0
  77. package/dist/util/file.d.ts +3 -0
  78. package/dist/util/file.js +19 -0
  79. package/dist/util/html.d.ts +1 -0
  80. package/dist/util/html.js +14 -0
  81. package/dist/util/index.d.ts +7 -0
  82. package/dist/util/index.js +7 -0
  83. package/dist/util/net.d.ts +1 -0
  84. package/dist/util/net.js +31 -0
  85. package/dist/util/ripgrep.d.ts +10 -0
  86. package/dist/util/ripgrep.js +34 -0
  87. package/dist/util/subprocess.d.ts +15 -0
  88. package/dist/util/subprocess.js +113 -0
  89. package/dist/util/text.d.ts +15 -0
  90. package/dist/util/text.js +72 -0
  91. package/package.json +52 -0
@@ -0,0 +1,15 @@
1
+ export interface ProcessResult {
2
+ stdout: string;
3
+ stderr: string;
4
+ status: number | null;
5
+ error?: Error;
6
+ truncated?: boolean;
7
+ }
8
+ export declare function killProcessTree(pid: number | null | undefined, opts?: {
9
+ group?: boolean;
10
+ force?: boolean;
11
+ }): void;
12
+ export declare function runProcess(cmd: string, args: string[], opts?: {
13
+ cwd?: string;
14
+ timeout?: number;
15
+ }, signal?: AbortSignal): Promise<ProcessResult>;
@@ -0,0 +1,113 @@
1
+ import { spawn, spawnSync } from "node:child_process";
2
+ import { MAX_PROCESS_BUFFER_MB, mbToBytes } from "./constants.js";
3
+ const KILL_GRACE_MS = 2000;
4
+ const MAX_PROCESS_BUFFER = mbToBytes(MAX_PROCESS_BUFFER_MB);
5
+ const liveProcesses = new Set();
6
+ process.on("exit", () => {
7
+ for (const pid of liveProcesses)
8
+ killProcessTree(pid, { group: true, force: true });
9
+ });
10
+ export function killProcessTree(pid, opts) {
11
+ if (!pid)
12
+ return;
13
+ if (process.platform === "win32") {
14
+ try {
15
+ spawnSync("taskkill", ["/PID", String(pid), "/T", "/F"], { windowsHide: true });
16
+ }
17
+ catch { }
18
+ return;
19
+ }
20
+ const targets = opts?.group ? [-pid, pid] : [pid];
21
+ for (const target of targets) {
22
+ try {
23
+ process.kill(target, opts?.force ? "SIGKILL" : "SIGTERM");
24
+ if (!opts?.force)
25
+ scheduleSIGKILL(target);
26
+ return;
27
+ }
28
+ catch { }
29
+ }
30
+ }
31
+ function scheduleSIGKILL(pid) {
32
+ setTimeout(() => {
33
+ try {
34
+ process.kill(pid, "SIGKILL");
35
+ }
36
+ catch { }
37
+ }, KILL_GRACE_MS).unref();
38
+ }
39
+ export function runProcess(cmd, args, opts = {}, signal) {
40
+ return new Promise((resolve) => {
41
+ const child = spawn(cmd, args, {
42
+ cwd: opts.cwd,
43
+ stdio: ["ignore", "pipe", "pipe"],
44
+ detached: process.platform !== "win32",
45
+ });
46
+ const outChunks = [];
47
+ const errChunks = [];
48
+ let size = 0;
49
+ let settled = false;
50
+ function flushOutput() {
51
+ return {
52
+ stdout: Buffer.concat(outChunks).toString("utf-8"),
53
+ stderr: Buffer.concat(errChunks).toString("utf-8"),
54
+ };
55
+ }
56
+ function settle(result) {
57
+ if (settled)
58
+ return;
59
+ settled = true;
60
+ if (timer)
61
+ clearTimeout(timer);
62
+ signal?.removeEventListener("abort", kill);
63
+ resolve(result);
64
+ }
65
+ function kill() { killProcessTree(child.pid, { group: true }); }
66
+ function onChunk(c, chunks) {
67
+ if (settled)
68
+ return;
69
+ chunks.push(c);
70
+ size += c.length;
71
+ if (size > MAX_PROCESS_BUFFER) {
72
+ kill();
73
+ settle({
74
+ ...flushOutput(),
75
+ status: null,
76
+ error: new Error(`Command output exceeded ${MAX_PROCESS_BUFFER_MB}MB`),
77
+ truncated: true,
78
+ });
79
+ }
80
+ }
81
+ if (signal) {
82
+ signal.addEventListener("abort", kill, { once: true });
83
+ if (signal.aborted)
84
+ kill();
85
+ }
86
+ child.on("spawn", () => {
87
+ liveProcesses.add(child.pid);
88
+ if (signal?.aborted)
89
+ kill();
90
+ });
91
+ let timer;
92
+ const { timeout } = opts;
93
+ if (timeout && timeout > 0) {
94
+ timer = setTimeout(() => {
95
+ kill();
96
+ settle({
97
+ ...flushOutput(),
98
+ status: null,
99
+ error: new Error(`Command timed out (${timeout / 1000}s)`),
100
+ });
101
+ }, timeout);
102
+ }
103
+ child.stdout?.on("data", (c) => onChunk(c, outChunks));
104
+ child.stderr?.on("data", (c) => onChunk(c, errChunks));
105
+ child.on("error", (error) => settle({ stdout: "", stderr: "", status: null, error }));
106
+ child.on("close", (status) => {
107
+ liveProcesses.delete(child.pid);
108
+ if (settled)
109
+ return;
110
+ settle({ ...flushOutput(), status });
111
+ });
112
+ });
113
+ }
@@ -0,0 +1,15 @@
1
+ export declare function formatDuration(value: number): string;
2
+ export declare function formatCompactNumber(value: number): string;
3
+ export declare function getTextBytes(content: string): number;
4
+ export declare function countNonEmptyLines(content: string): number;
5
+ export declare function summarizeText(content: string, length: number, showChars?: boolean): string;
6
+ export declare function summaryBytes(prefix: string, result: {
7
+ content: string;
8
+ isError?: boolean;
9
+ }, failText: string): string;
10
+ export declare function summaryCount(word: "file" | "match", count: number, isError: boolean, failText: string): string;
11
+ export declare function defaultResultSummary(result: {
12
+ content: string;
13
+ isError?: boolean;
14
+ }): string;
15
+ export declare function toErrorMessage(e: unknown): string;
@@ -0,0 +1,72 @@
1
+ const secondsFormatter = new Intl.NumberFormat("en-US", {
2
+ style: "unit",
3
+ unit: "second",
4
+ unitDisplay: "narrow",
5
+ maximumFractionDigits: 2,
6
+ });
7
+ import { MAX_SUMMARY_LENGTH } from "./constants.js";
8
+ const compactNumberFormatter = new Intl.NumberFormat("en-US", {
9
+ notation: "compact",
10
+ maximumFractionDigits: 2,
11
+ });
12
+ export function formatDuration(value) {
13
+ if (!value)
14
+ return "0s";
15
+ if (value < 60)
16
+ return secondsFormatter.format(value);
17
+ const total = Math.round(value);
18
+ const days = Math.floor(total / 86400);
19
+ const hours = Math.floor((total % 86400) / 3600);
20
+ const minutes = Math.floor((total % 3600) / 60);
21
+ const seconds = total % 60;
22
+ const parts = [];
23
+ if (days)
24
+ parts.push(`${days}d`);
25
+ if (hours)
26
+ parts.push(`${hours}h`);
27
+ if (minutes)
28
+ parts.push(`${minutes}m`);
29
+ if (seconds)
30
+ parts.push(`${seconds}s`);
31
+ return parts.join(" ");
32
+ }
33
+ export function formatCompactNumber(value) {
34
+ if (!value)
35
+ return "0";
36
+ return compactNumberFormatter.format(value);
37
+ }
38
+ export function getTextBytes(content) {
39
+ return Buffer.byteLength(content, "utf-8");
40
+ }
41
+ export function countNonEmptyLines(content) {
42
+ return content.split("\n").filter((l) => l).length;
43
+ }
44
+ export function summarizeText(content, length, showChars) {
45
+ const text = content.replace(/\n/g, " ").replace(/\s+/g, " ").trim();
46
+ if (text.length <= length)
47
+ return text;
48
+ const truncated = text.slice(0, length) + "…";
49
+ return showChars ? `${truncated} (${text.length})` : truncated;
50
+ }
51
+ export function summaryBytes(prefix, result, failText) {
52
+ if (result.isError)
53
+ return failText;
54
+ return `${prefix} ${formatCompactNumber(getTextBytes(result.content))} bytes`;
55
+ }
56
+ export function summaryCount(word, count, isError, failText) {
57
+ if (isError)
58
+ return failText;
59
+ const plural = word === "match" ? "matches" : "files";
60
+ return `Found ${count} ${count === 1 ? word : plural}`;
61
+ }
62
+ export function defaultResultSummary(result) {
63
+ if (result.isError) {
64
+ return summarizeText(result.content, MAX_SUMMARY_LENGTH);
65
+ }
66
+ const bytes = getTextBytes(result.content);
67
+ const lines = countNonEmptyLines(result.content);
68
+ return `Retrieved ${formatCompactNumber(bytes)} bytes, ${formatCompactNumber(lines)} lines`;
69
+ }
70
+ export function toErrorMessage(e) {
71
+ return e instanceof Error ? e.message : String(e);
72
+ }
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@vietor/agent-core",
3
+ "version": "0.7.0",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ },
12
+ "./util": {
13
+ "types": "./dist/util/index.d.ts",
14
+ "import": "./dist/util/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "description": "Lightweight AI agent framework — session orchestration, tool system, MCP client/server, skill loader",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/vietor/easy-agent.git"
25
+ },
26
+ "dependencies": {
27
+ "@anthropic-ai/sdk": "^0.115.0",
28
+ "@modelcontextprotocol/sdk": "^1.30.0",
29
+ "@vscode/ripgrep": "^1.18.0",
30
+ "openai": "^7.4.0",
31
+ "turndown": "^7.2.4",
32
+ "undici": "^8.10.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^22.20.1",
36
+ "@types/turndown": "^5.0.6",
37
+ "tsx": "^4.23.1",
38
+ "typescript": "^6.0.3"
39
+ },
40
+ "engines": {
41
+ "node": ">=22.0.0"
42
+ },
43
+ "keywords": [
44
+ "ai",
45
+ "llm",
46
+ "agent"
47
+ ],
48
+ "scripts": {
49
+ "build": "tsc",
50
+ "test": "node --import tsx --test test/*.test.ts"
51
+ }
52
+ }