@goondan/openharness-base 0.0.1-alpha4 → 2.0.0-alpha.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 (105) hide show
  1. package/dist/index.d.ts +72 -5
  2. package/dist/index.js +506 -5
  3. package/package.json +11 -33
  4. package/src/__tests__/compaction-summarize.test.ts +234 -0
  5. package/src/__tests__/context-message.test.ts +203 -0
  6. package/src/__tests__/logging.test.ts +200 -0
  7. package/src/__tests__/message-window.test.ts +193 -0
  8. package/src/__tests__/required-tools-guard.test.ts +206 -0
  9. package/src/__tests__/tool-search.test.ts +187 -0
  10. package/src/__tests__/tools.test.ts +332 -0
  11. package/src/extensions/compaction-summarize.ts +58 -0
  12. package/src/extensions/context-message.ts +37 -0
  13. package/src/extensions/logging.ts +42 -0
  14. package/src/extensions/message-window.ts +23 -0
  15. package/src/extensions/required-tools-guard.ts +24 -0
  16. package/src/extensions/tool-search.ts +38 -0
  17. package/src/index.ts +16 -0
  18. package/src/tools/bash.ts +38 -0
  19. package/src/tools/file-system.ts +83 -0
  20. package/src/tools/http-fetch.ts +64 -0
  21. package/src/tools/json-query.ts +71 -0
  22. package/src/tools/text-transform.ts +59 -0
  23. package/src/tools/wait.ts +46 -0
  24. package/tsconfig.json +8 -0
  25. package/vitest.config.ts +7 -0
  26. package/README.md +0 -11
  27. package/dist/extensions/compaction.d.ts +0 -12
  28. package/dist/extensions/compaction.d.ts.map +0 -1
  29. package/dist/extensions/compaction.js +0 -159
  30. package/dist/extensions/compaction.js.map +0 -1
  31. package/dist/extensions/context-message.d.ts +0 -9
  32. package/dist/extensions/context-message.d.ts.map +0 -1
  33. package/dist/extensions/context-message.js +0 -446
  34. package/dist/extensions/context-message.js.map +0 -1
  35. package/dist/extensions/index.d.ts +0 -13
  36. package/dist/extensions/index.d.ts.map +0 -1
  37. package/dist/extensions/index.js +0 -7
  38. package/dist/extensions/index.js.map +0 -1
  39. package/dist/extensions/logging.d.ts +0 -11
  40. package/dist/extensions/logging.d.ts.map +0 -1
  41. package/dist/extensions/logging.js +0 -140
  42. package/dist/extensions/logging.js.map +0 -1
  43. package/dist/extensions/message-integrity.d.ts +0 -8
  44. package/dist/extensions/message-integrity.d.ts.map +0 -1
  45. package/dist/extensions/message-integrity.js +0 -88
  46. package/dist/extensions/message-integrity.js.map +0 -1
  47. package/dist/extensions/message-window.d.ts +0 -7
  48. package/dist/extensions/message-window.d.ts.map +0 -1
  49. package/dist/extensions/message-window.js +0 -60
  50. package/dist/extensions/message-window.js.map +0 -1
  51. package/dist/extensions/required-tools-guard.d.ts +0 -9
  52. package/dist/extensions/required-tools-guard.d.ts.map +0 -1
  53. package/dist/extensions/required-tools-guard.js +0 -74
  54. package/dist/extensions/required-tools-guard.js.map +0 -1
  55. package/dist/extensions/tool-search.d.ts +0 -10
  56. package/dist/extensions/tool-search.d.ts.map +0 -1
  57. package/dist/extensions/tool-search.js +0 -198
  58. package/dist/extensions/tool-search.js.map +0 -1
  59. package/dist/harness.yaml +0 -503
  60. package/dist/index.d.ts.map +0 -1
  61. package/dist/index.js.map +0 -1
  62. package/dist/manifests/base.d.ts +0 -8
  63. package/dist/manifests/base.d.ts.map +0 -1
  64. package/dist/manifests/base.js +0 -352
  65. package/dist/manifests/base.js.map +0 -1
  66. package/dist/manifests/index.d.ts +0 -3
  67. package/dist/manifests/index.d.ts.map +0 -1
  68. package/dist/manifests/index.js +0 -2
  69. package/dist/manifests/index.js.map +0 -1
  70. package/dist/tools/bash.d.ts +0 -8
  71. package/dist/tools/bash.d.ts.map +0 -1
  72. package/dist/tools/bash.js +0 -119
  73. package/dist/tools/bash.js.map +0 -1
  74. package/dist/tools/file-system.d.ts +0 -12
  75. package/dist/tools/file-system.d.ts.map +0 -1
  76. package/dist/tools/file-system.js +0 -117
  77. package/dist/tools/file-system.js.map +0 -1
  78. package/dist/tools/http-fetch.d.ts +0 -8
  79. package/dist/tools/http-fetch.d.ts.map +0 -1
  80. package/dist/tools/http-fetch.js +0 -149
  81. package/dist/tools/http-fetch.js.map +0 -1
  82. package/dist/tools/index.d.ts +0 -7
  83. package/dist/tools/index.d.ts.map +0 -1
  84. package/dist/tools/index.js +0 -7
  85. package/dist/tools/index.js.map +0 -1
  86. package/dist/tools/json-query.d.ts +0 -12
  87. package/dist/tools/json-query.d.ts.map +0 -1
  88. package/dist/tools/json-query.js +0 -176
  89. package/dist/tools/json-query.js.map +0 -1
  90. package/dist/tools/text-transform.d.ts +0 -16
  91. package/dist/tools/text-transform.d.ts.map +0 -1
  92. package/dist/tools/text-transform.js +0 -127
  93. package/dist/tools/text-transform.js.map +0 -1
  94. package/dist/tools/wait.d.ts +0 -6
  95. package/dist/tools/wait.d.ts.map +0 -1
  96. package/dist/tools/wait.js +0 -32
  97. package/dist/tools/wait.js.map +0 -1
  98. package/dist/types.d.ts +0 -4
  99. package/dist/types.d.ts.map +0 -1
  100. package/dist/types.js +0 -6
  101. package/dist/types.js.map +0 -1
  102. package/dist/utils.d.ts +0 -17
  103. package/dist/utils.d.ts.map +0 -1
  104. package/dist/utils.js +0 -159
  105. package/dist/utils.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,5 +1,72 @@
1
- export * from './types.js';
2
- export * from './tools/index.js';
3
- export * from './extensions/index.js';
4
- export * from './manifests/index.js';
5
- //# sourceMappingURL=index.d.ts.map
1
+ import { Extension, ToolDefinition } from '@goondan/openharness-types';
2
+
3
+ /**
4
+ * ContextMessage extension — prepends a system message to the conversation
5
+ * at the start of every turn.
6
+ *
7
+ * Priority 10 (HIGH) ensures it runs before other turn middleware.
8
+ */
9
+ declare function ContextMessage(text: string): Extension;
10
+
11
+ /**
12
+ * MessageWindow extension — truncates conversation history to keep only
13
+ * the most recent `maxMessages` messages before each step.
14
+ */
15
+ declare function MessageWindow(config: {
16
+ maxMessages: number;
17
+ }): Extension;
18
+
19
+ /**
20
+ * CompactionSummarize extension — when message count exceeds `threshold`,
21
+ * removes the oldest messages and prepends a summary system message.
22
+ *
23
+ * For MVP the "summary" is just the concatenation of removed message text.
24
+ */
25
+ declare function CompactionSummarize(config: {
26
+ threshold: number;
27
+ summaryPrompt?: string;
28
+ }): Extension;
29
+
30
+ /**
31
+ * Logging extension — subscribes to core events and logs them.
32
+ */
33
+ declare function Logging(config?: {
34
+ logger?: (msg: string) => void;
35
+ }): Extension;
36
+
37
+ /**
38
+ * ToolSearch extension — registers a meta-tool `search_tools` that searches
39
+ * registered tool names and descriptions by keyword.
40
+ */
41
+ declare function ToolSearch(): Extension;
42
+
43
+ /**
44
+ * RequiredToolsGuard extension — blocks a turn if any required tools are
45
+ * not registered.
46
+ */
47
+ declare function RequiredToolsGuard(config: {
48
+ tools: string[];
49
+ }): Extension;
50
+
51
+ interface BashToolConfig {
52
+ timeout?: number;
53
+ maxBuffer?: number;
54
+ }
55
+ declare function BashTool(config?: BashToolConfig): ToolDefinition;
56
+
57
+ declare function FileReadTool(): ToolDefinition;
58
+ declare function FileWriteTool(): ToolDefinition;
59
+ declare function FileListTool(): ToolDefinition;
60
+
61
+ declare function HttpFetchTool(): ToolDefinition;
62
+
63
+ declare function JsonQueryTool(): ToolDefinition;
64
+
65
+ declare function TextTransformTool(): ToolDefinition;
66
+
67
+ interface WaitToolConfig {
68
+ maxMs?: number;
69
+ }
70
+ declare function WaitTool(config?: WaitToolConfig): ToolDefinition;
71
+
72
+ export { BashTool, type BashToolConfig, CompactionSummarize, ContextMessage, FileListTool, FileReadTool, FileWriteTool, HttpFetchTool, JsonQueryTool, Logging, MessageWindow, RequiredToolsGuard, TextTransformTool, ToolSearch, WaitTool, type WaitToolConfig };
package/dist/index.js CHANGED
@@ -1,5 +1,506 @@
1
- export * from './types.js';
2
- export * from './tools/index.js';
3
- export * from './extensions/index.js';
4
- export * from './manifests/index.js';
5
- //# sourceMappingURL=index.js.map
1
+ // src/extensions/context-message.ts
2
+ import { randomUUID } from "crypto";
3
+ function ContextMessage(text) {
4
+ return {
5
+ name: "context-message",
6
+ register(api) {
7
+ api.pipeline.register(
8
+ "turn",
9
+ async (ctx, next) => {
10
+ ctx.conversation.emit({
11
+ type: "append",
12
+ message: {
13
+ id: `ctx-msg-${randomUUID()}`,
14
+ data: {
15
+ role: "system",
16
+ content: text
17
+ },
18
+ metadata: {
19
+ __createdBy: "context-message"
20
+ }
21
+ }
22
+ });
23
+ return next();
24
+ },
25
+ { priority: 10 }
26
+ );
27
+ }
28
+ };
29
+ }
30
+
31
+ // src/extensions/message-window.ts
32
+ function MessageWindow(config) {
33
+ return {
34
+ name: "message-window",
35
+ register(api) {
36
+ api.pipeline.register("step", async (ctx, next) => {
37
+ if (ctx.conversation.messages.length > config.maxMessages) {
38
+ ctx.conversation.emit({
39
+ type: "truncate",
40
+ keepLast: config.maxMessages
41
+ });
42
+ }
43
+ return next();
44
+ });
45
+ }
46
+ };
47
+ }
48
+
49
+ // src/extensions/compaction-summarize.ts
50
+ import { randomUUID as randomUUID2 } from "crypto";
51
+ function CompactionSummarize(config) {
52
+ return {
53
+ name: "compaction-summarize",
54
+ register(api) {
55
+ api.pipeline.register("step", async (ctx, next) => {
56
+ const messages = ctx.conversation.messages;
57
+ if (messages.length > config.threshold) {
58
+ const keepCount = Math.floor(config.threshold / 2);
59
+ const removeCount = messages.length - keepCount;
60
+ const toRemove = messages.slice(0, removeCount);
61
+ const summaryText = toRemove.map(
62
+ (m) => typeof m.data.content === "string" ? m.data.content : JSON.stringify(m.data.content)
63
+ ).join(" ");
64
+ for (const msg of toRemove) {
65
+ ctx.conversation.emit({ type: "remove", messageId: msg.id });
66
+ }
67
+ ctx.conversation.emit({
68
+ type: "append",
69
+ message: {
70
+ id: `summary-${randomUUID2()}`,
71
+ data: {
72
+ role: "system",
73
+ content: `[Summary of earlier conversation]: ${summaryText}`
74
+ },
75
+ metadata: {
76
+ __createdBy: "compaction-summarize"
77
+ }
78
+ }
79
+ });
80
+ }
81
+ return next();
82
+ });
83
+ }
84
+ };
85
+ }
86
+
87
+ // src/extensions/logging.ts
88
+ function Logging(config) {
89
+ const log = config?.logger ?? console.log;
90
+ return {
91
+ name: "logging",
92
+ register(api) {
93
+ api.on("turn.start", (payload) => {
94
+ log(`[turn.start] ${JSON.stringify(payload)}`);
95
+ });
96
+ api.on("turn.done", (payload) => {
97
+ log(`[turn.done] ${JSON.stringify(payload)}`);
98
+ });
99
+ api.on("turn.error", (payload) => {
100
+ log(`[turn.error] ${JSON.stringify(payload)}`);
101
+ });
102
+ api.on("step.start", (payload) => {
103
+ log(`[step.start] ${JSON.stringify(payload)}`);
104
+ });
105
+ api.on("step.done", (payload) => {
106
+ log(`[step.done] ${JSON.stringify(payload)}`);
107
+ });
108
+ api.on("tool.start", (payload) => {
109
+ log(`[tool.start] ${JSON.stringify(payload)}`);
110
+ });
111
+ api.on("tool.done", (payload) => {
112
+ log(`[tool.done] ${JSON.stringify(payload)}`);
113
+ });
114
+ }
115
+ };
116
+ }
117
+
118
+ // src/extensions/tool-search.ts
119
+ function ToolSearch() {
120
+ return {
121
+ name: "tool-search",
122
+ register(api) {
123
+ api.tools.register({
124
+ name: "search_tools",
125
+ description: "Search registered tools by keyword in name or description.",
126
+ parameters: {
127
+ type: "object",
128
+ properties: {
129
+ query: {
130
+ type: "string",
131
+ description: "Keyword to search for in tool names and descriptions."
132
+ }
133
+ },
134
+ required: ["query"]
135
+ },
136
+ handler: async (args) => {
137
+ const query = args["query"].toLowerCase();
138
+ const allTools = api.tools.list();
139
+ const matching = allTools.filter(
140
+ (t) => t.name.toLowerCase().includes(query) || t.description.toLowerCase().includes(query)
141
+ );
142
+ return { type: "json", data: matching };
143
+ }
144
+ });
145
+ }
146
+ };
147
+ }
148
+
149
+ // src/extensions/required-tools-guard.ts
150
+ function RequiredToolsGuard(config) {
151
+ return {
152
+ name: "required-tools-guard",
153
+ register(api) {
154
+ api.pipeline.register("turn", async (ctx, next) => {
155
+ const registered = api.tools.list().map((t) => t.name);
156
+ const missing = config.tools.filter((name) => !registered.includes(name));
157
+ if (missing.length > 0) {
158
+ throw new Error(
159
+ `RequiredToolsGuard: missing required tools: ${missing.join(", ")}`
160
+ );
161
+ }
162
+ return next();
163
+ });
164
+ }
165
+ };
166
+ }
167
+
168
+ // src/tools/bash.ts
169
+ import { exec } from "child_process";
170
+ function BashTool(config = {}) {
171
+ const { timeout = 3e4, maxBuffer = 1024 * 1024 } = config;
172
+ return {
173
+ name: "bash",
174
+ description: "Execute a shell command and return its output.",
175
+ parameters: {
176
+ type: "object",
177
+ properties: {
178
+ command: { type: "string", description: "The shell command to execute." },
179
+ cwd: { type: "string", description: "Optional working directory for the command." }
180
+ },
181
+ required: ["command"]
182
+ },
183
+ async handler(args, _ctx) {
184
+ const command = args["command"];
185
+ const cwd = args["cwd"];
186
+ return new Promise((resolve) => {
187
+ exec(command, { timeout, maxBuffer, cwd }, (error, stdout, stderr) => {
188
+ if (error) {
189
+ resolve({ type: "error", error: stderr || error.message });
190
+ } else {
191
+ resolve({ type: "text", text: stdout });
192
+ }
193
+ });
194
+ });
195
+ }
196
+ };
197
+ }
198
+
199
+ // src/tools/file-system.ts
200
+ import { readFile, writeFile, readdir } from "fs/promises";
201
+ function FileReadTool() {
202
+ return {
203
+ name: "file_read",
204
+ description: "Read the contents of a file.",
205
+ parameters: {
206
+ type: "object",
207
+ properties: {
208
+ path: { type: "string", description: "Absolute or relative path to the file to read." },
209
+ encoding: {
210
+ type: "string",
211
+ enum: ["utf8", "base64"],
212
+ description: "File encoding. Defaults to utf8."
213
+ }
214
+ },
215
+ required: ["path"]
216
+ },
217
+ async handler(args, _ctx) {
218
+ const filePath = args["path"];
219
+ const encoding = args["encoding"] ?? "utf8";
220
+ try {
221
+ const content = await readFile(filePath, { encoding });
222
+ return { type: "text", text: content };
223
+ } catch (err) {
224
+ return { type: "error", error: err.message };
225
+ }
226
+ }
227
+ };
228
+ }
229
+ function FileWriteTool() {
230
+ return {
231
+ name: "file_write",
232
+ description: "Write content to a file, creating or overwriting it.",
233
+ parameters: {
234
+ type: "object",
235
+ properties: {
236
+ path: { type: "string", description: "Absolute or relative path to the file to write." },
237
+ content: { type: "string", description: "The content to write to the file." }
238
+ },
239
+ required: ["path", "content"]
240
+ },
241
+ async handler(args, _ctx) {
242
+ const filePath = args["path"];
243
+ const content = args["content"];
244
+ try {
245
+ await writeFile(filePath, content, "utf8");
246
+ return { type: "text", text: `File written: ${filePath}` };
247
+ } catch (err) {
248
+ return { type: "error", error: err.message };
249
+ }
250
+ }
251
+ };
252
+ }
253
+ function FileListTool() {
254
+ return {
255
+ name: "file_list",
256
+ description: "List files and directories in a given directory.",
257
+ parameters: {
258
+ type: "object",
259
+ properties: {
260
+ path: { type: "string", description: "Absolute or relative path to the directory to list." }
261
+ },
262
+ required: ["path"]
263
+ },
264
+ async handler(args, _ctx) {
265
+ const dirPath = args["path"];
266
+ try {
267
+ const entries = await readdir(dirPath, { withFileTypes: true });
268
+ const result = entries.map((e) => ({
269
+ name: e.name,
270
+ type: e.isDirectory() ? "directory" : "file"
271
+ }));
272
+ return { type: "json", data: result };
273
+ } catch (err) {
274
+ return { type: "error", error: err.message };
275
+ }
276
+ }
277
+ };
278
+ }
279
+
280
+ // src/tools/http-fetch.ts
281
+ function HttpFetchTool() {
282
+ return {
283
+ name: "http_fetch",
284
+ description: "Perform an HTTP request and return the response.",
285
+ parameters: {
286
+ type: "object",
287
+ properties: {
288
+ url: { type: "string", description: "The URL to fetch." },
289
+ method: {
290
+ type: "string",
291
+ enum: ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"],
292
+ description: "HTTP method. Defaults to GET."
293
+ },
294
+ headers: {
295
+ type: "object",
296
+ additionalProperties: { type: "string" },
297
+ description: "Optional request headers."
298
+ },
299
+ body: { type: "string", description: "Optional request body." }
300
+ },
301
+ required: ["url"]
302
+ },
303
+ async handler(args, _ctx) {
304
+ const url = args["url"];
305
+ const method = args["method"] ?? "GET";
306
+ const headers = args["headers"] ?? {};
307
+ const body = args["body"];
308
+ try {
309
+ const response = await fetch(url, {
310
+ method,
311
+ headers,
312
+ body: body !== void 0 ? body : void 0
313
+ });
314
+ const responseHeaders = {};
315
+ response.headers.forEach((value, key) => {
316
+ responseHeaders[key] = value;
317
+ });
318
+ let responseBody;
319
+ const contentType = response.headers.get("content-type") ?? "";
320
+ if (contentType.includes("application/json")) {
321
+ responseBody = await response.json();
322
+ } else {
323
+ responseBody = await response.text();
324
+ }
325
+ return {
326
+ type: "json",
327
+ data: {
328
+ status: response.status,
329
+ headers: responseHeaders,
330
+ body: responseBody
331
+ }
332
+ };
333
+ } catch (err) {
334
+ return { type: "error", error: err.message };
335
+ }
336
+ }
337
+ };
338
+ }
339
+
340
+ // src/tools/json-query.ts
341
+ function jsonQuery(data, path) {
342
+ let normalized = path.trim();
343
+ if (normalized.startsWith("$.")) {
344
+ normalized = normalized.slice(2);
345
+ } else if (normalized === "$") {
346
+ return data;
347
+ } else if (normalized.startsWith("$")) {
348
+ normalized = normalized.slice(1);
349
+ }
350
+ if (normalized === "" || normalized === ".") {
351
+ return data;
352
+ }
353
+ const segments = [];
354
+ const normalized2 = normalized.replace(/\[(\d+)\]/g, ".$1").replace(/\[['"](.+?)['"]\]/g, ".$1");
355
+ for (const part of normalized2.split(".")) {
356
+ if (part === "") continue;
357
+ const num = Number(part);
358
+ segments.push(Number.isInteger(num) && String(num) === part ? num : part);
359
+ }
360
+ let current = data;
361
+ for (const segment of segments) {
362
+ if (current === null || current === void 0) return void 0;
363
+ if (typeof current === "object") {
364
+ current = current[segment];
365
+ } else {
366
+ return void 0;
367
+ }
368
+ }
369
+ return current;
370
+ }
371
+ function JsonQueryTool() {
372
+ return {
373
+ name: "json_query",
374
+ description: "Query JSON data using a simple JSONPath-like path expression.",
375
+ parameters: {
376
+ type: "object",
377
+ properties: {
378
+ data: { description: "The JSON data to query." },
379
+ path: {
380
+ type: "string",
381
+ description: "JSONPath-like path, e.g. $.key.nested[0].field"
382
+ }
383
+ },
384
+ required: ["data", "path"]
385
+ },
386
+ async handler(args, _ctx) {
387
+ const data = args["data"];
388
+ const path = args["path"];
389
+ try {
390
+ const result = jsonQuery(data, path);
391
+ return { type: "json", data: result };
392
+ } catch (err) {
393
+ return { type: "error", error: err.message };
394
+ }
395
+ }
396
+ };
397
+ }
398
+
399
+ // src/tools/text-transform.ts
400
+ function TextTransformTool() {
401
+ return {
402
+ name: "text_transform",
403
+ description: "Apply a transformation operation to a text string.",
404
+ parameters: {
405
+ type: "object",
406
+ properties: {
407
+ text: { type: "string", description: "The input text to transform." },
408
+ operation: {
409
+ type: "string",
410
+ enum: ["uppercase", "lowercase", "trim", "split", "replace"],
411
+ description: "The transformation to apply."
412
+ },
413
+ options: {
414
+ type: "object",
415
+ properties: {
416
+ delimiter: { type: "string", description: "Delimiter for split operation." },
417
+ find: { type: "string", description: "String to find for replace operation." },
418
+ replacement: { type: "string", description: "Replacement string for replace operation." }
419
+ }
420
+ }
421
+ },
422
+ required: ["text", "operation"]
423
+ },
424
+ async handler(args, _ctx) {
425
+ const text = args["text"];
426
+ const operation = args["operation"];
427
+ const options = args["options"] ?? {};
428
+ try {
429
+ switch (operation) {
430
+ case "uppercase":
431
+ return { type: "text", text: text.toUpperCase() };
432
+ case "lowercase":
433
+ return { type: "text", text: text.toLowerCase() };
434
+ case "trim":
435
+ return { type: "text", text: text.trim() };
436
+ case "split": {
437
+ const delimiter = options["delimiter"] ?? " ";
438
+ return { type: "json", data: text.split(delimiter) };
439
+ }
440
+ case "replace": {
441
+ const find = options["find"] ?? "";
442
+ const replacement = options["replacement"] ?? "";
443
+ return { type: "text", text: text.split(find).join(replacement) };
444
+ }
445
+ default:
446
+ return { type: "error", error: `Unknown operation: ${operation}` };
447
+ }
448
+ } catch (err) {
449
+ return { type: "error", error: err.message };
450
+ }
451
+ }
452
+ };
453
+ }
454
+
455
+ // src/tools/wait.ts
456
+ function WaitTool(config = {}) {
457
+ const { maxMs = 6e4 } = config;
458
+ return {
459
+ name: "wait",
460
+ description: "Wait for a specified number of milliseconds before continuing.",
461
+ parameters: {
462
+ type: "object",
463
+ properties: {
464
+ ms: {
465
+ type: "number",
466
+ description: "Number of milliseconds to wait.",
467
+ minimum: 0
468
+ }
469
+ },
470
+ required: ["ms"]
471
+ },
472
+ async handler(args, ctx) {
473
+ const requestedMs = args["ms"];
474
+ const ms = Math.min(requestedMs, maxMs);
475
+ await new Promise((resolve, reject) => {
476
+ const timer = setTimeout(resolve, ms);
477
+ if (ctx.abortSignal.aborted) {
478
+ clearTimeout(timer);
479
+ reject(new Error("Aborted"));
480
+ return;
481
+ }
482
+ ctx.abortSignal.addEventListener("abort", () => {
483
+ clearTimeout(timer);
484
+ reject(new Error("Aborted"));
485
+ });
486
+ });
487
+ return { type: "text", text: `Waited ${ms}ms` };
488
+ }
489
+ };
490
+ }
491
+ export {
492
+ BashTool,
493
+ CompactionSummarize,
494
+ ContextMessage,
495
+ FileListTool,
496
+ FileReadTool,
497
+ FileWriteTool,
498
+ HttpFetchTool,
499
+ JsonQueryTool,
500
+ Logging,
501
+ MessageWindow,
502
+ RequiredToolsGuard,
503
+ TextTransformTool,
504
+ ToolSearch,
505
+ WaitTool
506
+ };
package/package.json CHANGED
@@ -1,45 +1,23 @@
1
1
  {
2
2
  "name": "@goondan/openharness-base",
3
- "version": "0.0.1-alpha4",
4
- "description": "Barebone harness with reference tools and extensions",
3
+ "version": "2.0.0-alpha.1",
5
4
  "type": "module",
6
- "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
- "homepage": "https://github.com/goondan/openharness#readme",
9
- "bugs": {
10
- "url": "https://github.com/goondan/openharness/issues"
11
- },
12
- "repository": {
13
- "type": "git",
14
- "url": "git+https://github.com/goondan/openharness.git",
15
- "directory": "packages/base"
16
- },
17
5
  "exports": {
18
- ".": {
19
- "types": "./dist/index.d.ts",
20
- "import": "./dist/index.js"
21
- }
22
- },
23
- "files": [
24
- "dist"
25
- ],
26
- "keywords": [
27
- "agent",
28
- "extensions",
29
- "harness",
30
- "reference",
31
- "tools"
32
- ],
33
- "publishConfig": {
34
- "access": "public"
6
+ ".": { "import": "./dist/index.js", "types": "./dist/index.d.ts" }
35
7
  },
36
8
  "scripts": {
37
- "build": "pnpm clean && tsc -p tsconfig.json && node ./build-manifest.mjs",
38
- "typecheck": "tsc --noEmit -p tsconfig.json",
9
+ "build": "tsup src/index.ts --format esm --dts",
39
10
  "test": "vitest run",
11
+ "typecheck": "tsc --noEmit",
40
12
  "clean": "rm -rf dist"
41
13
  },
42
14
  "dependencies": {
43
- "@goondan/openharness-types": "^0.0.1-alpha4"
15
+ "@goondan/openharness-types": "workspace:*"
16
+ },
17
+ "devDependencies": {
18
+ "@types/node": "^25.5.0",
19
+ "tsup": "^8.4.0",
20
+ "typescript": "^5.7.0",
21
+ "vitest": "^3.0.0"
44
22
  }
45
23
  }