forked from WHC/Hermit
Extensions: skills, plugins, MCP, sub-agents; configurable keys
- Skills (SKILL.md discovery, skill tool, /skills /skill) - plugin.json exec tools with permission prompts, timeouts and workspace trust (/plugins) - MCP stdio client: JSON-RPC initialize/tools/list/tools/call, mcp__server__tool, /mcp and sidebar status - task tool with general/explore/plan and .agent/agents/*.md roles, parallel read-only runs, cancel propagation, /agents - Keymap with Ctrl+X leader, keybinds.json overrides and /keys panel - Collapsed thinking, throttled streaming Markdown, leaner tool output, parallel read-only tools - Spawn: close-on-exec pipes and a process-wide fork lock - Tests for keymap, skills, plugins, MCP, sub-agents, shell compaction; docs/plugins.md
This commit is contained in:
+55
-4
@@ -167,6 +167,45 @@ int main(void) {
|
||||
"missing required arg");
|
||||
reset(&r);
|
||||
|
||||
/* compact read_file (default profile) */
|
||||
ctx.compact = 1;
|
||||
EXPECT(run(&ctx, mk("read_file", "path", "src/notes.txt", NULL), &r) == 0 &&
|
||||
strcmp(r.out, "src/notes.txt · 1 line\n1|TODO: x\n") == 0,
|
||||
"compact read: header + numbers");
|
||||
reset(&r);
|
||||
EXPECT(run(&ctx, mk("read_file", "path", "lines.txt", "offset", "10",
|
||||
"limit", "3", NULL),
|
||||
&r) == 0 &&
|
||||
strstr(r.out, "lines.txt · lines 10-12 of 100\n10|line 10\n") ==
|
||||
r.out &&
|
||||
strstr(r.out, "… 88 more lines; continue with offset=13"),
|
||||
"compact slice header and continuation");
|
||||
reset(&r);
|
||||
EXPECT(run(&ctx, mk("read_file", "path", "src/notes.txt", "line_numbers",
|
||||
"false", NULL),
|
||||
&r) == 0 &&
|
||||
strstr(r.out, "\nTODO: x\n") && !strstr(r.out, "1|"),
|
||||
"compact read without numbers");
|
||||
reset(&r);
|
||||
{
|
||||
char big[5000];
|
||||
memset(big, 'a', sizeof(big) - 2);
|
||||
big[sizeof(big) - 2] = '\n';
|
||||
big[sizeof(big) - 1] = 0;
|
||||
wfile("long.txt", big);
|
||||
EXPECT(run(&ctx, mk("read_file", "path", "long.txt", NULL), &r) == 0 &&
|
||||
strstr(r.out, "[line cut, +2998 bytes]") &&
|
||||
strstr(r.out, "1 long line cut"),
|
||||
"compact read cuts long lines");
|
||||
reset(&r);
|
||||
}
|
||||
wfile("empty.txt", "");
|
||||
EXPECT(run(&ctx, mk("read_file", "path", "empty.txt", NULL), &r) == 0 &&
|
||||
strstr(r.out, "empty file"),
|
||||
"compact read of an empty file");
|
||||
reset(&r);
|
||||
ctx.compact = 0;
|
||||
|
||||
/* list_dir */
|
||||
EXPECT(run(&ctx, mk("list_dir", NULL), &r) == 0, "list_dir ok");
|
||||
EXPECT(r.out && strstr(r.out, "src/") && strstr(r.out, " main.c"),
|
||||
@@ -180,6 +219,8 @@ int main(void) {
|
||||
EXPECT(run(&ctx, mk("list_dir", "path", "src", "depth", "1", NULL), &r) == 0 &&
|
||||
strstr(r.out, "deep/") && !strstr(r.out, "util.c"),
|
||||
"list_dir depth");
|
||||
EXPECT(r.out && strstr(r.out, "deep/ (1 entry)"),
|
||||
"list_dir counts entries at the depth limit");
|
||||
reset(&r);
|
||||
|
||||
/* glob */
|
||||
@@ -205,20 +246,22 @@ int main(void) {
|
||||
|
||||
/* grep */
|
||||
EXPECT(run(&ctx, mk("grep", "pattern", "int add", NULL), &r) == 0, "grep ok");
|
||||
EXPECT(r.out && strstr(r.out, "src/deep/util.c:1:int add"), "grep hit");
|
||||
EXPECT(r.out && strstr(r.out, "src/deep/util.c\n1:int add"), "grep hit grouped");
|
||||
EXPECT(r.out && strncmp(r.out, "1 match in 1 file\n", 18) == 0,
|
||||
"grep summary first");
|
||||
EXPECT(r.out && !strstr(r.out, "junk.c") && !strstr(r.out, "run.log"),
|
||||
"grep skips node_modules and ignored files");
|
||||
reset(&r);
|
||||
EXPECT(run(&ctx, mk("grep", "pattern", "x = \\d+", "glob", "*.c", NULL),
|
||||
&r) == 0 &&
|
||||
strstr(r.out, "src/main.c:3:"),
|
||||
strstr(r.out, "src/main.c\n3:"),
|
||||
"grep translates \\d");
|
||||
reset(&r);
|
||||
EXPECT(run(&ctx, mk("grep", "pattern", "RETURN", "ignore_case", "true",
|
||||
"path", "src/main.c", "context", "1", NULL),
|
||||
&r) == 0 &&
|
||||
strstr(r.out, "src/main.c:5: return 0;") &&
|
||||
strstr(r.out, "src/main.c-4-") && strstr(r.out, "src/main.c-6-"),
|
||||
strstr(r.out, "\n5: return 0;") && strstr(r.out, "\n4-") &&
|
||||
strstr(r.out, "\n6-"),
|
||||
"grep single file, icase, context");
|
||||
reset(&r);
|
||||
EXPECT(run(&ctx, mk("grep", "pattern", "(", NULL), &r) == 1 &&
|
||||
@@ -241,11 +284,19 @@ int main(void) {
|
||||
strstr(r.out, "not found"),
|
||||
"edit not found");
|
||||
reset(&r);
|
||||
EXPECT(run(&ctx, mk("edit_file", "path", "src/main.c", "old_string",
|
||||
"int main(void) {\n int x = 7;", "new_string", "y",
|
||||
NULL),
|
||||
&r) == 1 &&
|
||||
strstr(r.out, "appears (whitespace aside) at line 2"),
|
||||
"edit not found points at the near line");
|
||||
reset(&r);
|
||||
EXPECT(run(&ctx, mk("edit_file", "path", "src/deep/util.c", "old_string",
|
||||
"int a, int b", "new_string", "long a, long b", NULL),
|
||||
&r) == 1 &&
|
||||
strstr(r.out, "matches 2 places"),
|
||||
"edit ambiguous");
|
||||
EXPECT(r.out && strstr(r.out, "(lines 1, 2)"), "edit ambiguous lines");
|
||||
reset(&r);
|
||||
EXPECT(run(&ctx, mk("edit_file", "path", "src/deep/util.c", "old_string",
|
||||
"int a, int b", "new_string", "long a, long b",
|
||||
|
||||
Reference in New Issue
Block a user