@zhijiewang/openharness 0.1.2 → 0.2.1

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 (120) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
  3. package/.github/pull_request_template.md +24 -0
  4. package/CHANGELOG.md +1 -1
  5. package/CODE_OF_CONDUCT.md +43 -0
  6. package/README.md +109 -62
  7. package/SECURITY.md +21 -0
  8. package/dist/Tool.d.ts +1 -1
  9. package/dist/Tool.js +1 -1
  10. package/dist/commands/index.d.ts +37 -0
  11. package/dist/commands/index.d.ts.map +1 -0
  12. package/dist/commands/index.js +189 -0
  13. package/dist/commands/index.js.map +1 -0
  14. package/dist/components/App.d.ts.map +1 -1
  15. package/dist/components/App.js +3 -2
  16. package/dist/components/App.js.map +1 -1
  17. package/dist/components/ErrorBoundary.d.ts +17 -0
  18. package/dist/components/ErrorBoundary.d.ts.map +1 -0
  19. package/dist/components/ErrorBoundary.js +19 -0
  20. package/dist/components/ErrorBoundary.js.map +1 -0
  21. package/dist/components/Markdown.d.ts.map +1 -1
  22. package/dist/components/Markdown.js +70 -18
  23. package/dist/components/Markdown.js.map +1 -1
  24. package/dist/components/Messages.d.ts.map +1 -1
  25. package/dist/components/Messages.js +10 -4
  26. package/dist/components/Messages.js.map +1 -1
  27. package/dist/components/PermissionPrompt.d.ts.map +1 -1
  28. package/dist/components/PermissionPrompt.js +25 -7
  29. package/dist/components/PermissionPrompt.js.map +1 -1
  30. package/dist/components/REPL.d.ts.map +1 -1
  31. package/dist/components/REPL.js +60 -6
  32. package/dist/components/REPL.js.map +1 -1
  33. package/dist/components/Spinner.d.ts +3 -2
  34. package/dist/components/Spinner.d.ts.map +1 -1
  35. package/dist/components/Spinner.js +22 -4
  36. package/dist/components/Spinner.js.map +1 -1
  37. package/dist/components/TextInput.d.ts.map +1 -1
  38. package/dist/components/TextInput.js +4 -1
  39. package/dist/components/TextInput.js.map +1 -1
  40. package/dist/git/index.d.ts +47 -0
  41. package/dist/git/index.d.ts.map +1 -0
  42. package/dist/git/index.js +151 -0
  43. package/dist/git/index.js.map +1 -0
  44. package/dist/harness/session.d.ts.map +1 -1
  45. package/dist/harness/session.js +2 -1
  46. package/dist/harness/session.js.map +1 -1
  47. package/dist/main.js +89 -3
  48. package/dist/main.js.map +1 -1
  49. package/dist/providers/openai.js +11 -1
  50. package/dist/providers/openai.js.map +1 -1
  51. package/dist/providers/openrouter.js +11 -1
  52. package/dist/providers/openrouter.js.map +1 -1
  53. package/dist/query.d.ts +15 -11
  54. package/dist/query.d.ts.map +1 -1
  55. package/dist/query.js +196 -80
  56. package/dist/query.js.map +1 -1
  57. package/dist/services/StreamingToolExecutor.d.ts +25 -0
  58. package/dist/services/StreamingToolExecutor.d.ts.map +1 -0
  59. package/dist/services/StreamingToolExecutor.js +107 -0
  60. package/dist/services/StreamingToolExecutor.js.map +1 -0
  61. package/dist/tools/AgentTool/index.d.ts +15 -0
  62. package/dist/tools/AgentTool/index.d.ts.map +1 -0
  63. package/dist/tools/AgentTool/index.js +30 -0
  64. package/dist/tools/AgentTool/index.js.map +1 -0
  65. package/dist/tools/AskUserTool/index.d.ts +15 -0
  66. package/dist/tools/AskUserTool/index.d.ts.map +1 -0
  67. package/dist/tools/AskUserTool/index.js +30 -0
  68. package/dist/tools/AskUserTool/index.js.map +1 -0
  69. package/dist/tools/EnterPlanModeTool/index.d.ts +6 -0
  70. package/dist/tools/EnterPlanModeTool/index.d.ts.map +1 -0
  71. package/dist/tools/EnterPlanModeTool/index.js +37 -0
  72. package/dist/tools/EnterPlanModeTool/index.js.map +1 -0
  73. package/dist/tools/ExitPlanModeTool/index.d.ts +6 -0
  74. package/dist/tools/ExitPlanModeTool/index.d.ts.map +1 -0
  75. package/dist/tools/ExitPlanModeTool/index.js +21 -0
  76. package/dist/tools/ExitPlanModeTool/index.js.map +1 -0
  77. package/dist/tools/NotebookEditTool/index.d.ts +18 -0
  78. package/dist/tools/NotebookEditTool/index.d.ts.map +1 -0
  79. package/dist/tools/NotebookEditTool/index.js +61 -0
  80. package/dist/tools/NotebookEditTool/index.js.map +1 -0
  81. package/dist/tools/SkillTool/index.d.ts +15 -0
  82. package/dist/tools/SkillTool/index.d.ts.map +1 -0
  83. package/dist/tools/SkillTool/index.js +49 -0
  84. package/dist/tools/SkillTool/index.js.map +1 -0
  85. package/dist/tools/TaskCreateTool/index.d.ts +15 -0
  86. package/dist/tools/TaskCreateTool/index.d.ts.map +1 -0
  87. package/dist/tools/TaskCreateTool/index.js +54 -0
  88. package/dist/tools/TaskCreateTool/index.js.map +1 -0
  89. package/dist/tools/TaskListTool/index.d.ts +6 -0
  90. package/dist/tools/TaskListTool/index.d.ts.map +1 -0
  91. package/dist/tools/TaskListTool/index.js +40 -0
  92. package/dist/tools/TaskListTool/index.js.map +1 -0
  93. package/dist/tools/TaskUpdateTool/index.d.ts +18 -0
  94. package/dist/tools/TaskUpdateTool/index.d.ts.map +1 -0
  95. package/dist/tools/TaskUpdateTool/index.js +50 -0
  96. package/dist/tools/TaskUpdateTool/index.js.map +1 -0
  97. package/dist/tools/WebSearchTool/index.d.ts +15 -0
  98. package/dist/tools/WebSearchTool/index.d.ts.map +1 -0
  99. package/dist/tools/WebSearchTool/index.js +76 -0
  100. package/dist/tools/WebSearchTool/index.js.map +1 -0
  101. package/dist/tools.d.ts.map +1 -1
  102. package/dist/tools.js +27 -0
  103. package/dist/tools.js.map +1 -1
  104. package/dist/types/message.d.ts +1 -1
  105. package/dist/types/message.js +1 -1
  106. package/dist/types/permissions.d.ts +2 -2
  107. package/dist/types/permissions.js +2 -2
  108. package/dist/utils/retry.d.ts +10 -0
  109. package/dist/utils/retry.d.ts.map +1 -0
  110. package/dist/utils/retry.js +23 -0
  111. package/dist/utils/retry.js.map +1 -0
  112. package/dist/utils/theme.d.ts +27 -0
  113. package/dist/utils/theme.d.ts.map +1 -0
  114. package/dist/utils/theme.js +45 -0
  115. package/dist/utils/theme.js.map +1 -0
  116. package/dist/utils/tokens.d.ts +18 -0
  117. package/dist/utils/tokens.d.ts.map +1 -0
  118. package/dist/utils/tokens.js +57 -0
  119. package/dist/utils/tokens.js.map +1 -0
  120. package/package.json +61 -57
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ const inputSchema = z.object({
3
+ question: z.string(),
4
+ options: z.array(z.string()).optional(),
5
+ });
6
+ export const AskUserTool = {
7
+ name: "AskUser",
8
+ description: "Ask the user a question. The REPL will display it as a prompt.",
9
+ inputSchema,
10
+ riskLevel: "low",
11
+ isReadOnly() {
12
+ return true;
13
+ },
14
+ isConcurrencySafe() {
15
+ return false;
16
+ },
17
+ async call(input, _context) {
18
+ let output = `[Question] ${input.question}`;
19
+ if (input.options && input.options.length > 0) {
20
+ output += "\nOptions:\n" + input.options.map((o, i) => ` ${i + 1}. ${o}`).join("\n");
21
+ }
22
+ return { output, isError: false };
23
+ },
24
+ prompt() {
25
+ return `Ask the user a question. This is a signal to the UI to prompt the user. Parameters:
26
+ - question (string, required): The question to ask.
27
+ - options (string[], optional): List of options to present.`;
28
+ },
29
+ };
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/AskUserTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACxC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,WAAW,GAA6B;IACnD,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,gEAAgE;IAC7E,WAAW;IACX,SAAS,EAAE,KAAK;IAEhB,UAAU;QACR,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iBAAiB;QACf,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ;QACxB,IAAI,MAAM,GAAG,cAAc,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC5C,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxF,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACpC,CAAC;IAED,MAAM;QACJ,OAAO;;4DAEiD,CAAC;IAC3D,CAAC;CACF,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { z } from "zod";
2
+ import type { Tool } from "../../Tool.js";
3
+ declare const inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
4
+ export declare const EnterPlanModeTool: Tool<typeof inputSchema>;
5
+ export {};
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/EnterPlanModeTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,IAAI,EAA2B,MAAM,eAAe,CAAC;AAEnE,QAAA,MAAM,WAAW,gDAAe,CAAC;AAEjC,eAAO,MAAM,iBAAiB,EAAE,IAAI,CAAC,OAAO,WAAW,CAoCtD,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { z } from "zod";
2
+ import * as fs from "fs/promises";
3
+ import * as path from "path";
4
+ const inputSchema = z.object({});
5
+ export const EnterPlanModeTool = {
6
+ name: "EnterPlanMode",
7
+ description: "Enter plan mode, creating .oh/plan.md if it does not exist.",
8
+ inputSchema,
9
+ riskLevel: "low",
10
+ isReadOnly() {
11
+ return false;
12
+ },
13
+ isConcurrencySafe() {
14
+ return false;
15
+ },
16
+ async call(_input, context) {
17
+ const dir = path.join(context.workingDir, ".oh");
18
+ const filePath = path.join(dir, "plan.md");
19
+ try {
20
+ await fs.mkdir(dir, { recursive: true });
21
+ try {
22
+ await fs.access(filePath);
23
+ }
24
+ catch {
25
+ await fs.writeFile(filePath, "# Plan\n\n", "utf-8");
26
+ }
27
+ return { output: "Plan mode entered.", isError: false };
28
+ }
29
+ catch (err) {
30
+ return { output: `Error entering plan mode: ${err.message}`, isError: true };
31
+ }
32
+ },
33
+ prompt() {
34
+ return `Enter plan mode. Creates .oh/plan.md if it does not already exist. No parameters required.`;
35
+ },
36
+ };
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/EnterPlanModeTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAEjC,MAAM,CAAC,MAAM,iBAAiB,GAA6B;IACzD,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,6DAA6D;IAC1E,WAAW;IACX,SAAS,EAAE,KAAK;IAEhB,UAAU;QACR,OAAO,KAAK,CAAC;IACf,CAAC;IAED,iBAAiB;QACf,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAE3C,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAEzC,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC5B,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;YACtD,CAAC;YAED,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC1D,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,EAAE,MAAM,EAAE,6BAA6B,GAAG,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC/E,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO,4FAA4F,CAAC;IACtG,CAAC;CACF,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { z } from "zod";
2
+ import type { Tool } from "../../Tool.js";
3
+ declare const inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
4
+ export declare const ExitPlanModeTool: Tool<typeof inputSchema>;
5
+ export {};
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/ExitPlanModeTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,IAAI,EAA2B,MAAM,eAAe,CAAC;AAEnE,QAAA,MAAM,WAAW,gDAAe,CAAC;AAEjC,eAAO,MAAM,gBAAgB,EAAE,IAAI,CAAC,OAAO,WAAW,CAqBrD,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { z } from "zod";
2
+ const inputSchema = z.object({});
3
+ export const ExitPlanModeTool = {
4
+ name: "ExitPlanMode",
5
+ description: "Exit plan mode.",
6
+ inputSchema,
7
+ riskLevel: "low",
8
+ isReadOnly() {
9
+ return false;
10
+ },
11
+ isConcurrencySafe() {
12
+ return false;
13
+ },
14
+ async call(_input, _context) {
15
+ return { output: "Plan mode exited.", isError: false };
16
+ },
17
+ prompt() {
18
+ return `Exit plan mode. No parameters required.`;
19
+ },
20
+ };
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/ExitPlanModeTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAEjC,MAAM,CAAC,MAAM,gBAAgB,GAA6B;IACxD,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE,iBAAiB;IAC9B,WAAW;IACX,SAAS,EAAE,KAAK;IAEhB,UAAU;QACR,OAAO,KAAK,CAAC;IACf,CAAC;IAED,iBAAiB;QACf,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ;QACzB,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACzD,CAAC;IAED,MAAM;QACJ,OAAO,yCAAyC,CAAC;IACnD,CAAC;CACF,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+ import type { Tool } from "../../Tool.js";
3
+ declare const inputSchema: z.ZodObject<{
4
+ notebook_path: z.ZodString;
5
+ cell_index: z.ZodNumber;
6
+ new_source: z.ZodString;
7
+ }, "strip", z.ZodTypeAny, {
8
+ notebook_path: string;
9
+ cell_index: number;
10
+ new_source: string;
11
+ }, {
12
+ notebook_path: string;
13
+ cell_index: number;
14
+ new_source: string;
15
+ }>;
16
+ export declare const NotebookEditTool: Tool<typeof inputSchema>;
17
+ export {};
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/NotebookEditTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,IAAI,EAA2B,MAAM,eAAe,CAAC;AAEnE,QAAA,MAAM,WAAW;;;;;;;;;;;;EAIf,CAAC;AAEH,eAAO,MAAM,gBAAgB,EAAE,IAAI,CAAC,OAAO,WAAW,CA8DrD,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { z } from "zod";
2
+ import * as fs from "fs/promises";
3
+ import * as path from "path";
4
+ const inputSchema = z.object({
5
+ notebook_path: z.string(),
6
+ cell_index: z.number(),
7
+ new_source: z.string(),
8
+ });
9
+ export const NotebookEditTool = {
10
+ name: "NotebookEdit",
11
+ description: "Edit a cell in a Jupyter notebook (.ipynb) file.",
12
+ inputSchema,
13
+ riskLevel: "medium",
14
+ isReadOnly() {
15
+ return false;
16
+ },
17
+ isConcurrencySafe() {
18
+ return false;
19
+ },
20
+ async call(input, context) {
21
+ const filePath = path.resolve(context.workingDir, input.notebook_path);
22
+ // Path containment — must stay within working directory
23
+ if (!filePath.startsWith(path.resolve(context.workingDir))) {
24
+ return { output: "Error: Path must be within the working directory.", isError: true };
25
+ }
26
+ try {
27
+ const content = await fs.readFile(filePath, "utf-8");
28
+ const notebook = JSON.parse(content);
29
+ if (!notebook.cells || !Array.isArray(notebook.cells)) {
30
+ return { output: "Error: Invalid notebook format — no cells array.", isError: true };
31
+ }
32
+ if (input.cell_index < 0 || input.cell_index >= notebook.cells.length) {
33
+ return {
34
+ output: `Error: Cell index ${input.cell_index} out of range (0-${notebook.cells.length - 1}).`,
35
+ isError: true,
36
+ };
37
+ }
38
+ // Notebook cell source is an array of lines
39
+ const lines = input.new_source.split("\n").map((line, i, arr) => i < arr.length - 1 ? line + "\n" : line);
40
+ notebook.cells[input.cell_index].source = lines;
41
+ await fs.writeFile(filePath, JSON.stringify(notebook, null, 1), "utf-8");
42
+ return {
43
+ output: `Cell ${input.cell_index} updated in ${filePath}.`,
44
+ isError: false,
45
+ };
46
+ }
47
+ catch (err) {
48
+ if (err.code === "ENOENT") {
49
+ return { output: `Error: Notebook not found: ${filePath}`, isError: true };
50
+ }
51
+ return { output: `Error editing notebook: ${err.message}`, isError: true };
52
+ }
53
+ },
54
+ prompt() {
55
+ return `Edit a cell in a Jupyter notebook (.ipynb). Parameters:
56
+ - notebook_path (string, required): Path to the .ipynb file.
57
+ - cell_index (number, required): Zero-based index of the cell to edit.
58
+ - new_source (string, required): The new source code for the cell.`;
59
+ },
60
+ };
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/NotebookEditTool/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ import type { Tool } from "../../Tool.js";
3
+ declare const inputSchema: z.ZodObject<{
4
+ skill: z.ZodString;
5
+ args: z.ZodOptional<z.ZodString>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ skill: string;
8
+ args?: string | undefined;
9
+ }, {
10
+ skill: string;
11
+ args?: string | undefined;
12
+ }>;
13
+ export declare const SkillTool: Tool<typeof inputSchema>;
14
+ export {};
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/SkillTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,IAAI,EAA2B,MAAM,eAAe,CAAC;AAEnE,QAAA,MAAM,WAAW;;;;;;;;;EAGf,CAAC;AAEH,eAAO,MAAM,SAAS,EAAE,IAAI,CAAC,OAAO,WAAW,CA4C9C,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { z } from "zod";
2
+ import * as fs from "fs/promises";
3
+ import * as path from "path";
4
+ const inputSchema = z.object({
5
+ skill: z.string(),
6
+ args: z.string().optional(),
7
+ });
8
+ export const SkillTool = {
9
+ name: "Skill",
10
+ description: "Execute a skill by reading its definition from .oh/skills/.",
11
+ inputSchema,
12
+ riskLevel: "low",
13
+ isReadOnly() {
14
+ return true;
15
+ },
16
+ isConcurrencySafe() {
17
+ return false;
18
+ },
19
+ async call(input, context) {
20
+ // Path traversal protection
21
+ if (input.skill.includes("..") || input.skill.includes("/") || input.skill.includes("\\")) {
22
+ return { output: "Error: Invalid skill name.", isError: true };
23
+ }
24
+ const baseDir = path.join(context.workingDir, ".oh", "skills");
25
+ const filePath = path.join(baseDir, `${input.skill}.md`);
26
+ if (!filePath.startsWith(baseDir)) {
27
+ return { output: "Error: Invalid skill path.", isError: true };
28
+ }
29
+ try {
30
+ const content = await fs.readFile(filePath, "utf-8");
31
+ return { output: content, isError: false };
32
+ }
33
+ catch (err) {
34
+ if (err.code === "ENOENT") {
35
+ return {
36
+ output: `Error: Skill "${input.skill}" not found at ${filePath}`,
37
+ isError: true,
38
+ };
39
+ }
40
+ return { output: `Error reading skill: ${err.message}`, isError: true };
41
+ }
42
+ },
43
+ prompt() {
44
+ return `Execute a skill by loading its definition from .oh/skills/{skill}.md. Parameters:
45
+ - skill (string, required): The skill name (maps to a .md file).
46
+ - args (string, optional): Arguments to pass to the skill.`;
47
+ },
48
+ };
49
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/SkillTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC5B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,SAAS,GAA6B;IACjD,IAAI,EAAE,OAAO;IACb,WAAW,EAAE,6DAA6D;IAC1E,WAAW;IACX,SAAS,EAAE,KAAK;IAEhB,UAAU;QACR,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iBAAiB;QACf,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO;QACvB,4BAA4B;QAC5B,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1F,OAAO,EAAE,MAAM,EAAE,4BAA4B,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACjE,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,KAAK,KAAK,CAAC,CAAC;QACzD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAClC,OAAO,EAAE,MAAM,EAAE,4BAA4B,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACjE,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACrD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC7C,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC1B,OAAO;oBACL,MAAM,EAAE,iBAAiB,KAAK,CAAC,KAAK,kBAAkB,QAAQ,EAAE;oBAChE,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,wBAAwB,GAAG,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO;;2DAEgD,CAAC;IAC1D,CAAC;CACF,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ import type { Tool } from "../../Tool.js";
3
+ declare const inputSchema: z.ZodObject<{
4
+ subject: z.ZodString;
5
+ description: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ description: string;
8
+ subject: string;
9
+ }, {
10
+ description: string;
11
+ subject: string;
12
+ }>;
13
+ export declare const TaskCreateTool: Tool<typeof inputSchema>;
14
+ export {};
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/TaskCreateTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,IAAI,EAA2B,MAAM,eAAe,CAAC;AAEnE,QAAA,MAAM,WAAW;;;;;;;;;EAGf,CAAC;AASH,eAAO,MAAM,cAAc,EAAE,IAAI,CAAC,OAAO,WAAW,CAoDnD,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { z } from "zod";
2
+ import * as fs from "fs/promises";
3
+ import * as path from "path";
4
+ const inputSchema = z.object({
5
+ subject: z.string(),
6
+ description: z.string(),
7
+ });
8
+ export const TaskCreateTool = {
9
+ name: "TaskCreate",
10
+ description: "Create a new task and append it to .oh/tasks.json.",
11
+ inputSchema,
12
+ riskLevel: "low",
13
+ isReadOnly() {
14
+ return false;
15
+ },
16
+ isConcurrencySafe() {
17
+ return false; // Mutates shared tasks.json
18
+ },
19
+ async call(input, context) {
20
+ const dir = path.join(context.workingDir, ".oh");
21
+ const filePath = path.join(dir, "tasks.json");
22
+ try {
23
+ await fs.mkdir(dir, { recursive: true });
24
+ let tasks = [];
25
+ try {
26
+ const content = await fs.readFile(filePath, "utf-8");
27
+ tasks = JSON.parse(content);
28
+ }
29
+ catch {
30
+ // File doesn't exist yet
31
+ }
32
+ const maxId = tasks.reduce((max, t) => Math.max(max, t.id), 0);
33
+ const newTask = {
34
+ id: maxId + 1,
35
+ subject: input.subject,
36
+ description: input.description,
37
+ status: "pending",
38
+ };
39
+ tasks.push(newTask);
40
+ await fs.writeFile(filePath, JSON.stringify(tasks, null, 2), "utf-8");
41
+ return { output: `Task #${newTask.id} created: ${newTask.subject}`, isError: false };
42
+ }
43
+ catch (err) {
44
+ return { output: `Error creating task: ${err.message}`, isError: true };
45
+ }
46
+ },
47
+ prompt() {
48
+ return `Create a new task in .oh/tasks.json. Parameters:
49
+ - subject (string, required): Short title for the task.
50
+ - description (string, required): Detailed description of the task.
51
+ Each task gets an auto-incremented ID and starts with status "pending".`;
52
+ },
53
+ };
54
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/TaskCreateTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;CACxB,CAAC,CAAC;AASH,MAAM,CAAC,MAAM,cAAc,GAA6B;IACtD,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,oDAAoD;IACjE,WAAW;IACX,SAAS,EAAE,KAAK;IAEhB,UAAU;QACR,OAAO,KAAK,CAAC;IACf,CAAC;IAED,iBAAiB;QACf,OAAO,KAAK,CAAC,CAAC,4BAA4B;IAC5C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QAE9C,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAEzC,IAAI,KAAK,GAAW,EAAE,CAAC;YACvB,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACrD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC9B,CAAC;YAAC,MAAM,CAAC;gBACP,yBAAyB;YAC3B,CAAC;YAED,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/D,MAAM,OAAO,GAAS;gBACpB,EAAE,EAAE,KAAK,GAAG,CAAC;gBACb,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,MAAM,EAAE,SAAS;aAClB,CAAC;YAEF,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACpB,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEtE,OAAO,EAAE,MAAM,EAAE,SAAS,OAAO,CAAC,EAAE,aAAa,OAAO,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACvF,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,EAAE,MAAM,EAAE,wBAAwB,GAAG,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO;;;wEAG6D,CAAC;IACvE,CAAC;CACF,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { z } from "zod";
2
+ import type { Tool } from "../../Tool.js";
3
+ declare const inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
4
+ export declare const TaskListTool: Tool<typeof inputSchema>;
5
+ export {};
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/TaskListTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,IAAI,EAA2B,MAAM,eAAe,CAAC;AAEnE,QAAA,MAAM,WAAW,gDAAe,CAAC;AASjC,eAAO,MAAM,YAAY,EAAE,IAAI,CAAC,OAAO,WAAW,CAyCjD,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { z } from "zod";
2
+ import * as fs from "fs/promises";
3
+ import * as path from "path";
4
+ const inputSchema = z.object({});
5
+ export const TaskListTool = {
6
+ name: "TaskList",
7
+ description: "List all tasks from .oh/tasks.json.",
8
+ inputSchema,
9
+ riskLevel: "low",
10
+ isReadOnly() {
11
+ return true;
12
+ },
13
+ isConcurrencySafe() {
14
+ return true;
15
+ },
16
+ async call(_input, context) {
17
+ const filePath = path.join(context.workingDir, ".oh", "tasks.json");
18
+ try {
19
+ const content = await fs.readFile(filePath, "utf-8");
20
+ const tasks = JSON.parse(content);
21
+ if (tasks.length === 0) {
22
+ return { output: "No tasks found.", isError: false };
23
+ }
24
+ const output = tasks
25
+ .map((t) => `#${t.id} [${t.status}] ${t.subject}\n ${t.description}`)
26
+ .join("\n\n");
27
+ return { output, isError: false };
28
+ }
29
+ catch (err) {
30
+ if (err.code === "ENOENT") {
31
+ return { output: "No tasks found. Create a task first.", isError: false };
32
+ }
33
+ return { output: `Error listing tasks: ${err.message}`, isError: true };
34
+ }
35
+ },
36
+ prompt() {
37
+ return `List all tasks from .oh/tasks.json. No parameters required.`;
38
+ },
39
+ };
40
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/TaskListTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AASjC,MAAM,CAAC,MAAM,YAAY,GAA6B;IACpD,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,qCAAqC;IAClD,WAAW;IACX,SAAS,EAAE,KAAK;IAEhB,UAAU;QACR,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO;QACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;QAEpE,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACrD,MAAM,KAAK,GAAW,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAE1C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACvD,CAAC;YAED,MAAM,MAAM,GAAG,KAAK;iBACjB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;iBACtE,IAAI,CAAC,MAAM,CAAC,CAAC;YAEhB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACpC,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC1B,OAAO,EAAE,MAAM,EAAE,sCAAsC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAC5E,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,wBAAwB,GAAG,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO,6DAA6D,CAAC;IACvE,CAAC;CACF,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+ import type { Tool } from "../../Tool.js";
3
+ declare const inputSchema: z.ZodObject<{
4
+ taskId: z.ZodNumber;
5
+ status: z.ZodOptional<z.ZodString>;
6
+ description: z.ZodOptional<z.ZodString>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ taskId: number;
9
+ status?: string | undefined;
10
+ description?: string | undefined;
11
+ }, {
12
+ taskId: number;
13
+ status?: string | undefined;
14
+ description?: string | undefined;
15
+ }>;
16
+ export declare const TaskUpdateTool: Tool<typeof inputSchema>;
17
+ export {};
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/TaskUpdateTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,IAAI,EAA2B,MAAM,eAAe,CAAC;AAEnE,QAAA,MAAM,WAAW;;;;;;;;;;;;EAIf,CAAC;AASH,eAAO,MAAM,cAAc,EAAE,IAAI,CAAC,OAAO,WAAW,CA8CnD,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { z } from "zod";
2
+ import * as fs from "fs/promises";
3
+ import * as path from "path";
4
+ const inputSchema = z.object({
5
+ taskId: z.number(),
6
+ status: z.string().optional(),
7
+ description: z.string().optional(),
8
+ });
9
+ export const TaskUpdateTool = {
10
+ name: "TaskUpdate",
11
+ description: "Update an existing task in .oh/tasks.json.",
12
+ inputSchema,
13
+ riskLevel: "low",
14
+ isReadOnly() {
15
+ return false;
16
+ },
17
+ isConcurrencySafe() {
18
+ return false; // Mutates shared tasks.json
19
+ },
20
+ async call(input, context) {
21
+ const filePath = path.join(context.workingDir, ".oh", "tasks.json");
22
+ try {
23
+ const content = await fs.readFile(filePath, "utf-8");
24
+ const tasks = JSON.parse(content);
25
+ const task = tasks.find((t) => t.id === input.taskId);
26
+ if (!task) {
27
+ return { output: `Error: Task #${input.taskId} not found.`, isError: true };
28
+ }
29
+ if (input.status !== undefined)
30
+ task.status = input.status;
31
+ if (input.description !== undefined)
32
+ task.description = input.description;
33
+ await fs.writeFile(filePath, JSON.stringify(tasks, null, 2), "utf-8");
34
+ return { output: `Task #${task.id} updated. Status: ${task.status}`, isError: false };
35
+ }
36
+ catch (err) {
37
+ if (err.code === "ENOENT") {
38
+ return { output: "Error: No tasks file found. Create a task first.", isError: true };
39
+ }
40
+ return { output: `Error updating task: ${err.message}`, isError: true };
41
+ }
42
+ },
43
+ prompt() {
44
+ return `Update an existing task in .oh/tasks.json. Parameters:
45
+ - taskId (number, required): The ID of the task to update.
46
+ - status (string, optional): New status for the task.
47
+ - description (string, optional): New description for the task.`;
48
+ },
49
+ };
50
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/TaskUpdateTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACnC,CAAC,CAAC;AASH,MAAM,CAAC,MAAM,cAAc,GAA6B;IACtD,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,4CAA4C;IACzD,WAAW;IACX,SAAS,EAAE,KAAK;IAEhB,UAAU;QACR,OAAO,KAAK,CAAC;IACf,CAAC;IAED,iBAAiB;QACf,OAAO,KAAK,CAAC,CAAC,4BAA4B;IAC5C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;QAEpE,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACrD,MAAM,KAAK,GAAW,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAE1C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC;YACtD,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,EAAE,MAAM,EAAE,gBAAgB,KAAK,CAAC,MAAM,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC9E,CAAC;YAED,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC3D,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;gBAAE,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;YAE1E,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEtE,OAAO,EAAE,MAAM,EAAE,SAAS,IAAI,CAAC,EAAE,qBAAqB,IAAI,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACxF,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC1B,OAAO,EAAE,MAAM,EAAE,kDAAkD,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YACvF,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,wBAAwB,GAAG,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO;;;gEAGqD,CAAC;IAC/D,CAAC;CACF,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ import type { Tool } from "../../Tool.js";
3
+ declare const inputSchema: z.ZodObject<{
4
+ query: z.ZodString;
5
+ limit: z.ZodOptional<z.ZodNumber>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ query: string;
8
+ limit?: number | undefined;
9
+ }, {
10
+ query: string;
11
+ limit?: number | undefined;
12
+ }>;
13
+ export declare const WebSearchTool: Tool<typeof inputSchema>;
14
+ export {};
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/WebSearchTool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,IAAI,EAA2B,MAAM,eAAe,CAAC;AAEnE,QAAA,MAAM,WAAW;;;;;;;;;EAGf,CAAC;AAIH,eAAO,MAAM,aAAa,EAAE,IAAI,CAAC,OAAO,WAAW,CAkFlD,CAAC"}
@@ -0,0 +1,76 @@
1
+ import { z } from "zod";
2
+ const inputSchema = z.object({
3
+ query: z.string(),
4
+ limit: z.number().optional(),
5
+ });
6
+ const DEFAULT_LIMIT = 5;
7
+ export const WebSearchTool = {
8
+ name: "WebSearch",
9
+ description: "Search the web via DuckDuckGo and return top results.",
10
+ inputSchema,
11
+ riskLevel: "medium",
12
+ isReadOnly() {
13
+ return true;
14
+ },
15
+ isConcurrencySafe() {
16
+ return true;
17
+ },
18
+ async call(input, _context) {
19
+ const limit = input.limit ?? DEFAULT_LIMIT;
20
+ const url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(input.query)}`;
21
+ try {
22
+ const response = await fetch(url, {
23
+ headers: {
24
+ "User-Agent": "Mozilla/5.0 (compatible; OpenHarness/1.0)",
25
+ },
26
+ });
27
+ if (!response.ok) {
28
+ return { output: `Error: HTTP ${response.status}`, isError: true };
29
+ }
30
+ const html = await response.text();
31
+ // Parse results from DuckDuckGo HTML response
32
+ const results = [];
33
+ const resultRegex = /<a[^>]+class="result__a"[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/g;
34
+ const snippetRegex = /<a[^>]+class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g;
35
+ let match;
36
+ const titles = [];
37
+ while ((match = resultRegex.exec(html)) !== null) {
38
+ const rawUrl = match[1];
39
+ const title = match[2].replace(/<[^>]*>/g, "").trim();
40
+ // DuckDuckGo wraps URLs in a redirect; extract the actual URL
41
+ const actualUrlMatch = rawUrl.match(/uddg=([^&]+)/);
42
+ const actualUrl = actualUrlMatch
43
+ ? decodeURIComponent(actualUrlMatch[1])
44
+ : rawUrl;
45
+ titles.push({ url: actualUrl, title });
46
+ }
47
+ const snippets = [];
48
+ while ((match = snippetRegex.exec(html)) !== null) {
49
+ snippets.push(match[1].replace(/<[^>]*>/g, "").trim());
50
+ }
51
+ for (let i = 0; i < Math.min(titles.length, limit); i++) {
52
+ results.push({
53
+ title: titles[i].title,
54
+ url: titles[i].url,
55
+ snippet: snippets[i] ?? "",
56
+ });
57
+ }
58
+ if (results.length === 0) {
59
+ return { output: "No results found.", isError: false };
60
+ }
61
+ const output = results
62
+ .map((r, i) => `${i + 1}. ${r.title}\n ${r.url}\n ${r.snippet}`)
63
+ .join("\n\n");
64
+ return { output, isError: false };
65
+ }
66
+ catch (err) {
67
+ return { output: `Error performing search: ${err.message}`, isError: true };
68
+ }
69
+ },
70
+ prompt() {
71
+ return `Search the web using DuckDuckGo and return top results. Parameters:
72
+ - query (string, required): The search query.
73
+ - limit (number, optional): Maximum number of results to return (default 5).`;
74
+ },
75
+ };
76
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/WebSearchTool/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AASvC;;GAEG;AACH,wBAAgB,WAAW,IAAI,KAAK,CAUnC"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAuBvC;;GAEG;AACH,wBAAgB,WAAW,IAAI,KAAK,CAyBnC"}