@ai-setting/roy-agent-core 1.5.33 → 1.5.35

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.
@@ -8,7 +8,7 @@ import {
8
8
  grepTool,
9
9
  readFileTool,
10
10
  writeFileTool
11
- } from "../../../shared/@ai-setting/roy-agent-core-p46v1kr2.js";
11
+ } from "../../../shared/@ai-setting/roy-agent-core-qfdp3pvq.js";
12
12
  import"../../../shared/@ai-setting/roy-agent-core-xs5rsgat.js";
13
13
  import"../../../shared/@ai-setting/roy-agent-core-psv4v63c.js";
14
14
  import"../../../shared/@ai-setting/roy-agent-core-fs0mn2jk.js";
@@ -1,8 +1,10 @@
1
1
  import {
2
2
  ToolComponent,
3
3
  ToolRegistry,
4
- ToolValidator
5
- } from "../../shared/@ai-setting/roy-agent-core-q27e6dhw.js";
4
+ ToolValidator,
5
+ getMaxOutputSize,
6
+ setToolConfigComponent
7
+ } from "../../shared/@ai-setting/roy-agent-core-5wp5grzj.js";
6
8
  import {
7
9
  bashTool,
8
10
  echoTool,
@@ -13,7 +15,7 @@ import {
13
15
  grepTool,
14
16
  readFileTool,
15
17
  writeFileTool
16
- } from "../../shared/@ai-setting/roy-agent-core-p46v1kr2.js";
18
+ } from "../../shared/@ai-setting/roy-agent-core-qfdp3pvq.js";
17
19
  import"../../shared/@ai-setting/roy-agent-core-e25xkv53.js";
18
20
  import"../../shared/@ai-setting/roy-agent-core-qxhq8ven.js";
19
21
  import"../../shared/@ai-setting/roy-agent-core-kkbwepqb.js";
@@ -25,9 +27,11 @@ import"../../shared/@ai-setting/roy-agent-core-psv4v63c.js";
25
27
  import"../../shared/@ai-setting/roy-agent-core-fs0mn2jk.js";
26
28
  export {
27
29
  writeFileTool,
30
+ setToolConfigComponent,
28
31
  readFileTool,
29
32
  grepTool,
30
33
  globTool,
34
+ getMaxOutputSize,
31
35
  getBuiltInTool,
32
36
  getAllBuiltInTools,
33
37
  editFileTool,
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  ToolComponent,
10
10
  ToolRegistry,
11
11
  ToolValidator
12
- } from "./shared/@ai-setting/roy-agent-core-q27e6dhw.js";
12
+ } from "./shared/@ai-setting/roy-agent-core-5wp5grzj.js";
13
13
  import {
14
14
  bashTool,
15
15
  editFileTool,
@@ -19,7 +19,7 @@ import {
19
19
  grepTool,
20
20
  readFileTool,
21
21
  writeFileTool
22
- } from "./shared/@ai-setting/roy-agent-core-p46v1kr2.js";
22
+ } from "./shared/@ai-setting/roy-agent-core-qfdp3pvq.js";
23
23
  import {
24
24
  PromptComponent,
25
25
  getBuiltInPrompt,
@@ -149,7 +149,8 @@ var TOOL_DEFAULTS = {
149
149
  "tool.sandbox.enabled": false,
150
150
  "tool.sandbox.type": "native",
151
151
  "tool.execution.timeout": 30000,
152
- "tool.execution.maxConcurrency": 5
152
+ "tool.execution.maxConcurrency": 5,
153
+ "tool.execution.maxOutputSize": 5120
153
154
  };
154
155
  var TOOL_CONFIG_REGISTRATION = {
155
156
  name: "tool",
@@ -163,13 +164,47 @@ var TOOL_CONFIG_REGISTRATION = {
163
164
  { key: "tool.sandbox.enabled", sources: ["env", "file"] },
164
165
  { key: "tool.sandbox.type", sources: ["env", "file"] },
165
166
  { key: "tool.execution.timeout", sources: ["env", "file"] },
166
- { key: "tool.execution.maxConcurrency", sources: ["env", "file"] }
167
+ { key: "tool.execution.maxConcurrency", sources: ["env", "file"] },
168
+ { key: "tool.execution.maxOutputSize", sources: ["env", "file"] }
167
169
  ]
168
170
  };
169
171
 
170
172
  // src/env/tool/tool-component.ts
171
173
  init_workflow_hil();
172
174
  var logger = createLogger("tool");
175
+ var configComponentInstance = null;
176
+ function setToolConfigComponent(component) {
177
+ configComponentInstance = component;
178
+ }
179
+ function getMaxOutputSize() {
180
+ if (configComponentInstance) {
181
+ const maxOutputSize = configComponentInstance.get("tool.execution.maxOutputSize");
182
+ if (typeof maxOutputSize === "number" && maxOutputSize >= 0) {
183
+ return maxOutputSize;
184
+ }
185
+ }
186
+ return 5120;
187
+ }
188
+ function truncateOutput(output, maxSize) {
189
+ if (maxSize <= 0 || output.length <= maxSize) {
190
+ return {
191
+ output,
192
+ metadata: {}
193
+ };
194
+ }
195
+ const truncatedOutput = output.substring(0, maxSize);
196
+ const truncationNotice = `
197
+
198
+ [OUTPUT TRUNCATED: ${output.length} → ${maxSize} characters. Use offset/limit parameters or pipe to file for full content.]`;
199
+ return {
200
+ output: truncatedOutput + truncationNotice,
201
+ metadata: {
202
+ output_truncated: true,
203
+ original_output_size: output.length,
204
+ truncated_output_size: maxSize
205
+ }
206
+ };
207
+ }
173
208
 
174
209
  class ToolComponent extends BaseComponent {
175
210
  name = "tool";
@@ -191,6 +226,7 @@ class ToolComponent extends BaseComponent {
191
226
  throw new Error("ConfigComponent is required for ToolComponent initialization");
192
227
  }
193
228
  this.configComponent = options.configComponent;
229
+ setToolConfigComponent(options.configComponent);
194
230
  await this.registerConfig(options);
195
231
  if (this.config?.builtInTools?.enabled !== false) {
196
232
  await this.loadBuiltInTools();
@@ -377,6 +413,17 @@ class ToolComponent extends BaseComponent {
377
413
  } else {
378
414
  result.metadata.execution_time_ms = Date.now() - startTime;
379
415
  }
416
+ if (typeof result.output === "string") {
417
+ const maxOutputSize = getMaxOutputSize();
418
+ if (maxOutputSize > 0) {
419
+ const { output: truncatedOutput, metadata: truncationMeta } = truncateOutput(result.output, maxOutputSize);
420
+ result.output = truncatedOutput;
421
+ result.metadata = {
422
+ ...result.metadata,
423
+ ...truncationMeta
424
+ };
425
+ }
426
+ }
380
427
  if (!skipHooks) {
381
428
  await globalHookManager.execute(ToolHookPoints.AFTER_EXECUTE, { tool, args, context, result }, { toolName: tool.name });
382
429
  }
@@ -439,4 +486,4 @@ var ToolComponentConfigSchema = z.object({
439
486
  maxConcurrency: z.number().int().positive().default(4)
440
487
  }).default({})
441
488
  });
442
- export { ToolRegistry, ToolValidator, ToolComponent };
489
+ export { ToolRegistry, ToolValidator, setToolConfigComponent, getMaxOutputSize, ToolComponent };
@@ -11,100 +11,124 @@ import {
11
11
  // src/env/tool/built-in/bash.ts
12
12
  init_propagation();
13
13
  import { z } from "zod";
14
+ import { Effect as Effect2 } from "effect";
15
+
16
+ // src/env/tool/built-in/bash-effect.ts
17
+ import { Effect, Context, Layer } from "effect";
14
18
  import { spawn } from "child_process";
15
- import path from "path";
16
- function getPlatform() {
17
- return process.platform;
18
- }
19
- function isWindows() {
20
- return getPlatform() === "win32";
21
- }
22
- function getShellCommand(command) {
23
- if (isWindows()) {
24
- return {
25
- shell: "cmd.exe",
26
- args: ["/c", command]
27
- };
28
- }
29
- return {
30
- shell: "/bin/sh",
31
- args: ["-c", command]
32
- };
33
- }
34
- function normalizeCwd(cwd) {
35
- if (!cwd)
36
- return;
37
- return path.normalize(cwd);
38
- }
39
- function executeCommand(command, options) {
40
- return new Promise((resolve) => {
41
- const { shell, args } = getShellCommand(command);
42
- let stdout = "";
43
- let stderr = "";
44
- let timedOut = false;
45
- let resolved = false;
46
- let timer = null;
47
- let forceKillTimer = null;
48
- const child = spawn(shell, args, {
49
- cwd: normalizeCwd(options.cwd),
50
- env: options.env,
51
- stdio: ["ignore", "pipe", "pipe"],
19
+ var BashSpawner = Context.GenericTag("BashSpawner");
20
+ var isWindows = process.platform === "win32";
21
+ var SIGKILL_TIMEOUT_MS = 200;
22
+ var killTree = (proc, signal = "SIGKILL") => {
23
+ if (isWindows) {
24
+ spawn("taskkill", ["/pid", String(proc.pid), "/f", "/t"], {
25
+ stdio: "ignore",
52
26
  windowsHide: true
53
27
  });
54
- const cleanup = () => {
55
- if (timer)
56
- clearTimeout(timer);
57
- if (forceKillTimer)
58
- clearTimeout(forceKillTimer);
59
- };
60
- const doResolve = (result) => {
61
- if (!resolved) {
62
- resolved = true;
63
- cleanup();
64
- resolve(result);
65
- }
66
- };
67
- if (options.timeout) {
68
- timer = setTimeout(() => {
69
- timedOut = true;
70
- if (isWindows()) {
71
- child.kill("SIGTERM");
72
- forceKillTimer = setTimeout(() => {
73
- if (!child.killed) {
74
- try {
75
- process.kill(child.pid, "SIGKILL");
76
- } catch {}
28
+ return;
29
+ }
30
+ const pid = proc.pid;
31
+ if (!pid)
32
+ return;
33
+ try {
34
+ process.kill(-pid, "SIGTERM");
35
+ setTimeout(() => {
36
+ try {
37
+ process.kill(-pid, 0);
38
+ process.kill(-pid, signal);
39
+ } catch {}
40
+ }, SIGKILL_TIMEOUT_MS);
41
+ } catch {}
42
+ };
43
+ var makeBashSpawner = () => {
44
+ return {
45
+ run: (command, options) => {
46
+ return Effect.gen(function* () {
47
+ const cwd = options?.cwd;
48
+ const timeout = options?.timeout ?? 60000;
49
+ const env = options?.env ?? {};
50
+ let stdout = "";
51
+ let stderr = "";
52
+ let timedOut = false;
53
+ let timer = null;
54
+ let child = null;
55
+ let exitResolve = null;
56
+ let exited = false;
57
+ const spawnOpts = {
58
+ shell: true,
59
+ cwd,
60
+ env: { ...process.env, ...env },
61
+ stdio: ["pipe", "pipe", "pipe"]
62
+ };
63
+ child = spawn(command, [], spawnOpts);
64
+ const checkExited = () => exited || !child || !child.pid || child.killed || child.exitCode !== null;
65
+ if (timeout > 0) {
66
+ timer = setTimeout(() => {
67
+ if (!checkExited()) {
68
+ timedOut = true;
69
+ killTree(child, "SIGKILL");
70
+ if (exitResolve) {
71
+ exitResolve(-1);
72
+ exited = true;
73
+ }
77
74
  }
78
- }, 500);
79
- } else {
80
- child.kill("SIGKILL");
75
+ }, timeout);
81
76
  }
82
- }, options.timeout);
83
- }
84
- child.stdout?.on("data", (data) => {
85
- stdout += data.toString();
86
- });
87
- child.stderr?.on("data", (data) => {
88
- stderr += data.toString();
89
- });
90
- child.on("close", (code) => {
91
- doResolve({
92
- stdout: stdout.trim(),
93
- stderr: stderr.trim(),
94
- exitCode: timedOut ? -1 : code ?? 0,
95
- timedOut
96
- });
97
- });
98
- child.on("error", (err) => {
99
- doResolve({
100
- stdout: stdout.trim(),
101
- stderr: err.message,
102
- exitCode: 1,
103
- timedOut: false
77
+ yield* Effect.addFinalizer(() => {
78
+ return Effect.sync(() => {
79
+ if (timer)
80
+ clearTimeout(timer);
81
+ if (!checkExited() && child) {
82
+ child.kill("SIGKILL");
83
+ }
84
+ });
85
+ });
86
+ const stdoutChunks = [];
87
+ const stderrChunks = [];
88
+ child.stdout?.on("data", (data) => {
89
+ stdoutChunks.push(data);
90
+ });
91
+ child.stderr?.on("data", (data) => {
92
+ stderrChunks.push(data);
93
+ });
94
+ const exitCode = yield* Effect.async((resume) => {
95
+ exitResolve = (code) => {
96
+ if (!exited) {
97
+ exited = true;
98
+ resume(Effect.succeed(code));
99
+ }
100
+ };
101
+ child.on("exit", (code) => {
102
+ if (!exited) {
103
+ exited = true;
104
+ resume(Effect.succeed(code ?? 0));
105
+ }
106
+ });
107
+ child.on("error", () => {
108
+ if (!exited) {
109
+ exited = true;
110
+ resume(Effect.succeed(1));
111
+ }
112
+ });
113
+ });
114
+ if (timer)
115
+ clearTimeout(timer);
116
+ stdout = Buffer.concat(stdoutChunks).toString("utf-8");
117
+ stderr = Buffer.concat(stderrChunks).toString("utf-8");
118
+ return {
119
+ stdout: stdout.trim(),
120
+ stderr: stderr.trim(),
121
+ exitCode: timedOut ? -1 : exitCode,
122
+ success: !timedOut && exitCode === 0,
123
+ timedOut
124
+ };
104
125
  });
105
- });
106
- });
107
- }
126
+ }
127
+ };
128
+ };
129
+ var BashSpawnerLayer = Layer.succeed(BashSpawner, makeBashSpawner());
130
+
131
+ // src/env/tool/built-in/bash.ts
108
132
  function getCurrentSpanContext() {
109
133
  try {
110
134
  const { getTracerProvider } = (init_tracer_provider(), __toCommonJS(exports_tracer_provider));
@@ -152,7 +176,7 @@ var bashTool = {
152
176
  metadata: {
153
177
  category: "system",
154
178
  tags: ["shell", "command", "terminal", "exec"],
155
- version: "1.3.0"
179
+ version: "2.0.0"
156
180
  },
157
181
  execute: async (args, ctx) => {
158
182
  const startTime = Date.now();
@@ -198,11 +222,16 @@ var bashTool = {
198
222
  } catch {}
199
223
  const spanId = otelSpan?.spanContext?.spanId;
200
224
  try {
201
- const result = await executeCommand(command, {
202
- cwd,
203
- timeout,
204
- env: childEnv
225
+ const program = Effect2.gen(function* () {
226
+ const spawner = yield* BashSpawner;
227
+ const result2 = yield* spawner.run(command, {
228
+ cwd,
229
+ timeout,
230
+ env: childEnv
231
+ });
232
+ return result2;
205
233
  });
234
+ const result = await Effect2.runPromise(program.pipe(Effect2.scoped, Effect2.provide(BashSpawnerLayer)));
206
235
  if (otelSpan) {
207
236
  if (result.timedOut) {
208
237
  const execError = new Error(`Command timed out after ${timeout}ms`);
@@ -284,7 +313,7 @@ var echoTool = {
284
313
  import { z as z2 } from "zod";
285
314
  import { glob as globAsync } from "glob";
286
315
  import { stat } from "fs/promises";
287
- import path2 from "path";
316
+ import path from "path";
288
317
  var globTool = {
289
318
  name: "glob",
290
319
  description: "Search for files matching a glob pattern. Use this to find files by name patterns like **/*.ts or **/*.md.",
@@ -325,7 +354,7 @@ var globTool = {
325
354
  };
326
355
  }
327
356
  try {
328
- const absolutePattern = path2.isAbsolute(pattern) ? pattern : pattern;
357
+ const absolutePattern = path.isAbsolute(pattern) ? pattern : pattern;
329
358
  const files = await globAsync(absolutePattern, {
330
359
  cwd: searchDir,
331
360
  ignore: ignore || ["**/node_modules/**", "**/.git/**"],
@@ -336,7 +365,7 @@ var globTool = {
336
365
  const filesWithMtime = [];
337
366
  for (const file of files) {
338
367
  try {
339
- const fullPath = path2.join(searchDir, file);
368
+ const fullPath = path.join(searchDir, file);
340
369
  const stats = await stat(fullPath);
341
370
  if (stats.isFile()) {
342
371
  filesWithMtime.push({
@@ -388,7 +417,7 @@ var globTool = {
388
417
  // src/env/tool/built-in/read-file.ts
389
418
  import { z as z3 } from "zod";
390
419
  import { readFile, stat as stat2 } from "fs/promises";
391
- import path3 from "path";
420
+ import path2 from "path";
392
421
  var readFileTool = {
393
422
  name: "read_file",
394
423
  description: "Read the contents of a file. Use this to read source code, configuration files, or any text files.",
@@ -425,7 +454,7 @@ var readFileTool = {
425
454
  metadata: { execution_time_ms: Date.now() - startTime }
426
455
  };
427
456
  }
428
- const normalizedPath = path3.normalize(filePath);
457
+ const normalizedPath = path2.normalize(filePath);
429
458
  try {
430
459
  const stats = await stat2(normalizedPath);
431
460
  if (stats.isDirectory()) {
@@ -503,7 +532,7 @@ var readFileTool = {
503
532
  // src/env/tool/built-in/write-file.ts
504
533
  import { z as z4 } from "zod";
505
534
  import { writeFile, mkdir, stat as stat3 } from "fs/promises";
506
- import path4 from "path";
535
+ import path3 from "path";
507
536
  var writeFileTool = {
508
537
  name: "write_file",
509
538
  description: "Write content to a file. Use this to create new files or overwrite existing ones.",
@@ -541,7 +570,7 @@ var writeFileTool = {
541
570
  metadata: { execution_time_ms: Date.now() - startTime }
542
571
  };
543
572
  }
544
- const normalizedPath = path4.normalize(filePath);
573
+ const normalizedPath = path3.normalize(filePath);
545
574
  try {
546
575
  const stats = await stat3(normalizedPath);
547
576
  if (stats.isDirectory()) {
@@ -564,7 +593,7 @@ var writeFileTool = {
564
593
  }
565
594
  try {
566
595
  if (createDirs) {
567
- await mkdir(path4.dirname(normalizedPath), { recursive: true });
596
+ await mkdir(path3.dirname(normalizedPath), { recursive: true });
568
597
  }
569
598
  const flags = append ? "a" : "w";
570
599
  await writeFile(normalizedPath, content, { flag: flags });
@@ -593,7 +622,7 @@ var writeFileTool = {
593
622
  // src/env/tool/built-in/edit-file.ts
594
623
  import { z as z5 } from "zod";
595
624
  import { readFile as readFile2, writeFile as writeFile2, stat as stat4, unlink } from "fs/promises";
596
- import path5 from "path";
625
+ import path4 from "path";
597
626
  import { randomUUID } from "crypto";
598
627
  var editFileTool = {
599
628
  name: "edit_file",
@@ -632,7 +661,7 @@ var editFileTool = {
632
661
  metadata: { execution_time_ms: Date.now() - startTime }
633
662
  };
634
663
  }
635
- const normalizedPath = path5.normalize(filePath);
664
+ const normalizedPath = path4.normalize(filePath);
636
665
  try {
637
666
  const stats = await stat4(normalizedPath);
638
667
  if (stats.isDirectory()) {
@@ -710,7 +739,7 @@ function escapeRegExp(string) {
710
739
  import { z as z6 } from "zod";
711
740
  import { readFile as readFile3, stat as stat5 } from "fs/promises";
712
741
  import { glob as globAsync2 } from "glob";
713
- import path6 from "path";
742
+ import path5 from "path";
714
743
  function isBinaryContent(content) {
715
744
  for (let i = 0;i < Math.min(content.length, 8192); i++) {
716
745
  if (content[i] === 0) {
@@ -780,7 +809,7 @@ var grepTool = {
780
809
  maxDepth: 10,
781
810
  nodir: true
782
811
  });
783
- files = files.map((f) => path6.join(basePath, f));
812
+ files = files.map((f) => path5.join(basePath, f));
784
813
  }
785
814
  const results = [];
786
815
  const regexFlags = caseSensitive ? "" : "i";
@@ -811,7 +840,7 @@ var grepTool = {
811
840
  regex.lastIndex = 0;
812
841
  if (regex.test(lines[i])) {
813
842
  const lineNum = showLineNumbers ? `${i + 1}:` : "";
814
- const relativePath = path6.relative(basePath, file);
843
+ const relativePath = path5.relative(basePath, file);
815
844
  results.push(`${relativePath}:${lineNum}${lines[i]}`);
816
845
  if (results.length >= maxResults)
817
846
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-setting/roy-agent-core",
3
- "version": "1.5.33",
3
+ "version": "1.5.35",
4
4
  "type": "module",
5
5
  "description": "Core SDK for roy-agent - Environment, Components, Tools, Sessions, Tasks",
6
6
  "main": "./dist/index.js",
@@ -38,9 +38,12 @@
38
38
  "@ai-sdk/google": "^3.0.0",
39
39
  "@ai-sdk/openai": "^3.0.0",
40
40
  "@ai-sdk/openai-compatible": "^2.0.0",
41
+ "@effect/platform": "^0.96.1",
42
+ "@effect/platform-node": "^0.106.0",
41
43
  "@modelcontextprotocol/sdk": "^1.29.0",
42
44
  "ai": "^6.0.0",
43
45
  "better-sqlite3": "^11.10.0",
46
+ "effect": "^3.21.2",
44
47
  "glob": "^13.0.6",
45
48
  "jsonc-parser": "^3.2.0",
46
49
  "reflect-metadata": "^0.2.2",