agentool 0.0.1 → 1.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.
- package/README.md +738 -52
- package/dist/ask-user/index.cjs +8 -0
- package/dist/ask-user/index.d.cts +68 -0
- package/dist/ask-user/index.d.ts +68 -0
- package/dist/ask-user/index.js +8 -0
- package/dist/bash/index.cjs +8 -0
- package/dist/bash/index.d.cts +63 -0
- package/dist/bash/index.d.ts +63 -0
- package/dist/bash/index.js +8 -0
- package/dist/chunk-3EPGFWZV.cjs +30 -0
- package/dist/chunk-3VO6NETR.cjs +79 -0
- package/dist/chunk-44AFQ2B7.js +30 -0
- package/dist/chunk-4HIATLKI.js +112 -0
- package/dist/chunk-4HXAKPQH.cjs +36 -0
- package/dist/chunk-4YI2H55A.js +142 -0
- package/dist/chunk-56CL4JCW.cjs +53 -0
- package/dist/chunk-5NW4OGRI.cjs +99 -0
- package/dist/chunk-5O55DKOB.cjs +112 -0
- package/dist/chunk-5TDZF4IM.cjs +197 -0
- package/dist/chunk-6DJSWTWQ.cjs +40 -0
- package/dist/chunk-6PQLFDGT.js +117 -0
- package/dist/chunk-ACGW44YT.js +47 -0
- package/dist/chunk-CAEVLIQB.cjs +117 -0
- package/dist/chunk-CGTPF6IS.js +90 -0
- package/dist/chunk-E6NBEYZD.js +51 -0
- package/dist/chunk-EA3YV7ZG.js +79 -0
- package/dist/chunk-ECYT46FP.js +40 -0
- package/dist/chunk-FV2R5FFQ.cjs +102 -0
- package/dist/chunk-FW3UJ622.cjs +59 -0
- package/dist/chunk-G3ITTPGX.js +99 -0
- package/dist/chunk-HDKXSKMO.js +30 -0
- package/dist/chunk-HNP7JDQC.cjs +159 -0
- package/dist/chunk-HNUL2CID.cjs +34 -0
- package/dist/chunk-HZAQRHBT.js +99 -0
- package/dist/chunk-I3ONDY7P.js +46 -0
- package/dist/chunk-I6KFFQPV.cjs +58 -0
- package/dist/chunk-IEX4NOVN.cjs +48 -0
- package/dist/chunk-IRRNYFI5.js +48 -0
- package/dist/chunk-K77GC2QI.js +59 -0
- package/dist/chunk-L5JH4I77.cjs +51 -0
- package/dist/chunk-LK6SQH2G.cjs +30 -0
- package/dist/chunk-LPV5CN2K.js +58 -0
- package/dist/chunk-LTE5NG4D.js +53 -0
- package/dist/chunk-MF7CJVIZ.js +40 -0
- package/dist/chunk-MIYA7TNR.cjs +123 -0
- package/dist/chunk-MJCAXASI.js +123 -0
- package/dist/chunk-OM2UFTGS.cjs +47 -0
- package/dist/chunk-ONBH74ZV.cjs +90 -0
- package/dist/chunk-OXLQ7QVL.cjs +40 -0
- package/dist/chunk-P6Z5XFDS.js +73 -0
- package/dist/chunk-QZ5GS6HW.cjs +46 -0
- package/dist/chunk-S7IVHOA6.js +75 -0
- package/dist/chunk-SUSAPI5W.cjs +142 -0
- package/dist/chunk-TMW3XKKJ.js +34 -0
- package/dist/chunk-UDIG7332.js +159 -0
- package/dist/chunk-VLNDEVKS.js +102 -0
- package/dist/chunk-VXZ4RKJI.js +36 -0
- package/dist/chunk-XAQGZ374.js +197 -0
- package/dist/chunk-YPPPGGLA.cjs +99 -0
- package/dist/chunk-ZBLQV6UO.cjs +73 -0
- package/dist/chunk-ZFQZWXOI.cjs +75 -0
- package/dist/context-compaction/index.cjs +8 -0
- package/dist/context-compaction/index.d.cts +77 -0
- package/dist/context-compaction/index.d.ts +77 -0
- package/dist/context-compaction/index.js +8 -0
- package/dist/diff/index.cjs +9 -0
- package/dist/diff/index.d.cts +72 -0
- package/dist/diff/index.d.ts +72 -0
- package/dist/diff/index.js +9 -0
- package/dist/edit/index.cjs +10 -0
- package/dist/edit/index.d.cts +53 -0
- package/dist/edit/index.d.ts +53 -0
- package/dist/edit/index.js +10 -0
- package/dist/glob/index.cjs +10 -0
- package/dist/glob/index.d.cts +47 -0
- package/dist/glob/index.d.ts +47 -0
- package/dist/glob/index.js +10 -0
- package/dist/grep/index.cjs +10 -0
- package/dist/grep/index.d.cts +50 -0
- package/dist/grep/index.d.ts +50 -0
- package/dist/grep/index.js +10 -0
- package/dist/http-request/index.cjs +8 -0
- package/dist/http-request/index.d.cts +60 -0
- package/dist/http-request/index.d.ts +60 -0
- package/dist/http-request/index.js +8 -0
- package/dist/index.cjs +133 -0
- package/dist/index.d.cts +23 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +133 -0
- package/dist/lsp/index.cjs +10 -0
- package/dist/lsp/index.d.cts +35 -0
- package/dist/lsp/index.d.ts +35 -0
- package/dist/lsp/index.js +10 -0
- package/dist/memory/index.cjs +9 -0
- package/dist/memory/index.d.cts +63 -0
- package/dist/memory/index.d.ts +63 -0
- package/dist/memory/index.js +9 -0
- package/dist/multi-edit/index.cjs +11 -0
- package/dist/multi-edit/index.d.cts +72 -0
- package/dist/multi-edit/index.d.ts +72 -0
- package/dist/multi-edit/index.js +11 -0
- package/dist/read/index.cjs +10 -0
- package/dist/read/index.d.cts +67 -0
- package/dist/read/index.d.ts +67 -0
- package/dist/read/index.js +10 -0
- package/dist/sleep/index.cjs +8 -0
- package/dist/sleep/index.d.cts +60 -0
- package/dist/sleep/index.d.ts +60 -0
- package/dist/sleep/index.js +8 -0
- package/dist/task-create/index.cjs +9 -0
- package/dist/task-create/index.d.cts +19 -0
- package/dist/task-create/index.d.ts +19 -0
- package/dist/task-create/index.js +9 -0
- package/dist/task-get/index.cjs +9 -0
- package/dist/task-get/index.d.cts +15 -0
- package/dist/task-get/index.d.ts +15 -0
- package/dist/task-get/index.js +9 -0
- package/dist/task-list/index.cjs +9 -0
- package/dist/task-list/index.d.cts +11 -0
- package/dist/task-list/index.d.ts +11 -0
- package/dist/task-list/index.js +9 -0
- package/dist/task-update/index.cjs +9 -0
- package/dist/task-update/index.d.cts +31 -0
- package/dist/task-update/index.d.ts +31 -0
- package/dist/task-update/index.js +9 -0
- package/dist/tool-search/index.cjs +8 -0
- package/dist/tool-search/index.d.cts +18 -0
- package/dist/tool-search/index.d.ts +18 -0
- package/dist/tool-search/index.js +8 -0
- package/dist/types-3QPDuCXN.d.cts +45 -0
- package/dist/types-3QPDuCXN.d.ts +45 -0
- package/dist/web-fetch/index.cjs +8 -0
- package/dist/web-fetch/index.d.cts +54 -0
- package/dist/web-fetch/index.d.ts +54 -0
- package/dist/web-fetch/index.js +8 -0
- package/dist/web-search/index.cjs +8 -0
- package/dist/web-search/index.d.cts +21 -0
- package/dist/web-search/index.d.ts +21 -0
- package/dist/web-search/index.js +8 -0
- package/dist/write/index.cjs +10 -0
- package/dist/write/index.d.cts +47 -0
- package/dist/write/index.d.ts +47 -0
- package/dist/write/index.js +10 -0
- package/package.json +170 -20
- package/dist/core/index.d.ts +0 -20
- package/dist/core/index.js +0 -1
- package/dist/core/index.js.map +0 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// src/tool-search/index.ts
|
|
2
|
+
import { tool } from "ai";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
function createToolSearch(config = {}) {
|
|
5
|
+
return tool({
|
|
6
|
+
description: "Search for available tools by name or keyword. Returns matching tool names and descriptions.",
|
|
7
|
+
inputSchema: z.object({
|
|
8
|
+
query: z.string().describe("Query to find tools by name or keyword"),
|
|
9
|
+
max_results: z.number().optional().default(5).describe("Max results to return")
|
|
10
|
+
}),
|
|
11
|
+
execute: async ({ query, max_results }) => {
|
|
12
|
+
try {
|
|
13
|
+
const registry = config.tools ?? {};
|
|
14
|
+
const entries = Object.entries(registry);
|
|
15
|
+
if (entries.length === 0) {
|
|
16
|
+
return "No tools registered. Provide a tools registry via createToolSearch({ tools: { ... } })";
|
|
17
|
+
}
|
|
18
|
+
const lower = query.toLowerCase();
|
|
19
|
+
const scored = entries.map(([name, { description }]) => {
|
|
20
|
+
let score = 0;
|
|
21
|
+
const nameLower = name.toLowerCase();
|
|
22
|
+
const descLower = description.toLowerCase();
|
|
23
|
+
if (nameLower === lower) score += 10;
|
|
24
|
+
else if (nameLower.includes(lower)) score += 5;
|
|
25
|
+
if (descLower.includes(lower)) score += 3;
|
|
26
|
+
for (const word of lower.split(/\s+/)) {
|
|
27
|
+
if (nameLower.includes(word)) score += 2;
|
|
28
|
+
if (descLower.includes(word)) score += 1;
|
|
29
|
+
}
|
|
30
|
+
return { name, description, score };
|
|
31
|
+
}).filter((e) => e.score > 0).sort((a, b) => b.score - a.score).slice(0, max_results);
|
|
32
|
+
if (scored.length === 0) {
|
|
33
|
+
return `No tools matched query "${query}".`;
|
|
34
|
+
}
|
|
35
|
+
return scored.map((e) => `${e.name}: ${e.description}`).join("\n");
|
|
36
|
+
} catch (error) {
|
|
37
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
38
|
+
return `Error [tool-search]: ${msg}`;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
var toolSearch = createToolSearch();
|
|
44
|
+
|
|
45
|
+
export {
|
|
46
|
+
createToolSearch,
|
|
47
|
+
toolSearch
|
|
48
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// src/context-compaction/index.ts
|
|
2
|
+
import { tool, zodSchema } from "ai";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
var parametersSchema = z.object({
|
|
5
|
+
messages: z.array(
|
|
6
|
+
z.object({
|
|
7
|
+
role: z.string().describe("Message role (system, user, assistant)"),
|
|
8
|
+
content: z.string().describe("Message content")
|
|
9
|
+
})
|
|
10
|
+
).describe("The conversation messages to compact"),
|
|
11
|
+
maxTokens: z.number().optional().describe(
|
|
12
|
+
"Target maximum tokens (default: config.maxTokens or 4096)"
|
|
13
|
+
)
|
|
14
|
+
});
|
|
15
|
+
function createContextCompaction(config = {}) {
|
|
16
|
+
return tool({
|
|
17
|
+
description: "Compact conversation history by summarizing older messages to reduce context size. Requires a summarize function in config. Returns compacted messages where total chars < maxTokens * 4.",
|
|
18
|
+
inputSchema: zodSchema(parametersSchema),
|
|
19
|
+
execute: async ({
|
|
20
|
+
messages,
|
|
21
|
+
maxTokens: inputMaxTokens
|
|
22
|
+
}) => {
|
|
23
|
+
const maxTokens = inputMaxTokens ?? config.maxTokens ?? 4096;
|
|
24
|
+
const charBudget = maxTokens * 4;
|
|
25
|
+
const totalChars = messages.reduce(
|
|
26
|
+
(sum, m) => sum + m.content.length,
|
|
27
|
+
0
|
|
28
|
+
);
|
|
29
|
+
if (totalChars <= charBudget) {
|
|
30
|
+
return JSON.stringify({
|
|
31
|
+
compacted: false,
|
|
32
|
+
messages,
|
|
33
|
+
reason: "Already within token budget"
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (!config.summarize) {
|
|
37
|
+
return "Error [context-compaction]: No summarize function configured. Provide a summarize callback in the tool config.";
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const summary = await config.summarize(messages);
|
|
41
|
+
const compactedMessages = [{ role: "system", content: summary }];
|
|
42
|
+
return JSON.stringify({
|
|
43
|
+
compacted: true,
|
|
44
|
+
messages: compactedMessages,
|
|
45
|
+
originalCount: messages.length
|
|
46
|
+
});
|
|
47
|
+
} catch (error) {
|
|
48
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
49
|
+
return `Error [context-compaction]: Summarization failed: ${msg}`;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
var contextCompaction = createContextCompaction();
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
createContextCompaction,
|
|
58
|
+
contextCompaction
|
|
59
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/shared/task-store.ts
|
|
2
|
+
var _promises = require('fs/promises');
|
|
3
|
+
var _path = require('path');
|
|
4
|
+
var _crypto = require('crypto');
|
|
5
|
+
function generateId() {
|
|
6
|
+
return _crypto.randomBytes.call(void 0, 4).toString("hex");
|
|
7
|
+
}
|
|
8
|
+
async function loadTasks(filePath) {
|
|
9
|
+
try {
|
|
10
|
+
const data = await _promises.readFile.call(void 0, filePath, "utf-8");
|
|
11
|
+
return JSON.parse(data);
|
|
12
|
+
} catch (e) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
async function saveTasks(filePath, tasks) {
|
|
17
|
+
await _promises.mkdir.call(void 0, _path.dirname.call(void 0, filePath), { recursive: true });
|
|
18
|
+
await _promises.writeFile.call(void 0, filePath, JSON.stringify(tasks, null, 2), "utf-8");
|
|
19
|
+
}
|
|
20
|
+
function formatTask(t) {
|
|
21
|
+
const lines = [
|
|
22
|
+
`ID: ${t.id}`,
|
|
23
|
+
`Subject: ${t.subject}`,
|
|
24
|
+
`Description: ${t.description}`,
|
|
25
|
+
`Status: ${t.status}`
|
|
26
|
+
];
|
|
27
|
+
if (t.owner) lines.push(`Owner: ${t.owner}`);
|
|
28
|
+
if (t.activeForm) lines.push(`Active: ${t.activeForm}`);
|
|
29
|
+
if (t.blocks.length > 0) lines.push(`Blocks: ${t.blocks.join(", ")}`);
|
|
30
|
+
if (t.blockedBy.length > 0) lines.push(`Blocked by: ${t.blockedBy.join(", ")}`);
|
|
31
|
+
if (t.metadata && Object.keys(t.metadata).length > 0) {
|
|
32
|
+
lines.push(`Metadata: ${JSON.stringify(t.metadata)}`);
|
|
33
|
+
}
|
|
34
|
+
lines.push(`Created: ${t.createdAt}`);
|
|
35
|
+
lines.push(`Updated: ${t.updatedAt}`);
|
|
36
|
+
return lines.join("\n");
|
|
37
|
+
}
|
|
38
|
+
function formatTaskSummary(t) {
|
|
39
|
+
const parts = [`#${t.id} [${t.status}] ${t.subject}`];
|
|
40
|
+
if (t.owner) parts.push(`(owner: ${t.owner})`);
|
|
41
|
+
if (t.blockedBy.length > 0) parts.push(`[blocked by ${t.blockedBy.join(", ")}]`);
|
|
42
|
+
return parts.join(" ");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
exports.generateId = generateId; exports.loadTasks = loadTasks; exports.saveTasks = saveTasks; exports.formatTask = formatTask; exports.formatTaskSummary = formatTaskSummary;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/web-search/index.ts
|
|
2
|
+
var _ai = require('ai');
|
|
3
|
+
var _zod = require('zod');
|
|
4
|
+
function createWebSearch(config = {}) {
|
|
5
|
+
return _ai.tool.call(void 0, {
|
|
6
|
+
description: "Search the web for information using a search query. Results can be filtered by allowed or blocked domains.",
|
|
7
|
+
inputSchema: _zod.z.object({
|
|
8
|
+
query: _zod.z.string().min(2).describe("The search query to use"),
|
|
9
|
+
allowed_domains: _zod.z.array(_zod.z.string()).optional().describe("Only include search results from these domains"),
|
|
10
|
+
blocked_domains: _zod.z.array(_zod.z.string()).optional().describe("Never include search results from these domains")
|
|
11
|
+
}),
|
|
12
|
+
execute: async ({ query, allowed_domains, blocked_domains }) => {
|
|
13
|
+
try {
|
|
14
|
+
if (!config.onSearch) {
|
|
15
|
+
return "Error [web-search]: No search callback configured. Provide onSearch via createWebSearch({ onSearch: async (query, opts) => ... })";
|
|
16
|
+
}
|
|
17
|
+
return await config.onSearch(query, { allowed_domains, blocked_domains });
|
|
18
|
+
} catch (error) {
|
|
19
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
20
|
+
return `Error [web-search]: ${msg}`;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
var webSearch = createWebSearch();
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
exports.createWebSearch = createWebSearch; exports.webSearch = webSearch;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// src/http-request/index.ts
|
|
2
|
+
import { tool } from "ai";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
function createHttpRequest(config = {}) {
|
|
5
|
+
return tool({
|
|
6
|
+
description: "Make an HTTP request to a URL. Returns the response status, headers, and body. Use this for API interactions, webhook calls, and service health checks. Unlike web-fetch, this returns raw response data without markdown conversion.",
|
|
7
|
+
inputSchema: z.object({
|
|
8
|
+
method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"]).describe("HTTP method"),
|
|
9
|
+
url: z.string().describe("The URL to send the request to"),
|
|
10
|
+
headers: z.record(z.string()).optional().describe("Request headers as key-value pairs"),
|
|
11
|
+
body: z.string().optional().describe("Request body (for POST, PUT, PATCH)"),
|
|
12
|
+
timeout: z.number().optional().describe("Request timeout in milliseconds (default: 30000)")
|
|
13
|
+
}),
|
|
14
|
+
execute: async ({ method, url, headers, body, timeout }) => {
|
|
15
|
+
try {
|
|
16
|
+
const timeoutMs = timeout ?? config.timeout ?? 3e4;
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
19
|
+
const mergedHeaders = { ...config.defaultHeaders, ...headers };
|
|
20
|
+
const response = await fetch(url, {
|
|
21
|
+
method,
|
|
22
|
+
headers: mergedHeaders,
|
|
23
|
+
body: ["POST", "PUT", "PATCH"].includes(method) ? body : void 0,
|
|
24
|
+
signal: controller.signal
|
|
25
|
+
});
|
|
26
|
+
clearTimeout(timeoutId);
|
|
27
|
+
const responseBody = await response.text();
|
|
28
|
+
const responseHeaders = {};
|
|
29
|
+
response.headers.forEach((value, key) => {
|
|
30
|
+
responseHeaders[key] = value;
|
|
31
|
+
});
|
|
32
|
+
return JSON.stringify(
|
|
33
|
+
{
|
|
34
|
+
status: response.status,
|
|
35
|
+
statusText: response.statusText,
|
|
36
|
+
headers: responseHeaders,
|
|
37
|
+
body: responseBody
|
|
38
|
+
},
|
|
39
|
+
null,
|
|
40
|
+
2
|
|
41
|
+
);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
const effectiveTimeout = timeout ?? config.timeout ?? 3e4;
|
|
44
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
45
|
+
return `Error [http-request]: Request timed out after ${effectiveTimeout}ms for ${method} ${url}. Try increasing the timeout or verify the server is responsive.`;
|
|
46
|
+
}
|
|
47
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
48
|
+
return `Error [http-request]: ${method} ${url} failed: ${msg}. Verify the URL is correct and the server is reachable.`;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
var httpRequest = createHttpRequest();
|
|
54
|
+
|
|
55
|
+
export {
|
|
56
|
+
createHttpRequest,
|
|
57
|
+
httpRequest
|
|
58
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatTask,
|
|
3
|
+
generateId,
|
|
4
|
+
loadTasks,
|
|
5
|
+
saveTasks
|
|
6
|
+
} from "./chunk-E6NBEYZD.js";
|
|
7
|
+
|
|
8
|
+
// src/task-create/index.ts
|
|
9
|
+
import { tool } from "ai";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
function createTaskCreate(config = {}) {
|
|
13
|
+
const cwd = config.cwd ?? process.cwd();
|
|
14
|
+
const tasksFile = config.tasksFile ?? join(cwd, ".agentool", "tasks.json");
|
|
15
|
+
return tool({
|
|
16
|
+
description: 'Create a new task to track work. Each task gets a unique ID, starts with "pending" status, and can include optional metadata.',
|
|
17
|
+
inputSchema: z.object({
|
|
18
|
+
subject: z.string().describe("A brief title for the task"),
|
|
19
|
+
description: z.string().describe("What needs to be done"),
|
|
20
|
+
metadata: z.record(z.string(), z.unknown()).optional().describe("Arbitrary metadata to attach to the task")
|
|
21
|
+
}),
|
|
22
|
+
execute: async ({ subject, description, metadata }) => {
|
|
23
|
+
try {
|
|
24
|
+
const tasks = await loadTasks(tasksFile);
|
|
25
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
26
|
+
const entry = {
|
|
27
|
+
id: generateId(),
|
|
28
|
+
subject,
|
|
29
|
+
description,
|
|
30
|
+
status: "pending",
|
|
31
|
+
blocks: [],
|
|
32
|
+
blockedBy: [],
|
|
33
|
+
metadata,
|
|
34
|
+
createdAt: now,
|
|
35
|
+
updatedAt: now
|
|
36
|
+
};
|
|
37
|
+
tasks.push(entry);
|
|
38
|
+
await saveTasks(tasksFile, tasks);
|
|
39
|
+
return `Created task ${entry.id}.
|
|
40
|
+
${formatTask(entry)}`;
|
|
41
|
+
} catch (error) {
|
|
42
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
43
|
+
return `Error [task-create]: ${msg}`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
var taskCreate = createTaskCreate();
|
|
49
|
+
|
|
50
|
+
export {
|
|
51
|
+
createTaskCreate,
|
|
52
|
+
taskCreate
|
|
53
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// src/sleep/index.ts
|
|
2
|
+
import { tool, zodSchema } from "ai";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
function createSleep(config = {}) {
|
|
5
|
+
const maxDuration = config.maxDuration ?? 3e5;
|
|
6
|
+
return tool({
|
|
7
|
+
description: "Pause execution for a specified duration. Useful for rate limiting, polling intervals, or waiting for external processes. Maximum duration is 300 seconds (5 minutes).",
|
|
8
|
+
inputSchema: zodSchema(
|
|
9
|
+
z.object({
|
|
10
|
+
durationMs: z.number().describe("Duration to sleep in milliseconds"),
|
|
11
|
+
reason: z.string().optional().describe("Optional reason for the sleep")
|
|
12
|
+
})
|
|
13
|
+
),
|
|
14
|
+
execute: async ({ durationMs, reason }) => {
|
|
15
|
+
try {
|
|
16
|
+
const clamped = Math.max(0, Math.min(durationMs, maxDuration));
|
|
17
|
+
const start = Date.now();
|
|
18
|
+
await new Promise((resolve) => setTimeout(resolve, clamped));
|
|
19
|
+
const elapsed = Date.now() - start;
|
|
20
|
+
const parts = [`Slept for ${elapsed}ms`];
|
|
21
|
+
if (reason) parts.push(`Reason: ${reason}`);
|
|
22
|
+
if (clamped !== durationMs) {
|
|
23
|
+
parts.push(
|
|
24
|
+
`(clamped from ${durationMs}ms to ${clamped}ms, max: ${maxDuration}ms)`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
return parts.join(". ");
|
|
28
|
+
} catch (error) {
|
|
29
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
30
|
+
return `Sleep failed: ${message}`;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
var sleep = createSleep();
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
createSleep,
|
|
39
|
+
sleep
|
|
40
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/shared/ripgrep.ts
|
|
2
|
+
var _child_process = require('child_process');
|
|
3
|
+
var MAX_BUFFER_SIZE = 2e7;
|
|
4
|
+
var DEFAULT_TIMEOUT = 2e4;
|
|
5
|
+
var INSTALL_URL = "https://github.com/BurntSushi/ripgrep#installation";
|
|
6
|
+
var RipgrepNotFoundError = class extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(
|
|
9
|
+
_nullishCoalesce(message, () => ( `ripgrep (rg) not found on PATH. Install it from: ${INSTALL_URL}`))
|
|
10
|
+
);
|
|
11
|
+
this.name = "RipgrepNotFoundError";
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
var RipgrepTimeoutError = class extends Error {
|
|
15
|
+
/**
|
|
16
|
+
* Lines captured from stdout before the process was killed.
|
|
17
|
+
* May be empty if no output arrived before the timeout.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
constructor(message, partialResults) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = "RipgrepTimeoutError";
|
|
23
|
+
this.partialResults = partialResults;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
function findRg() {
|
|
27
|
+
try {
|
|
28
|
+
const result = _child_process.execFileSync.call(void 0, "which", ["rg"], {
|
|
29
|
+
encoding: "utf-8",
|
|
30
|
+
timeout: 5e3
|
|
31
|
+
});
|
|
32
|
+
const rgPath = result.trim();
|
|
33
|
+
if (!rgPath) {
|
|
34
|
+
throw new RipgrepNotFoundError();
|
|
35
|
+
}
|
|
36
|
+
return rgPath;
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (error instanceof RipgrepNotFoundError) {
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
throw new RipgrepNotFoundError();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function isEagainError(stderr) {
|
|
45
|
+
return stderr.includes("os error 11") || stderr.includes("Resource temporarily unavailable");
|
|
46
|
+
}
|
|
47
|
+
function parseStdout(stdout) {
|
|
48
|
+
return stdout.trim().split("\n").map((line) => line.replace(/\r$/, "")).filter(Boolean);
|
|
49
|
+
}
|
|
50
|
+
async function executeRipgrep(args, target, options) {
|
|
51
|
+
const rgPath = findRg();
|
|
52
|
+
const timeout = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _ => _.timeout]), () => ( DEFAULT_TIMEOUT));
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
const handleResult = (error, stdout, stderr, isRetry) => {
|
|
55
|
+
if (!error) {
|
|
56
|
+
resolve(parseStdout(stdout));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (error.code === 1) {
|
|
60
|
+
resolve([]);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const CRITICAL_CODES = ["ENOENT", "EACCES", "EPERM"];
|
|
64
|
+
if (CRITICAL_CODES.includes(error.code)) {
|
|
65
|
+
reject(error);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (!isRetry && isEagainError(stderr)) {
|
|
69
|
+
_child_process.execFile.call(void 0,
|
|
70
|
+
rgPath,
|
|
71
|
+
["-j", "1", ...args, target],
|
|
72
|
+
{
|
|
73
|
+
maxBuffer: MAX_BUFFER_SIZE,
|
|
74
|
+
signal: _optionalChain([options, 'optionalAccess', _2 => _2.signal]),
|
|
75
|
+
timeout,
|
|
76
|
+
killSignal: "SIGKILL"
|
|
77
|
+
},
|
|
78
|
+
(retryErr, retryStdout, retryStderr) => {
|
|
79
|
+
handleResult(retryErr, retryStdout, retryStderr, true);
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const hasOutput = stdout && stdout.trim().length > 0;
|
|
85
|
+
const isTimeout = error.signal === "SIGTERM" || error.signal === "SIGKILL" || error.code === "ABORT_ERR";
|
|
86
|
+
const isBufferOverflow = error.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER";
|
|
87
|
+
let lines = [];
|
|
88
|
+
if (hasOutput) {
|
|
89
|
+
lines = parseStdout(stdout);
|
|
90
|
+
if (lines.length > 0 && (isTimeout || isBufferOverflow)) {
|
|
91
|
+
lines = lines.slice(0, -1);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (isTimeout && lines.length === 0) {
|
|
95
|
+
reject(
|
|
96
|
+
new RipgrepTimeoutError(
|
|
97
|
+
`Ripgrep search timed out after ${timeout / 1e3} seconds. Try a more specific path or pattern.`,
|
|
98
|
+
lines
|
|
99
|
+
)
|
|
100
|
+
);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
resolve(lines);
|
|
104
|
+
};
|
|
105
|
+
_child_process.execFile.call(void 0,
|
|
106
|
+
rgPath,
|
|
107
|
+
[...args, target],
|
|
108
|
+
{
|
|
109
|
+
maxBuffer: MAX_BUFFER_SIZE,
|
|
110
|
+
signal: _optionalChain([options, 'optionalAccess', _3 => _3.signal]),
|
|
111
|
+
timeout,
|
|
112
|
+
killSignal: "SIGKILL"
|
|
113
|
+
},
|
|
114
|
+
(error, stdout, stderr) => {
|
|
115
|
+
handleResult(error, stdout, stderr, false);
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
exports.executeRipgrep = executeRipgrep;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// src/shared/ripgrep.ts
|
|
2
|
+
import { execFile, execFileSync } from "child_process";
|
|
3
|
+
var MAX_BUFFER_SIZE = 2e7;
|
|
4
|
+
var DEFAULT_TIMEOUT = 2e4;
|
|
5
|
+
var INSTALL_URL = "https://github.com/BurntSushi/ripgrep#installation";
|
|
6
|
+
var RipgrepNotFoundError = class extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(
|
|
9
|
+
message ?? `ripgrep (rg) not found on PATH. Install it from: ${INSTALL_URL}`
|
|
10
|
+
);
|
|
11
|
+
this.name = "RipgrepNotFoundError";
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
var RipgrepTimeoutError = class extends Error {
|
|
15
|
+
/**
|
|
16
|
+
* Lines captured from stdout before the process was killed.
|
|
17
|
+
* May be empty if no output arrived before the timeout.
|
|
18
|
+
*/
|
|
19
|
+
partialResults;
|
|
20
|
+
constructor(message, partialResults) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = "RipgrepTimeoutError";
|
|
23
|
+
this.partialResults = partialResults;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
function findRg() {
|
|
27
|
+
try {
|
|
28
|
+
const result = execFileSync("which", ["rg"], {
|
|
29
|
+
encoding: "utf-8",
|
|
30
|
+
timeout: 5e3
|
|
31
|
+
});
|
|
32
|
+
const rgPath = result.trim();
|
|
33
|
+
if (!rgPath) {
|
|
34
|
+
throw new RipgrepNotFoundError();
|
|
35
|
+
}
|
|
36
|
+
return rgPath;
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (error instanceof RipgrepNotFoundError) {
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
throw new RipgrepNotFoundError();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function isEagainError(stderr) {
|
|
45
|
+
return stderr.includes("os error 11") || stderr.includes("Resource temporarily unavailable");
|
|
46
|
+
}
|
|
47
|
+
function parseStdout(stdout) {
|
|
48
|
+
return stdout.trim().split("\n").map((line) => line.replace(/\r$/, "")).filter(Boolean);
|
|
49
|
+
}
|
|
50
|
+
async function executeRipgrep(args, target, options) {
|
|
51
|
+
const rgPath = findRg();
|
|
52
|
+
const timeout = options?.timeout ?? DEFAULT_TIMEOUT;
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
const handleResult = (error, stdout, stderr, isRetry) => {
|
|
55
|
+
if (!error) {
|
|
56
|
+
resolve(parseStdout(stdout));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (error.code === 1) {
|
|
60
|
+
resolve([]);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const CRITICAL_CODES = ["ENOENT", "EACCES", "EPERM"];
|
|
64
|
+
if (CRITICAL_CODES.includes(error.code)) {
|
|
65
|
+
reject(error);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (!isRetry && isEagainError(stderr)) {
|
|
69
|
+
execFile(
|
|
70
|
+
rgPath,
|
|
71
|
+
["-j", "1", ...args, target],
|
|
72
|
+
{
|
|
73
|
+
maxBuffer: MAX_BUFFER_SIZE,
|
|
74
|
+
signal: options?.signal,
|
|
75
|
+
timeout,
|
|
76
|
+
killSignal: "SIGKILL"
|
|
77
|
+
},
|
|
78
|
+
(retryErr, retryStdout, retryStderr) => {
|
|
79
|
+
handleResult(retryErr, retryStdout, retryStderr, true);
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const hasOutput = stdout && stdout.trim().length > 0;
|
|
85
|
+
const isTimeout = error.signal === "SIGTERM" || error.signal === "SIGKILL" || error.code === "ABORT_ERR";
|
|
86
|
+
const isBufferOverflow = error.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER";
|
|
87
|
+
let lines = [];
|
|
88
|
+
if (hasOutput) {
|
|
89
|
+
lines = parseStdout(stdout);
|
|
90
|
+
if (lines.length > 0 && (isTimeout || isBufferOverflow)) {
|
|
91
|
+
lines = lines.slice(0, -1);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (isTimeout && lines.length === 0) {
|
|
95
|
+
reject(
|
|
96
|
+
new RipgrepTimeoutError(
|
|
97
|
+
`Ripgrep search timed out after ${timeout / 1e3} seconds. Try a more specific path or pattern.`,
|
|
98
|
+
lines
|
|
99
|
+
)
|
|
100
|
+
);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
resolve(lines);
|
|
104
|
+
};
|
|
105
|
+
execFile(
|
|
106
|
+
rgPath,
|
|
107
|
+
[...args, target],
|
|
108
|
+
{
|
|
109
|
+
maxBuffer: MAX_BUFFER_SIZE,
|
|
110
|
+
signal: options?.signal,
|
|
111
|
+
timeout,
|
|
112
|
+
killSignal: "SIGKILL"
|
|
113
|
+
},
|
|
114
|
+
(error, stdout, stderr) => {
|
|
115
|
+
handleResult(error, stdout, stderr, false);
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export {
|
|
122
|
+
executeRipgrep
|
|
123
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkCAEVLIQBcjs = require('./chunk-CAEVLIQB.cjs');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunkQZ5GS6HWcjs = require('./chunk-QZ5GS6HW.cjs');
|
|
8
|
+
|
|
9
|
+
// src/read/index.ts
|
|
10
|
+
var _ai = require('ai');
|
|
11
|
+
var _zod = require('zod');
|
|
12
|
+
function createRead(config = {}) {
|
|
13
|
+
const cwd = _nullishCoalesce(config.cwd, () => ( process.cwd()));
|
|
14
|
+
const defaultMaxLines = _nullishCoalesce(config.maxLines, () => ( 2e3));
|
|
15
|
+
return _ai.tool.call(void 0, {
|
|
16
|
+
description: 'Read a file from the local filesystem and return its contents with line numbers. Supports absolute paths, relative paths (resolved against the working directory), and tilde (~) home directory expansion. Returns numbered lines in "lineNumber\\tcontent" format. Use offset and limit to read specific ranges of large files.',
|
|
17
|
+
inputSchema: _zod.z.object({
|
|
18
|
+
file_path: _zod.z.string().describe("The absolute path to the file to read"),
|
|
19
|
+
offset: _zod.z.number().int().nonnegative().optional().describe("The line number to start reading from (default: 0)"),
|
|
20
|
+
limit: _zod.z.number().int().positive().optional().describe("The number of lines to read (default: 2000)")
|
|
21
|
+
}),
|
|
22
|
+
execute: async ({ file_path, offset, limit }) => {
|
|
23
|
+
try {
|
|
24
|
+
const absolutePath = _chunkQZ5GS6HWcjs.expandPath.call(void 0, file_path, cwd);
|
|
25
|
+
const result = await _chunkCAEVLIQBcjs.readFileInRange.call(void 0,
|
|
26
|
+
absolutePath,
|
|
27
|
+
_nullishCoalesce(offset, () => ( 0)),
|
|
28
|
+
_nullishCoalesce(limit, () => ( defaultMaxLines))
|
|
29
|
+
);
|
|
30
|
+
const numbered = _chunkCAEVLIQBcjs.addLineNumbers.call(void 0, {
|
|
31
|
+
content: result.content,
|
|
32
|
+
startLine: (_nullishCoalesce(offset, () => ( 0))) + 1
|
|
33
|
+
});
|
|
34
|
+
return numbered;
|
|
35
|
+
} catch (error) {
|
|
36
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
37
|
+
return `Error [read]: ${msg}`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
var read = createRead();
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
exports.createRead = createRead; exports.read = read;
|