@kooka/agent-sdk 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 (91) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +293 -0
  3. package/dist/abort.d.ts +2 -0
  4. package/dist/abort.d.ts.map +1 -0
  5. package/dist/abort.js +19 -0
  6. package/dist/abort.js.map +1 -0
  7. package/dist/agent/agent.d.ts +67 -0
  8. package/dist/agent/agent.d.ts.map +1 -0
  9. package/dist/agent/agent.js +1061 -0
  10. package/dist/agent/agent.js.map +1 -0
  11. package/dist/agent/constants.d.ts +6 -0
  12. package/dist/agent/constants.d.ts.map +1 -0
  13. package/dist/agent/constants.js +40 -0
  14. package/dist/agent/constants.js.map +1 -0
  15. package/dist/agent/prompts.d.ts +4 -0
  16. package/dist/agent/prompts.d.ts.map +1 -0
  17. package/dist/agent/prompts.js +31 -0
  18. package/dist/agent/prompts.js.map +1 -0
  19. package/dist/agent/reminders.d.ts +3 -0
  20. package/dist/agent/reminders.d.ts.map +1 -0
  21. package/dist/agent/reminders.js +31 -0
  22. package/dist/agent/reminders.js.map +1 -0
  23. package/dist/agent/retry.d.ts +12 -0
  24. package/dist/agent/retry.d.ts.map +1 -0
  25. package/dist/agent/retry.js +200 -0
  26. package/dist/agent/retry.js.map +1 -0
  27. package/dist/index.d.ts +49 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +50 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/llm/openaiCompatible.d.ts +23 -0
  32. package/dist/llm/openaiCompatible.d.ts.map +1 -0
  33. package/dist/llm/openaiCompatible.js +91 -0
  34. package/dist/llm/openaiCompatible.js.map +1 -0
  35. package/dist/plugins/pluginManager.d.ts +22 -0
  36. package/dist/plugins/pluginManager.d.ts.map +1 -0
  37. package/dist/plugins/pluginManager.js +171 -0
  38. package/dist/plugins/pluginManager.js.map +1 -0
  39. package/dist/plugins/types.d.ts +97 -0
  40. package/dist/plugins/types.d.ts.map +1 -0
  41. package/dist/plugins/types.js +2 -0
  42. package/dist/plugins/types.js.map +1 -0
  43. package/dist/skills.d.ts +28 -0
  44. package/dist/skills.d.ts.map +1 -0
  45. package/dist/skills.js +188 -0
  46. package/dist/skills.js.map +1 -0
  47. package/dist/tools/builtin/bash.d.ts +4 -0
  48. package/dist/tools/builtin/bash.d.ts.map +1 -0
  49. package/dist/tools/builtin/bash.js +364 -0
  50. package/dist/tools/builtin/bash.js.map +1 -0
  51. package/dist/tools/builtin/glob.d.ts +4 -0
  52. package/dist/tools/builtin/glob.d.ts.map +1 -0
  53. package/dist/tools/builtin/glob.js +87 -0
  54. package/dist/tools/builtin/glob.js.map +1 -0
  55. package/dist/tools/builtin/grep.d.ts +4 -0
  56. package/dist/tools/builtin/grep.d.ts.map +1 -0
  57. package/dist/tools/builtin/grep.js +190 -0
  58. package/dist/tools/builtin/grep.js.map +1 -0
  59. package/dist/tools/builtin/index.d.ts +15 -0
  60. package/dist/tools/builtin/index.d.ts.map +1 -0
  61. package/dist/tools/builtin/index.js +37 -0
  62. package/dist/tools/builtin/index.js.map +1 -0
  63. package/dist/tools/builtin/list.d.ts +4 -0
  64. package/dist/tools/builtin/list.d.ts.map +1 -0
  65. package/dist/tools/builtin/list.js +162 -0
  66. package/dist/tools/builtin/list.js.map +1 -0
  67. package/dist/tools/builtin/read.d.ts +4 -0
  68. package/dist/tools/builtin/read.d.ts.map +1 -0
  69. package/dist/tools/builtin/read.js +92 -0
  70. package/dist/tools/builtin/read.js.map +1 -0
  71. package/dist/tools/builtin/skill.d.ts +9 -0
  72. package/dist/tools/builtin/skill.d.ts.map +1 -0
  73. package/dist/tools/builtin/skill.js +126 -0
  74. package/dist/tools/builtin/skill.js.map +1 -0
  75. package/dist/tools/builtin/workspace.d.ts +13 -0
  76. package/dist/tools/builtin/workspace.d.ts.map +1 -0
  77. package/dist/tools/builtin/workspace.js +74 -0
  78. package/dist/tools/builtin/workspace.js.map +1 -0
  79. package/dist/tools/builtin/write.d.ts +4 -0
  80. package/dist/tools/builtin/write.d.ts.map +1 -0
  81. package/dist/tools/builtin/write.js +73 -0
  82. package/dist/tools/builtin/write.js.map +1 -0
  83. package/dist/tools/registry.d.ts +21 -0
  84. package/dist/tools/registry.d.ts.map +1 -0
  85. package/dist/tools/registry.js +150 -0
  86. package/dist/tools/registry.js.map +1 -0
  87. package/dist/types.d.ts +251 -0
  88. package/dist/types.d.ts.map +1 -0
  89. package/dist/types.js +2 -0
  90. package/dist/types.js.map +1 -0
  91. package/package.json +46 -0
@@ -0,0 +1,190 @@
1
+ import * as fs from 'fs/promises';
2
+ import { createReadStream } from 'fs';
3
+ import * as path from 'path';
4
+ import { glob } from 'glob';
5
+ import * as readline from 'readline';
6
+ import { optionalString, requireString } from '@kooka/core';
7
+ import { getWorkspaceRoot, resolveToolPath, toPosixPath } from './workspace.js';
8
+ const MAX_LINE_LENGTH = 2000;
9
+ const MAX_MATCHES = 100;
10
+ const MAX_FILE_BYTES = 2_000_000;
11
+ export const grepTool = {
12
+ id: 'grep',
13
+ name: 'Search in Files',
14
+ description: 'Search for a regex pattern in files. Supports optional path (file or directory, workspace-scoped) and include glob. Returns up to 100 matches grouped by file.',
15
+ parameters: {
16
+ type: 'object',
17
+ properties: {
18
+ pattern: { type: 'string', description: 'Regex pattern to search for' },
19
+ path: {
20
+ type: 'string',
21
+ description: 'File or directory to search in (absolute or workspace-relative). Must be within the current workspace. Omit for workspace root.',
22
+ },
23
+ include: { type: 'string', description: 'File glob to include (e.g., **/*.{ts,tsx})' },
24
+ },
25
+ required: ['pattern'],
26
+ },
27
+ execution: { type: 'function', handler: 'builtin.grep' },
28
+ metadata: {
29
+ category: 'file',
30
+ icon: 'search',
31
+ requiresApproval: false,
32
+ permission: 'grep',
33
+ readOnly: true,
34
+ permissionPatterns: [
35
+ { arg: 'pattern', kind: 'raw' },
36
+ { arg: 'path', kind: 'path' },
37
+ { arg: 'include', kind: 'raw' },
38
+ ],
39
+ },
40
+ };
41
+ function looksBinary(text) {
42
+ // basic guard: if file contains NUL, treat as binary
43
+ return text.includes('\u0000');
44
+ }
45
+ export const grepHandler = async (args, context) => {
46
+ try {
47
+ const patternResult = requireString(args, 'pattern');
48
+ if ('error' in patternResult)
49
+ return { success: false, error: patternResult.error };
50
+ const rawPattern = patternResult.value;
51
+ let re;
52
+ try {
53
+ re = new RegExp(rawPattern, 'i');
54
+ }
55
+ catch (error) {
56
+ return { success: false, error: `Invalid regex pattern: ${rawPattern}\n${error instanceof Error ? error.message : String(error)}` };
57
+ }
58
+ const baseDir = optionalString(args, 'path');
59
+ const include = optionalString(args, 'include');
60
+ const notes = [];
61
+ const workspaceRoot = getWorkspaceRoot(context);
62
+ let targetAbsPath = workspaceRoot;
63
+ if (baseDir) {
64
+ const resolved = resolveToolPath(baseDir, { ...context, allowExternalPaths: true });
65
+ if (resolved.isExternal) {
66
+ notes.push('Provided path was outside the current workspace; searching the workspace root instead.');
67
+ targetAbsPath = workspaceRoot;
68
+ }
69
+ else {
70
+ targetAbsPath = resolved.absPath;
71
+ }
72
+ }
73
+ let stat;
74
+ try {
75
+ stat = await fs.stat(targetAbsPath);
76
+ }
77
+ catch {
78
+ stat = null;
79
+ }
80
+ const isFile = !!stat?.isFile?.();
81
+ const isDir = !!stat?.isDirectory?.();
82
+ const matchesByFile = new Map();
83
+ let totalMatches = 0;
84
+ const addMatch = (m) => {
85
+ if (totalMatches >= MAX_MATCHES)
86
+ return;
87
+ const list = matchesByFile.get(m.filePath) ?? [];
88
+ list.push(m);
89
+ matchesByFile.set(m.filePath, list);
90
+ totalMatches++;
91
+ };
92
+ const searchFile = async (filePath) => {
93
+ if (totalMatches >= MAX_MATCHES)
94
+ return;
95
+ try {
96
+ const stat = await fs.stat(filePath);
97
+ if (!stat.isFile())
98
+ return;
99
+ if (stat.size > MAX_FILE_BYTES)
100
+ return;
101
+ }
102
+ catch {
103
+ return;
104
+ }
105
+ const stream = createReadStream(filePath, { encoding: 'utf8' });
106
+ const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
107
+ let lineNumber = 0;
108
+ try {
109
+ for await (const line of rl) {
110
+ if (totalMatches >= MAX_MATCHES)
111
+ break;
112
+ lineNumber += 1;
113
+ const lineText = String(line ?? '');
114
+ if (looksBinary(lineText)) {
115
+ break;
116
+ }
117
+ if (!re.test(lineText))
118
+ continue;
119
+ const trimmed = lineText.length > MAX_LINE_LENGTH ? lineText.slice(0, MAX_LINE_LENGTH) + '...' : lineText;
120
+ addMatch({ filePath, line: lineNumber, text: trimmed });
121
+ }
122
+ }
123
+ catch {
124
+ // ignore read/parse errors
125
+ }
126
+ finally {
127
+ try {
128
+ rl.close();
129
+ }
130
+ catch { }
131
+ try {
132
+ stream.destroy();
133
+ }
134
+ catch { }
135
+ }
136
+ };
137
+ if (isFile) {
138
+ await searchFile(targetAbsPath);
139
+ }
140
+ else if (isDir) {
141
+ const pattern = include && include.trim() ? include.trim() : '**/*';
142
+ const relMatches = await glob(pattern, {
143
+ cwd: targetAbsPath,
144
+ ignore: ['**/node_modules/**', '**/.git/**'],
145
+ nodir: true,
146
+ dot: true,
147
+ follow: false,
148
+ windowsPathsNoEscape: true,
149
+ });
150
+ for (const rel of relMatches) {
151
+ if (totalMatches >= MAX_MATCHES)
152
+ break;
153
+ await searchFile(path.resolve(targetAbsPath, rel));
154
+ }
155
+ }
156
+ else {
157
+ return { success: true, data: 'No files found' };
158
+ }
159
+ const files = Array.from(matchesByFile.keys()).sort((a, b) => a.localeCompare(b));
160
+ if (files.length === 0) {
161
+ const outputLines = [];
162
+ if (notes.length > 0) {
163
+ outputLines.push(`Note: ${notes.join(' ')}`, '');
164
+ }
165
+ outputLines.push('No matches found');
166
+ return { success: true, data: outputLines.join('\n') };
167
+ }
168
+ const lines = [];
169
+ if (notes.length > 0) {
170
+ lines.push(`Note: ${notes.join(' ')}`, '');
171
+ }
172
+ for (const filePath of files) {
173
+ const rel = context.workspaceRoot ? path.relative(context.workspaceRoot, filePath) : filePath;
174
+ lines.push(`${toPosixPath(rel)}:`);
175
+ const matches = matchesByFile.get(filePath) ?? [];
176
+ for (const m of matches) {
177
+ lines.push(` ${String(m.line).padStart(5, ' ')}| ${m.text}`);
178
+ }
179
+ lines.push('');
180
+ }
181
+ if (totalMatches >= MAX_MATCHES) {
182
+ lines.push('(Results are truncated.)');
183
+ }
184
+ return { success: true, data: lines.join('\n').trimEnd() };
185
+ }
186
+ catch (error) {
187
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
188
+ }
189
+ };
190
+ //# sourceMappingURL=grep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep.js","sourceRoot":"","sources":["../../../src/tools/builtin/grep.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { ToolDefinition, ToolHandler } from '../../types.js';
2
+ import { ToolRegistry } from '../registry.js';
3
+ export type BuiltinToolsOptions = {
4
+ skills?: {
5
+ enabled?: boolean;
6
+ paths?: string[];
7
+ };
8
+ };
9
+ export declare const DEFAULT_SKILL_PATHS: string[];
10
+ export declare function getBuiltinTools(options?: BuiltinToolsOptions): Array<{
11
+ tool: ToolDefinition;
12
+ handler: ToolHandler;
13
+ }>;
14
+ export declare function registerBuiltinTools(registry: ToolRegistry, options?: BuiltinToolsOptions): void;
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAU9C,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,mBAAmB,UAQ/B,CAAC;AAEF,wBAAgB,eAAe,CAAC,OAAO,GAAE,mBAAwB,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAAC,CAexH;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,GAAE,mBAAwB,GAAG,IAAI,CAIpG"}
@@ -0,0 +1,37 @@
1
+ import { bashHandler, bashTool } from './bash.js';
2
+ import { globHandler, globTool } from './glob.js';
3
+ import { grepHandler, grepTool } from './grep.js';
4
+ import { listHandler, listTool } from './list.js';
5
+ import { readHandler, readTool } from './read.js';
6
+ import { createSkillTool } from './skill.js';
7
+ import { writeHandler, writeTool } from './write.js';
8
+ export const DEFAULT_SKILL_PATHS = [
9
+ '.lingyun/skills',
10
+ '.claude/skills',
11
+ '.opencode/skill',
12
+ '.opencode/skills',
13
+ '~/.config/lingyun/skills',
14
+ '~/.codex/skills',
15
+ '~/.claude/skills',
16
+ ];
17
+ export function getBuiltinTools(options = {}) {
18
+ const skill = createSkillTool({
19
+ enabled: options.skills?.enabled,
20
+ searchPaths: options.skills?.paths?.length ? options.skills.paths : DEFAULT_SKILL_PATHS,
21
+ });
22
+ return [
23
+ { tool: readTool, handler: readHandler },
24
+ { tool: writeTool, handler: writeHandler },
25
+ { tool: listTool, handler: listHandler },
26
+ { tool: globTool, handler: globHandler },
27
+ { tool: grepTool, handler: grepHandler },
28
+ { tool: bashTool, handler: bashHandler },
29
+ { tool: skill.tool, handler: skill.handler },
30
+ ];
31
+ }
32
+ export function registerBuiltinTools(registry, options = {}) {
33
+ for (const { tool, handler } of getBuiltinTools(options)) {
34
+ registry.registerTool(tool, handler);
35
+ }
36
+ }
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/builtin/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AASrD,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,iBAAiB;IACjB,gBAAgB;IAChB,iBAAiB;IACjB,kBAAkB;IAClB,0BAA0B;IAC1B,iBAAiB;IACjB,kBAAkB;CACnB,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,UAA+B,EAAE;IAC/D,MAAM,KAAK,GAAG,eAAe,CAAC;QAC5B,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO;QAChC,WAAW,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,mBAAmB;KACxF,CAAC,CAAC;IAEH,OAAO;QACL,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE;QACxC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE;QAC1C,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE;QACxC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE;QACxC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE;QACxC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE;QACxC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;KAC7C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,QAAsB,EAAE,UAA+B,EAAE;IAC5F,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,QAAQ,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ToolDefinition, ToolHandler } from '../../types.js';
2
+ export declare const listTool: ToolDefinition;
3
+ export declare const listHandler: ToolHandler;
4
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/list.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIlE,eAAO,MAAM,QAAQ,EAAE,cAqBtB,CAAC;AAqEF,eAAO,MAAM,WAAW,EAAE,WAsFzB,CAAC"}
@@ -0,0 +1,162 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ import { optionalString } from '@kooka/core';
4
+ import { getWorkspaceRoot, resolveToolPath, toPosixPath } from './workspace.js';
5
+ export const listTool = {
6
+ id: 'list',
7
+ name: 'List Directory',
8
+ description: 'List a directory tree (workspace-scoped). Returns up to 100 files. Use ignore to exclude additional glob patterns.',
9
+ parameters: {
10
+ type: 'object',
11
+ properties: {
12
+ path: { type: 'string', description: 'Directory to list (absolute or workspace-relative). Omit for workspace root.' },
13
+ ignore: { type: 'array', description: 'Additional ignore patterns (glob fragments)', items: { type: 'string' } },
14
+ },
15
+ required: [],
16
+ },
17
+ execution: { type: 'function', handler: 'builtin.list' },
18
+ metadata: {
19
+ category: 'file',
20
+ icon: 'folder',
21
+ requiresApproval: false,
22
+ permission: 'list',
23
+ readOnly: true,
24
+ permissionPatterns: [{ arg: 'path', kind: 'path' }],
25
+ },
26
+ };
27
+ const DEFAULT_IGNORE_DIRS = [
28
+ 'node_modules',
29
+ '.git',
30
+ 'dist',
31
+ 'build',
32
+ 'target',
33
+ 'vendor',
34
+ 'bin',
35
+ 'obj',
36
+ '.idea',
37
+ '.vscode',
38
+ '.cache',
39
+ 'cache',
40
+ 'logs',
41
+ '.venv',
42
+ 'venv',
43
+ 'env',
44
+ '__pycache__',
45
+ ];
46
+ const MAX_LIST_FILES = 100;
47
+ const MAX_LIST_DEPTH = 25;
48
+ async function walkWorkspaceFiles(baseDir, ignoreDirs) {
49
+ const relFiles = [];
50
+ const queue = [{ absDir: baseDir, relDir: '.', depth: 0 }];
51
+ let truncated = false;
52
+ while (queue.length > 0) {
53
+ const next = queue.shift();
54
+ let entries;
55
+ try {
56
+ entries = await fs.readdir(next.absDir, { withFileTypes: true });
57
+ }
58
+ catch {
59
+ continue;
60
+ }
61
+ for (const entry of entries) {
62
+ if (relFiles.length >= MAX_LIST_FILES) {
63
+ truncated = true;
64
+ break;
65
+ }
66
+ if (entry.isSymbolicLink())
67
+ continue;
68
+ const name = entry.name;
69
+ const childRel = next.relDir === '.' ? name : `${next.relDir}/${name}`;
70
+ const childAbs = path.join(next.absDir, name);
71
+ if (entry.isDirectory()) {
72
+ if (ignoreDirs.has(name))
73
+ continue;
74
+ if (next.depth >= MAX_LIST_DEPTH)
75
+ continue;
76
+ queue.push({ absDir: childAbs, relDir: childRel, depth: next.depth + 1 });
77
+ continue;
78
+ }
79
+ relFiles.push(toPosixPath(childRel));
80
+ }
81
+ if (truncated)
82
+ break;
83
+ }
84
+ return { relFiles, truncated };
85
+ }
86
+ export const listHandler = async (args, context) => {
87
+ try {
88
+ const baseDir = optionalString(args, 'path');
89
+ const ignoreExtra = Array.isArray(args.ignore) ? args.ignore.map(String) : [];
90
+ const ignoreDirs = new Set([...DEFAULT_IGNORE_DIRS, ...ignoreExtra].filter(Boolean));
91
+ const notes = [];
92
+ const workspaceRoot = getWorkspaceRoot(context);
93
+ let base = workspaceRoot;
94
+ if (baseDir) {
95
+ const resolved = resolveToolPath(baseDir, { ...context, allowExternalPaths: true });
96
+ if (resolved.isExternal) {
97
+ notes.push('Provided path was outside the current workspace; listing the workspace root instead.');
98
+ base = workspaceRoot;
99
+ }
100
+ else {
101
+ base = resolved.absPath;
102
+ }
103
+ }
104
+ try {
105
+ const stat = await fs.stat(base);
106
+ if (!stat.isDirectory()) {
107
+ base = path.dirname(base);
108
+ }
109
+ }
110
+ catch {
111
+ base = workspaceRoot;
112
+ }
113
+ const listing = await walkWorkspaceFiles(base, ignoreDirs);
114
+ const truncated = listing.truncated;
115
+ const relFiles = listing.relFiles.filter((p) => p && p !== '.').sort();
116
+ const dirs = new Set();
117
+ const filesByDir = new Map();
118
+ for (const file of relFiles) {
119
+ const dir = path.posix.dirname(file);
120
+ const parts = dir === '.' ? [] : dir.split('/');
121
+ for (let i = 0; i <= parts.length; i++) {
122
+ const dirPath = i === 0 ? '.' : parts.slice(0, i).join('/');
123
+ dirs.add(dirPath);
124
+ }
125
+ if (!filesByDir.has(dir))
126
+ filesByDir.set(dir, []);
127
+ filesByDir.get(dir).push(path.posix.basename(file));
128
+ }
129
+ const renderDir = (dirPath, depth) => {
130
+ const indent = ' '.repeat(depth);
131
+ let output = '';
132
+ if (depth > 0) {
133
+ output += `${indent}${path.posix.basename(dirPath)}/\n`;
134
+ }
135
+ const childIndent = ' '.repeat(depth + 1);
136
+ const children = Array.from(dirs)
137
+ .filter((d) => path.posix.dirname(d) === dirPath && d !== dirPath)
138
+ .sort();
139
+ for (const child of children) {
140
+ output += renderDir(child, depth + 1);
141
+ }
142
+ const files = (filesByDir.get(dirPath) || []).slice().sort();
143
+ for (const f of files) {
144
+ output += `${childIndent}${f}\n`;
145
+ }
146
+ return output;
147
+ };
148
+ const header = [];
149
+ if (notes.length > 0) {
150
+ header.push(`Note: ${notes.join(' ')}`, '');
151
+ }
152
+ const output = header.join('\n') +
153
+ `${base}/\n` +
154
+ renderDir('.', 0) +
155
+ (truncated ? '\n(Results are truncated.)\n' : '');
156
+ return { success: true, data: output.trimEnd() };
157
+ }
158
+ catch (error) {
159
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
160
+ }
161
+ };
162
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/tools/builtin/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ToolDefinition, ToolHandler } from '../../types.js';
2
+ export declare const readTool: ToolDefinition;
3
+ export declare const readHandler: ToolHandler;
4
+ //# sourceMappingURL=read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/read.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAOlE,eAAO,MAAM,QAAQ,EAAE,cAyBtB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,WAmEzB,CAAC"}
@@ -0,0 +1,92 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ import { optionalNumber, requireString } from '@kooka/core';
4
+ import { BINARY_EXTENSIONS, containsBinaryData, resolveToolPath } from './workspace.js';
5
+ const DEFAULT_READ_LIMIT = 2000;
6
+ const MAX_LINE_LENGTH = 2000;
7
+ export const readTool = {
8
+ id: 'read',
9
+ name: 'Read File',
10
+ description: 'Reads a file from the workspace. Prefer fileId from glob, or use filePath (absolute or workspace-relative). Supports offset (0-based) and limit (default 2000). Returns cat-style numbered lines.',
11
+ parameters: {
12
+ type: 'object',
13
+ properties: {
14
+ fileId: { type: 'string', description: 'File handle from glob output (e.g. "F1"). Prefer this over spelling file paths.' },
15
+ filePath: { type: 'string', description: 'Absolute path or path relative to workspace root' },
16
+ offset: { type: 'number', description: 'Line offset to start reading from (0-based)' },
17
+ limit: { type: 'number', description: 'Number of lines to read (default 2000)' },
18
+ },
19
+ required: [],
20
+ },
21
+ execution: { type: 'function', handler: 'builtin.read' },
22
+ metadata: {
23
+ category: 'file',
24
+ icon: 'file',
25
+ requiresApproval: false,
26
+ permission: 'read',
27
+ supportsExternalPaths: true,
28
+ readOnly: true,
29
+ permissionPatterns: [{ arg: 'filePath', kind: 'path' }],
30
+ },
31
+ };
32
+ export const readHandler = async (args, context) => {
33
+ const filePathResult = requireString(args, 'filePath');
34
+ if ('error' in filePathResult)
35
+ return { success: false, error: filePathResult.error };
36
+ const filePath = filePathResult.value;
37
+ let absPath;
38
+ try {
39
+ absPath = resolveToolPath(filePath, context).absPath;
40
+ }
41
+ catch (error) {
42
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
43
+ }
44
+ const basename = path.basename(absPath);
45
+ const whitelist = ['.env.sample', '.env.example', '.example', '.env.template'];
46
+ const shouldBlockEnv = /^\.env(\.|$)/.test(basename) && !whitelist.some((suffix) => basename.endsWith(suffix));
47
+ if (shouldBlockEnv) {
48
+ return {
49
+ success: false,
50
+ error: `The user has blocked you from reading ${absPath}, DO NOT make further attempts to read it`,
51
+ };
52
+ }
53
+ const ext = path.extname(absPath).toLowerCase();
54
+ if (BINARY_EXTENSIONS.has(ext)) {
55
+ return { success: false, error: `Cannot read binary file: ${absPath}` };
56
+ }
57
+ let bytes;
58
+ try {
59
+ bytes = await fs.readFile(absPath);
60
+ }
61
+ catch (error) {
62
+ const message = error instanceof Error ? error.message : String(error);
63
+ return { success: false, error: `File not found: ${absPath}\n\n${message}` };
64
+ }
65
+ if (containsBinaryData(bytes)) {
66
+ return { success: false, error: `Cannot read binary file: ${absPath}` };
67
+ }
68
+ const text = new TextDecoder().decode(bytes);
69
+ const lines = text.replace(/\r\n/g, '\n').split('\n');
70
+ const offsetRaw = optionalNumber(args, 'offset');
71
+ const limitRaw = optionalNumber(args, 'limit');
72
+ const offset = Math.max(0, Math.floor(offsetRaw ?? 0));
73
+ const limit = Math.max(1, Math.floor(limitRaw ?? DEFAULT_READ_LIMIT));
74
+ const slice = lines.slice(offset, offset + limit);
75
+ const numbered = slice.map((line, index) => {
76
+ const trimmed = line.length > MAX_LINE_LENGTH ? line.substring(0, MAX_LINE_LENGTH) + '...' : line;
77
+ return `${String(index + offset + 1).padStart(5, '0')}| ${trimmed}`;
78
+ });
79
+ const totalLines = lines.length;
80
+ const lastReadLine = offset + slice.length;
81
+ const hasMoreLines = totalLines > lastReadLine;
82
+ let output = '<file>\n' + numbered.join('\n');
83
+ if (hasMoreLines) {
84
+ output += `\n\n(File has more lines. Use 'offset' parameter to read beyond line ${lastReadLine})`;
85
+ }
86
+ else {
87
+ output += `\n\n(End of file - total ${totalLines} lines)`;
88
+ }
89
+ output += '\n</file>';
90
+ return { success: true, data: output };
91
+ };
92
+ //# sourceMappingURL=read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/tools/builtin/read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { ToolDefinition, ToolHandler } from '../../types.js';
2
+ export declare function createSkillTool(options: {
3
+ enabled?: boolean;
4
+ searchPaths: string[];
5
+ }): {
6
+ tool: ToolDefinition;
7
+ handler: ToolHandler;
8
+ };
9
+ //# sourceMappingURL=skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/skill.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAkBlE,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,GAAG;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CA0HjD"}