@zhijiewang/openharness 0.1.1 → 0.2.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 (117) 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/CODE_OF_CONDUCT.md +43 -0
  5. package/README.md +160 -156
  6. package/SECURITY.md +21 -0
  7. package/dist/commands/index.d.ts +37 -0
  8. package/dist/commands/index.d.ts.map +1 -0
  9. package/dist/commands/index.js +189 -0
  10. package/dist/commands/index.js.map +1 -0
  11. package/dist/components/App.d.ts.map +1 -1
  12. package/dist/components/App.js +3 -2
  13. package/dist/components/App.js.map +1 -1
  14. package/dist/components/ErrorBoundary.d.ts +17 -0
  15. package/dist/components/ErrorBoundary.d.ts.map +1 -0
  16. package/dist/components/ErrorBoundary.js +19 -0
  17. package/dist/components/ErrorBoundary.js.map +1 -0
  18. package/dist/components/Markdown.d.ts.map +1 -1
  19. package/dist/components/Markdown.js +70 -18
  20. package/dist/components/Markdown.js.map +1 -1
  21. package/dist/components/Messages.d.ts.map +1 -1
  22. package/dist/components/Messages.js +10 -4
  23. package/dist/components/Messages.js.map +1 -1
  24. package/dist/components/PermissionPrompt.d.ts.map +1 -1
  25. package/dist/components/PermissionPrompt.js +25 -7
  26. package/dist/components/PermissionPrompt.js.map +1 -1
  27. package/dist/components/REPL.d.ts.map +1 -1
  28. package/dist/components/REPL.js +60 -6
  29. package/dist/components/REPL.js.map +1 -1
  30. package/dist/components/Spinner.d.ts +3 -2
  31. package/dist/components/Spinner.d.ts.map +1 -1
  32. package/dist/components/Spinner.js +22 -4
  33. package/dist/components/Spinner.js.map +1 -1
  34. package/dist/components/TextInput.d.ts.map +1 -1
  35. package/dist/components/TextInput.js +4 -1
  36. package/dist/components/TextInput.js.map +1 -1
  37. package/dist/git/index.d.ts +47 -0
  38. package/dist/git/index.d.ts.map +1 -0
  39. package/dist/git/index.js +151 -0
  40. package/dist/git/index.js.map +1 -0
  41. package/dist/harness/session.d.ts.map +1 -1
  42. package/dist/harness/session.js +2 -1
  43. package/dist/harness/session.js.map +1 -1
  44. package/dist/main.js +88 -2
  45. package/dist/main.js.map +1 -1
  46. package/dist/providers/openai.js +11 -1
  47. package/dist/providers/openai.js.map +1 -1
  48. package/dist/providers/openrouter.js +11 -1
  49. package/dist/providers/openrouter.js.map +1 -1
  50. package/dist/query.d.ts +15 -11
  51. package/dist/query.d.ts.map +1 -1
  52. package/dist/query.js +196 -80
  53. package/dist/query.js.map +1 -1
  54. package/dist/services/StreamingToolExecutor.d.ts +25 -0
  55. package/dist/services/StreamingToolExecutor.d.ts.map +1 -0
  56. package/dist/services/StreamingToolExecutor.js +107 -0
  57. package/dist/services/StreamingToolExecutor.js.map +1 -0
  58. package/dist/tools/AgentTool/index.d.ts +15 -0
  59. package/dist/tools/AgentTool/index.d.ts.map +1 -0
  60. package/dist/tools/AgentTool/index.js +30 -0
  61. package/dist/tools/AgentTool/index.js.map +1 -0
  62. package/dist/tools/AskUserTool/index.d.ts +15 -0
  63. package/dist/tools/AskUserTool/index.d.ts.map +1 -0
  64. package/dist/tools/AskUserTool/index.js +30 -0
  65. package/dist/tools/AskUserTool/index.js.map +1 -0
  66. package/dist/tools/EnterPlanModeTool/index.d.ts +6 -0
  67. package/dist/tools/EnterPlanModeTool/index.d.ts.map +1 -0
  68. package/dist/tools/EnterPlanModeTool/index.js +37 -0
  69. package/dist/tools/EnterPlanModeTool/index.js.map +1 -0
  70. package/dist/tools/ExitPlanModeTool/index.d.ts +6 -0
  71. package/dist/tools/ExitPlanModeTool/index.d.ts.map +1 -0
  72. package/dist/tools/ExitPlanModeTool/index.js +21 -0
  73. package/dist/tools/ExitPlanModeTool/index.js.map +1 -0
  74. package/dist/tools/NotebookEditTool/index.d.ts +18 -0
  75. package/dist/tools/NotebookEditTool/index.d.ts.map +1 -0
  76. package/dist/tools/NotebookEditTool/index.js +61 -0
  77. package/dist/tools/NotebookEditTool/index.js.map +1 -0
  78. package/dist/tools/SkillTool/index.d.ts +15 -0
  79. package/dist/tools/SkillTool/index.d.ts.map +1 -0
  80. package/dist/tools/SkillTool/index.js +49 -0
  81. package/dist/tools/SkillTool/index.js.map +1 -0
  82. package/dist/tools/TaskCreateTool/index.d.ts +15 -0
  83. package/dist/tools/TaskCreateTool/index.d.ts.map +1 -0
  84. package/dist/tools/TaskCreateTool/index.js +54 -0
  85. package/dist/tools/TaskCreateTool/index.js.map +1 -0
  86. package/dist/tools/TaskListTool/index.d.ts +6 -0
  87. package/dist/tools/TaskListTool/index.d.ts.map +1 -0
  88. package/dist/tools/TaskListTool/index.js +40 -0
  89. package/dist/tools/TaskListTool/index.js.map +1 -0
  90. package/dist/tools/TaskUpdateTool/index.d.ts +18 -0
  91. package/dist/tools/TaskUpdateTool/index.d.ts.map +1 -0
  92. package/dist/tools/TaskUpdateTool/index.js +50 -0
  93. package/dist/tools/TaskUpdateTool/index.js.map +1 -0
  94. package/dist/tools/WebSearchTool/index.d.ts +15 -0
  95. package/dist/tools/WebSearchTool/index.d.ts.map +1 -0
  96. package/dist/tools/WebSearchTool/index.js +76 -0
  97. package/dist/tools/WebSearchTool/index.js.map +1 -0
  98. package/dist/tools/web-fetch.test.d.ts +2 -0
  99. package/dist/tools/web-fetch.test.d.ts.map +1 -0
  100. package/dist/tools/web-fetch.test.js +27 -0
  101. package/dist/tools/web-fetch.test.js.map +1 -0
  102. package/dist/tools.d.ts.map +1 -1
  103. package/dist/tools.js +27 -0
  104. package/dist/tools.js.map +1 -1
  105. package/dist/utils/retry.d.ts +10 -0
  106. package/dist/utils/retry.d.ts.map +1 -0
  107. package/dist/utils/retry.js +23 -0
  108. package/dist/utils/retry.js.map +1 -0
  109. package/dist/utils/theme.d.ts +27 -0
  110. package/dist/utils/theme.d.ts.map +1 -0
  111. package/dist/utils/theme.js +45 -0
  112. package/dist/utils/theme.js.map +1 -0
  113. package/dist/utils/tokens.d.ts +18 -0
  114. package/dist/utils/tokens.d.ts.map +1 -0
  115. package/dist/utils/tokens.js +57 -0
  116. package/dist/utils/tokens.js.map +1 -0
  117. package/package.json +61 -57
@@ -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":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,CAAC,CAAC;AAExB,MAAM,CAAC,MAAM,aAAa,GAA6B;IACrD,IAAI,EAAE,WAAW;IACjB,WAAW,EAAE,uDAAuD;IACpE,WAAW;IACX,SAAS,EAAE,QAAQ;IAEnB,UAAU;QACR,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ;QACxB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,aAAa,CAAC;QAC3C,MAAM,GAAG,GAAG,uCAAuC,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAErF,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,OAAO,EAAE;oBACP,YAAY,EAAE,2CAA2C;iBAC1D;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,EAAE,MAAM,EAAE,eAAe,QAAQ,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YACrE,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAEnC,8CAA8C;YAC9C,MAAM,OAAO,GAAsD,EAAE,CAAC;YACtE,MAAM,WAAW,GAAG,mEAAmE,CAAC;YACxF,MAAM,YAAY,GAAG,sDAAsD,CAAC;YAE5E,IAAI,KAA6B,CAAC;YAClC,MAAM,MAAM,GAAqC,EAAE,CAAC;YAEpD,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBACjD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACxB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACtD,8DAA8D;gBAC9D,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;gBACpD,MAAM,SAAS,GAAG,cAAc;oBAC9B,CAAC,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;oBACvC,CAAC,CAAC,MAAM,CAAC;gBACX,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;YACzC,CAAC;YAED,MAAM,QAAQ,GAAa,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBAClD,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACzD,CAAC;YAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxD,OAAO,CAAC,IAAI,CAAC;oBACX,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK;oBACtB,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG;oBAClB,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE;iBAC3B,CAAC,CAAC;YACL,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACzD,CAAC;YAED,MAAM,MAAM,GAAG,OAAO;iBACnB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC;iBACnE,IAAI,CAAC,MAAM,CAAC,CAAC;YAEhB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACpC,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,EAAE,MAAM,EAAE,4BAA4B,GAAG,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC9E,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO;;6EAEkE,CAAC;IAC5E,CAAC;CACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=web-fetch.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-fetch.test.d.ts","sourceRoot":"","sources":["../../src/tools/web-fetch.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,27 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { WebFetchTool } from "./WebFetchTool/index.js";
4
+ const ctx = { workingDir: process.cwd() };
5
+ test("blocks localhost", async () => {
6
+ const r = await WebFetchTool.call({ url: "http://localhost:8080/secret" }, ctx);
7
+ assert.equal(r.isError, true);
8
+ assert.ok(r.output.includes("blocked"));
9
+ });
10
+ test("blocks 192.168.x.x", async () => {
11
+ const r = await WebFetchTool.call({ url: "http://192.168.1.1/" }, ctx);
12
+ assert.equal(r.isError, true);
13
+ assert.ok(r.output.includes("blocked"));
14
+ });
15
+ test("blocks .internal hostnames", async () => {
16
+ const r = await WebFetchTool.call({ url: "http://app.internal/api" }, ctx);
17
+ assert.equal(r.isError, true);
18
+ assert.ok(r.output.includes("blocked"));
19
+ });
20
+ test("allows normal https URLs (will fail to connect but not blocked)", async () => {
21
+ // Use a URL that won't actually resolve to avoid network calls,
22
+ // but the SSRF check itself should pass (error will be a fetch error, not "blocked")
23
+ const r = await WebFetchTool.call({ url: "https://example.invalid/page" }, ctx);
24
+ // Should NOT be the SSRF block message
25
+ assert.ok(!r.output.includes("private/internal hosts is blocked"));
26
+ });
27
+ //# sourceMappingURL=web-fetch.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-fetch.test.js","sourceRoot":"","sources":["../../src/tools/web-fetch.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,MAAM,GAAG,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;AAE1C,IAAI,CAAC,kBAAkB,EAAE,KAAK,IAAI,EAAE;IAClC,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,8BAA8B,EAAE,EAAE,GAAG,CAAC,CAAC;IAChF,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAC1C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,oBAAoB,EAAE,KAAK,IAAI,EAAE;IACpC,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,qBAAqB,EAAE,EAAE,GAAG,CAAC,CAAC;IACvE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAC1C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;IAC5C,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,yBAAyB,EAAE,EAAE,GAAG,CAAC,CAAC;IAC3E,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAC1C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;IACjF,gEAAgE;IAChE,qFAAqF;IACrF,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,8BAA8B,EAAE,EAAE,GAAG,CAAC,CAAC;IAChF,uCAAuC;IACvC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,mCAAmC,CAAC,CAAC,CAAC;AACrE,CAAC,CAAC,CAAC"}
@@ -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"}
package/dist/tools.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Tool registry — aggregates all available tools.
3
3
  */
4
+ // Core tools
4
5
  import { BashTool } from "./tools/BashTool/index.js";
5
6
  import { FileReadTool } from "./tools/FileReadTool/index.js";
6
7
  import { FileWriteTool } from "./tools/FileWriteTool/index.js";
@@ -8,11 +9,23 @@ import { FileEditTool } from "./tools/FileEditTool/index.js";
8
9
  import { GlobTool } from "./tools/GlobTool/index.js";
9
10
  import { GrepTool } from "./tools/GrepTool/index.js";
10
11
  import { WebFetchTool } from "./tools/WebFetchTool/index.js";
12
+ // Advanced tools
13
+ import { WebSearchTool } from "./tools/WebSearchTool/index.js";
14
+ import { TaskCreateTool } from "./tools/TaskCreateTool/index.js";
15
+ import { TaskUpdateTool } from "./tools/TaskUpdateTool/index.js";
16
+ import { TaskListTool } from "./tools/TaskListTool/index.js";
17
+ import { AskUserTool } from "./tools/AskUserTool/index.js";
18
+ import { SkillTool } from "./tools/SkillTool/index.js";
19
+ import { AgentTool } from "./tools/AgentTool/index.js";
20
+ import { EnterPlanModeTool } from "./tools/EnterPlanModeTool/index.js";
21
+ import { ExitPlanModeTool } from "./tools/ExitPlanModeTool/index.js";
22
+ import { NotebookEditTool } from "./tools/NotebookEditTool/index.js";
11
23
  /**
12
24
  * Returns all registered tools.
13
25
  */
14
26
  export function getAllTools() {
15
27
  return [
28
+ // Core (always available)
16
29
  BashTool,
17
30
  FileReadTool,
18
31
  FileWriteTool,
@@ -20,6 +33,20 @@ export function getAllTools() {
20
33
  GlobTool,
21
34
  GrepTool,
22
35
  WebFetchTool,
36
+ WebSearchTool,
37
+ // Task management
38
+ TaskCreateTool,
39
+ TaskUpdateTool,
40
+ TaskListTool,
41
+ // Agent interaction
42
+ AskUserTool,
43
+ SkillTool,
44
+ AgentTool,
45
+ // Planning
46
+ EnterPlanModeTool,
47
+ ExitPlanModeTool,
48
+ // Notebooks
49
+ NotebookEditTool,
23
50
  ];
24
51
  }
25
52
  //# sourceMappingURL=tools.js.map
package/dist/tools.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,QAAQ;QACR,YAAY;QACZ,aAAa;QACb,YAAY;QACZ,QAAQ;QACR,QAAQ;QACR,YAAY;KACb,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,aAAa;AACb,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,iBAAiB;AACjB,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAErE;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,0BAA0B;QAC1B,QAAQ;QACR,YAAY;QACZ,aAAa;QACb,YAAY;QACZ,QAAQ;QACR,QAAQ;QACR,YAAY;QACZ,aAAa;QACb,kBAAkB;QAClB,cAAc;QACd,cAAc;QACd,YAAY;QACZ,oBAAoB;QACpB,WAAW;QACX,SAAS;QACT,SAAS;QACT,WAAW;QACX,iBAAiB;QACjB,gBAAgB;QAChB,YAAY;QACZ,gBAAgB;KACjB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Retry with exponential backoff.
3
+ */
4
+ export type RetryOptions = {
5
+ maxRetries?: number;
6
+ backoffMs?: number;
7
+ signal?: AbortSignal;
8
+ };
9
+ export declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
10
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,CAAC,CAAC,CAkBZ"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Retry with exponential backoff.
3
+ */
4
+ export async function withRetry(fn, options) {
5
+ const { maxRetries = 3, backoffMs = 1000, signal } = options ?? {};
6
+ let lastError;
7
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
8
+ if (signal?.aborted)
9
+ throw new Error("Aborted");
10
+ try {
11
+ return await fn();
12
+ }
13
+ catch (err) {
14
+ lastError = err instanceof Error ? err : new Error(String(err));
15
+ if (attempt < maxRetries) {
16
+ const delay = backoffMs * Math.pow(2, attempt);
17
+ await new Promise((r) => setTimeout(r, delay));
18
+ }
19
+ }
20
+ }
21
+ throw lastError;
22
+ }
23
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,EAAoB,EACpB,OAAsB;IAEtB,MAAM,EAAE,UAAU,GAAG,CAAC,EAAE,SAAS,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;IACnE,IAAI,SAA4B,CAAC;IAEjC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,MAAM,EAAE,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;QAChD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,SAAS,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAChE,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;gBACzB,MAAM,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;gBAC/C,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,SAAS,CAAC;AAClB,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Semantic theme system for OpenHarness terminal UI.
3
+ * Inspired by Claude Code's 89-color theme with shimmer variants.
4
+ */
5
+ import React from "react";
6
+ export type Theme = {
7
+ primary: string;
8
+ primaryShimmer: string;
9
+ user: string;
10
+ assistant: string;
11
+ tool: string;
12
+ error: string;
13
+ success: string;
14
+ warning: string;
15
+ border: string;
16
+ dim: string;
17
+ text: string;
18
+ diffAdded: string;
19
+ diffRemoved: string;
20
+ stall: string;
21
+ stallShimmer: string;
22
+ };
23
+ export declare const darkTheme: Theme;
24
+ export declare const lightTheme: Theme;
25
+ export declare const ThemeProvider: React.Provider<Theme>;
26
+ export declare function useTheme(): Theme;
27
+ //# sourceMappingURL=theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/utils/theme.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,MAAM,KAAK,GAAG;IAElB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IAGvB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAGhB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IAGb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IAGpB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAoBvB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAoBxB,CAAC;AAIF,eAAO,MAAM,aAAa,uBAAwB,CAAC;AAEnD,wBAAgB,QAAQ,IAAI,KAAK,CAEhC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Semantic theme system for OpenHarness terminal UI.
3
+ * Inspired by Claude Code's 89-color theme with shimmer variants.
4
+ */
5
+ import React from "react";
6
+ export const darkTheme = {
7
+ primary: "magenta",
8
+ primaryShimmer: "magentaBright",
9
+ user: "cyan",
10
+ assistant: "magenta",
11
+ tool: "yellow",
12
+ error: "red",
13
+ success: "green",
14
+ warning: "yellow",
15
+ border: "gray",
16
+ dim: "gray",
17
+ text: "white",
18
+ diffAdded: "green",
19
+ diffRemoved: "red",
20
+ stall: "yellow",
21
+ stallShimmer: "redBright",
22
+ };
23
+ export const lightTheme = {
24
+ primary: "magentaBright",
25
+ primaryShimmer: "magenta",
26
+ user: "cyanBright",
27
+ assistant: "magentaBright",
28
+ tool: "yellowBright",
29
+ error: "redBright",
30
+ success: "greenBright",
31
+ warning: "yellowBright",
32
+ border: "blackBright",
33
+ dim: "blackBright",
34
+ text: "black",
35
+ diffAdded: "greenBright",
36
+ diffRemoved: "redBright",
37
+ stall: "yellowBright",
38
+ stallShimmer: "red",
39
+ };
40
+ const ThemeContext = React.createContext(darkTheme);
41
+ export const ThemeProvider = ThemeContext.Provider;
42
+ export function useTheme() {
43
+ return React.useContext(ThemeContext);
44
+ }
45
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/utils/theme.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AA6B1B,MAAM,CAAC,MAAM,SAAS,GAAU;IAC9B,OAAO,EAAE,SAAS;IAClB,cAAc,EAAE,eAAe;IAE/B,IAAI,EAAE,MAAM;IACZ,SAAS,EAAE,SAAS;IACpB,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,OAAO;IAChB,OAAO,EAAE,QAAQ;IAEjB,MAAM,EAAE,MAAM;IACd,GAAG,EAAE,MAAM;IACX,IAAI,EAAE,OAAO;IAEb,SAAS,EAAE,OAAO;IAClB,WAAW,EAAE,KAAK;IAElB,KAAK,EAAE,QAAQ;IACf,YAAY,EAAE,WAAW;CAC1B,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAU;IAC/B,OAAO,EAAE,eAAe;IACxB,cAAc,EAAE,SAAS;IAEzB,IAAI,EAAE,YAAY;IAClB,SAAS,EAAE,eAAe;IAC1B,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,WAAW;IAClB,OAAO,EAAE,aAAa;IACtB,OAAO,EAAE,cAAc;IAEvB,MAAM,EAAE,aAAa;IACrB,GAAG,EAAE,aAAa;IAClB,IAAI,EAAE,OAAO;IAEb,SAAS,EAAE,aAAa;IACxB,WAAW,EAAE,WAAW;IAExB,KAAK,EAAE,cAAc;IACrB,YAAY,EAAE,KAAK;CACpB,CAAC;AAEF,MAAM,YAAY,GAAG,KAAK,CAAC,aAAa,CAAQ,SAAS,CAAC,CAAC;AAE3D,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAC,QAAQ,CAAC;AAEnD,MAAM,UAAU,QAAQ;IACtB,OAAO,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Token estimation utilities and context window sizes.
3
+ */
4
+ import type { Message } from "../types/message.js";
5
+ export declare function estimateTokens(text: string): number;
6
+ export declare function estimateMessagesTokens(messages: Message[]): number;
7
+ export declare const CONTEXT_WINDOWS: Record<string, number>;
8
+ export declare function getContextWindow(model: string): number;
9
+ /**
10
+ * Compress messages to fit within a target token budget.
11
+ *
12
+ * Strategy:
13
+ * 1. Always keep first (system) and last 10 messages
14
+ * 2. For middle messages: if role=tool, replace content with "[truncated]"
15
+ * 3. If still over target, drop oldest non-system messages
16
+ */
17
+ export declare function compressMessages(messages: Message[], targetTokens: number): Message[];
18
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/utils/tokens.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAElE;AAED,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAUlD,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,EAAE,CAiCrF"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Token estimation utilities and context window sizes.
3
+ */
4
+ export function estimateTokens(text) {
5
+ return Math.ceil(text.length / 4);
6
+ }
7
+ export function estimateMessagesTokens(messages) {
8
+ return messages.reduce((sum, m) => sum + estimateTokens(m.content) + 10, 0); // +10 per message overhead
9
+ }
10
+ export const CONTEXT_WINDOWS = {
11
+ "llama3": 8192,
12
+ "qwen2.5:7b-instruct": 32768,
13
+ "gpt-4o": 128000,
14
+ "gpt-4o-mini": 128000,
15
+ "o3-mini": 200000,
16
+ "claude-sonnet-4-6": 200000,
17
+ "claude-haiku-4-5": 200000,
18
+ "claude-opus-4-6": 200000,
19
+ "deepseek-chat": 64000,
20
+ };
21
+ export function getContextWindow(model) {
22
+ return CONTEXT_WINDOWS[model] ?? 8192;
23
+ }
24
+ /**
25
+ * Compress messages to fit within a target token budget.
26
+ *
27
+ * Strategy:
28
+ * 1. Always keep first (system) and last 10 messages
29
+ * 2. For middle messages: if role=tool, replace content with "[truncated]"
30
+ * 3. If still over target, drop oldest non-system messages
31
+ */
32
+ export function compressMessages(messages, targetTokens) {
33
+ if (estimateMessagesTokens(messages) <= targetTokens) {
34
+ return messages;
35
+ }
36
+ const first = messages[0];
37
+ const tail = messages.slice(-10);
38
+ const middle = messages.slice(1, -10);
39
+ if (middle.length === 0) {
40
+ return messages;
41
+ }
42
+ // Step 1: truncate tool results in the middle
43
+ const compressed = middle.map((m) => m.role === "tool"
44
+ ? { ...m, content: "[truncated]" }
45
+ : m);
46
+ let result = first ? [first, ...compressed, ...tail] : [...compressed, ...tail];
47
+ if (estimateMessagesTokens(result) <= targetTokens) {
48
+ return result;
49
+ }
50
+ // Step 2: progressively drop oldest non-system middle messages
51
+ const kept = [...compressed];
52
+ while (kept.length > 0 && estimateMessagesTokens(first ? [first, ...kept, ...tail] : [...kept, ...tail]) > targetTokens) {
53
+ kept.shift();
54
+ }
55
+ return first ? [first, ...kept, ...tail] : [...kept, ...tail];
56
+ }
57
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/utils/tokens.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAmB;IACxD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,2BAA2B;AAC1G,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAA2B;IACrD,QAAQ,EAAE,IAAI;IACd,qBAAqB,EAAE,KAAK;IAC5B,QAAQ,EAAE,MAAM;IAChB,aAAa,EAAE,MAAM;IACrB,SAAS,EAAE,MAAM;IACjB,mBAAmB,EAAE,MAAM;IAC3B,kBAAkB,EAAE,MAAM;IAC1B,iBAAiB,EAAE,MAAM;IACzB,eAAe,EAAE,KAAK;CACvB,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,eAAe,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAmB,EAAE,YAAoB;IACxE,IAAI,sBAAsB,CAAC,QAAQ,CAAC,IAAI,YAAY,EAAE,CAAC;QACrD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAEtC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,8CAA8C;IAC9C,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAClC,CAAC,CAAC,IAAI,KAAK,MAAM;QACf,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE;QAClC,CAAC,CAAC,CAAC,CACN,CAAC;IAEF,IAAI,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;IAEhF,IAAI,sBAAsB,CAAC,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;QACnD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,+DAA+D;IAC/D,MAAM,IAAI,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC;IAC7B,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,YAAY,EAAE,CAAC;QACxH,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAED,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;AAChE,CAAC"}