@enactprotocol/cli 2.2.4 → 2.3.4

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 (66) hide show
  1. package/README.md +4 -37
  2. package/dist/commands/cache/index.js +5 -5
  3. package/dist/commands/cache/index.js.map +1 -1
  4. package/dist/commands/index.d.ts +1 -0
  5. package/dist/commands/index.d.ts.map +1 -1
  6. package/dist/commands/index.js +2 -0
  7. package/dist/commands/index.js.map +1 -1
  8. package/dist/commands/inspect/index.d.ts.map +1 -1
  9. package/dist/commands/inspect/index.js +3 -2
  10. package/dist/commands/inspect/index.js.map +1 -1
  11. package/dist/commands/install/index.d.ts +1 -1
  12. package/dist/commands/install/index.d.ts.map +1 -1
  13. package/dist/commands/install/index.js +69 -21
  14. package/dist/commands/install/index.js.map +1 -1
  15. package/dist/commands/learn/index.d.ts.map +1 -1
  16. package/dist/commands/learn/index.js +73 -14
  17. package/dist/commands/learn/index.js.map +1 -1
  18. package/dist/commands/list/index.d.ts +1 -1
  19. package/dist/commands/list/index.js +1 -1
  20. package/dist/commands/run/index.d.ts.map +1 -1
  21. package/dist/commands/run/index.js +166 -60
  22. package/dist/commands/run/index.js.map +1 -1
  23. package/dist/commands/serve/index.d.ts +9 -0
  24. package/dist/commands/serve/index.d.ts.map +1 -0
  25. package/dist/commands/serve/index.js +24 -0
  26. package/dist/commands/serve/index.js.map +1 -0
  27. package/dist/commands/validate/index.d.ts.map +1 -1
  28. package/dist/commands/validate/index.js +7 -37
  29. package/dist/commands/validate/index.js.map +1 -1
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +4 -2
  33. package/dist/index.js.map +1 -1
  34. package/dist/utils/errors.js +2 -2
  35. package/package.json +6 -5
  36. package/src/commands/cache/index.ts +5 -5
  37. package/src/commands/env/README.md +1 -1
  38. package/src/commands/index.ts +3 -0
  39. package/src/commands/inspect/index.ts +3 -2
  40. package/src/commands/install/README.md +2 -2
  41. package/src/commands/install/index.ts +98 -21
  42. package/src/commands/learn/index.ts +89 -18
  43. package/src/commands/list/index.ts +1 -1
  44. package/src/commands/run/README.md +1 -1
  45. package/src/commands/run/index.ts +218 -67
  46. package/src/commands/serve/index.ts +26 -0
  47. package/src/commands/validate/index.ts +7 -42
  48. package/src/index.ts +5 -1
  49. package/src/utils/errors.ts +2 -2
  50. package/tests/commands/cache.test.ts +2 -2
  51. package/tests/commands/install-integration.test.ts +11 -12
  52. package/tests/commands/publish.test.ts +12 -2
  53. package/tests/commands/run.test.ts +3 -1
  54. package/tests/commands/serve.test.ts +82 -0
  55. package/tests/commands/sign.test.ts +1 -1
  56. package/tests/e2e.test.ts +56 -34
  57. package/tests/fixtures/calculator/skill.yaml +38 -0
  58. package/tests/fixtures/echo-tool/SKILL.md +3 -10
  59. package/tests/fixtures/env-tool/{enact.yaml → skill.yaml} +0 -6
  60. package/tests/fixtures/greeter/skill.yaml +22 -0
  61. package/tests/utils/ignore.test.ts +3 -1
  62. package/tsconfig.json +2 -1
  63. package/tsconfig.tsbuildinfo +1 -1
  64. package/tests/fixtures/calculator/enact.yaml +0 -34
  65. package/tests/fixtures/greeter/enact.yaml +0 -18
  66. /package/tests/fixtures/invalid-tool/{enact.yaml → skill.yaml} +0 -0
@@ -46,7 +46,7 @@ describe("install integration", () => {
46
46
  mkdirSync(join(TEST_GLOBAL_HOME, ".enact", "cache"), { recursive: true });
47
47
 
48
48
  // Create sample tool source
49
- writeFileSync(join(TEST_TOOL_SRC, "enact.yaml"), SAMPLE_MANIFEST);
49
+ writeFileSync(join(TEST_TOOL_SRC, "skill.yaml"), SAMPLE_MANIFEST);
50
50
  });
51
51
 
52
52
  beforeEach(() => {
@@ -92,7 +92,7 @@ describe("install integration", () => {
92
92
 
93
93
  // Verify installation
94
94
  expect(existsSync(destPath)).toBe(true);
95
- expect(existsSync(join(destPath, "enact.yaml"))).toBe(true);
95
+ expect(existsSync(join(destPath, "skill.yaml"))).toBe(true);
96
96
 
97
97
  // Verify manifest can be loaded from destination
98
98
  const installedManifest = loadManifestFromDir(destPath);
@@ -118,7 +118,7 @@ describe("install integration", () => {
118
118
  // Create v2 source
119
119
  const v2Source = join(TEST_BASE, "source-tool-v2");
120
120
  mkdirSync(v2Source, { recursive: true });
121
- writeFileSync(join(v2Source, "enact.yaml"), SAMPLE_MANIFEST_V2);
121
+ writeFileSync(join(v2Source, "skill.yaml"), SAMPLE_MANIFEST_V2);
122
122
 
123
123
  // Simulate force overwrite
124
124
  rmSync(destPath, { recursive: true, force: true });
@@ -164,15 +164,14 @@ describe("install integration", () => {
164
164
  expect(getInstalledVersion("test/sample-tool", "project", TEST_PROJECT)).toBe("2.0.0");
165
165
  });
166
166
 
167
- test("global install extracts to cache path", async () => {
167
+ test("global install extracts to skills path", async () => {
168
168
  const { getToolCachePath } = await import("@enactprotocol/shared");
169
169
 
170
- // Verify cache path structure
171
- const cachePath = getToolCachePath("test/sample-tool", "1.0.0");
172
- expect(cachePath).toContain(".enact");
173
- expect(cachePath).toContain("cache");
174
- expect(cachePath).toContain("test/sample-tool");
175
- expect(cachePath).toContain("v1.0.0");
170
+ // Verify skill path structure (~/.agent/skills/{name}/, no version subdir)
171
+ const skillPath = getToolCachePath("test/sample-tool", "1.0.0");
172
+ expect(skillPath).toContain(".agent");
173
+ expect(skillPath).toContain("skills");
174
+ expect(skillPath).toContain("test/sample-tool");
176
175
  });
177
176
 
178
177
  test("listInstalledTools returns installed tools from registry", async () => {
@@ -241,7 +240,7 @@ describe("install integration", () => {
241
240
  const cachePath = join(TEST_GLOBAL_HOME, ".enact", "cache", "test", "cached-tool", "v1.0.0");
242
241
  mkdirSync(cachePath, { recursive: true });
243
242
  writeFileSync(
244
- join(cachePath, "enact.yaml"),
243
+ join(cachePath, "skill.yaml"),
245
244
  `
246
245
  name: test/cached-tool
247
246
  version: 1.0.0
@@ -252,7 +251,7 @@ command: echo "cached"
252
251
 
253
252
  // The resolver should be able to find this tool once it's registered
254
253
  // Note: Full resolver testing is in resolver.test.ts
255
- expect(existsSync(join(cachePath, "enact.yaml"))).toBe(true);
254
+ expect(existsSync(join(cachePath, "skill.yaml"))).toBe(true);
256
255
  });
257
256
  });
258
257
  });
@@ -107,11 +107,19 @@ describe("publish command", () => {
107
107
  });
108
108
 
109
109
  describe("manifest file detection", () => {
110
- test("identifies enact.yaml as manifest", () => {
110
+ test("identifies manifest files", () => {
111
111
  const isManifest = (filename: string): boolean => {
112
- return filename === "enact.yaml" || filename === "enact.yml" || filename === "enact.md";
112
+ return (
113
+ filename === "skill.yaml" ||
114
+ filename === "skill.yml" ||
115
+ filename === "enact.yaml" ||
116
+ filename === "enact.yml" ||
117
+ filename === "enact.md"
118
+ );
113
119
  };
114
120
 
121
+ expect(isManifest("skill.yaml")).toBe(true);
122
+ expect(isManifest("skill.yml")).toBe(true);
115
123
  expect(isManifest("enact.yaml")).toBe(true);
116
124
  expect(isManifest("enact.yml")).toBe(true);
117
125
  expect(isManifest("enact.md")).toBe(true);
@@ -124,6 +132,8 @@ describe("publish command", () => {
124
132
  return lastDot === -1 ? "" : filename.slice(lastDot + 1);
125
133
  };
126
134
 
135
+ expect(getExtension("skill.yaml")).toBe("yaml");
136
+ expect(getExtension("skill.yml")).toBe("yml");
127
137
  expect(getExtension("enact.yaml")).toBe("yaml");
128
138
  expect(getExtension("enact.yml")).toBe("yml");
129
139
  expect(getExtension("enact.md")).toBe("md");
@@ -38,7 +38,9 @@ describe("run command", () => {
38
38
  configureRunCommand(program);
39
39
 
40
40
  const runCmd = program.commands.find((cmd) => cmd.name() === "run");
41
- expect(runCmd?.description()).toBe("Execute a tool with its manifest-defined command");
41
+ expect(runCmd?.description()).toBe(
42
+ "Execute a tool or action with its manifest-defined command"
43
+ );
42
44
  });
43
45
 
44
46
  test("accepts tool argument", () => {
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Tests for the serve command
3
+ */
4
+
5
+ import { describe, expect, test } from "bun:test";
6
+ import { Command } from "commander";
7
+ import { configureServeCommand } from "../../src/commands/serve";
8
+
9
+ describe("serve command", () => {
10
+ describe("command configuration", () => {
11
+ test("configures serve command on program", () => {
12
+ const program = new Command();
13
+ configureServeCommand(program);
14
+
15
+ const serveCmd = program.commands.find((cmd) => cmd.name() === "serve");
16
+ expect(serveCmd).toBeDefined();
17
+ });
18
+
19
+ test("has correct description", () => {
20
+ const program = new Command();
21
+ configureServeCommand(program);
22
+
23
+ const serveCmd = program.commands.find((cmd) => cmd.name() === "serve");
24
+ expect(serveCmd?.description()).toBe("Start a self-hosted Enact registry server");
25
+ });
26
+ });
27
+
28
+ describe("options", () => {
29
+ test("has --port option with default 3000", () => {
30
+ const program = new Command();
31
+ configureServeCommand(program);
32
+
33
+ const serveCmd = program.commands.find((cmd) => cmd.name() === "serve");
34
+ const opts = serveCmd?.options ?? [];
35
+ const portOpt = opts.find((o) => o.long === "--port");
36
+ expect(portOpt).toBeDefined();
37
+ expect(portOpt?.defaultValue).toBe("3000");
38
+ });
39
+
40
+ test("has -p short option for port", () => {
41
+ const program = new Command();
42
+ configureServeCommand(program);
43
+
44
+ const serveCmd = program.commands.find((cmd) => cmd.name() === "serve");
45
+ const opts = serveCmd?.options ?? [];
46
+ const portOpt = opts.find((o) => o.short === "-p");
47
+ expect(portOpt).toBeDefined();
48
+ });
49
+
50
+ test("has --data option with default ./registry-data", () => {
51
+ const program = new Command();
52
+ configureServeCommand(program);
53
+
54
+ const serveCmd = program.commands.find((cmd) => cmd.name() === "serve");
55
+ const opts = serveCmd?.options ?? [];
56
+ const dataOpt = opts.find((o) => o.long === "--data");
57
+ expect(dataOpt).toBeDefined();
58
+ expect(dataOpt?.defaultValue).toBe("./registry-data");
59
+ });
60
+
61
+ test("has -d short option for data", () => {
62
+ const program = new Command();
63
+ configureServeCommand(program);
64
+
65
+ const serveCmd = program.commands.find((cmd) => cmd.name() === "serve");
66
+ const opts = serveCmd?.options ?? [];
67
+ const dataOpt = opts.find((o) => o.short === "-d");
68
+ expect(dataOpt).toBeDefined();
69
+ });
70
+
71
+ test("has --host option with default 0.0.0.0", () => {
72
+ const program = new Command();
73
+ configureServeCommand(program);
74
+
75
+ const serveCmd = program.commands.find((cmd) => cmd.name() === "serve");
76
+ const opts = serveCmd?.options ?? [];
77
+ const hostOpt = opts.find((o) => o.long === "--host");
78
+ expect(hostOpt).toBeDefined();
79
+ expect(hostOpt?.defaultValue).toBe("0.0.0.0");
80
+ });
81
+ });
82
+ });
@@ -17,7 +17,7 @@ describe("sign command", () => {
17
17
 
18
18
  // Create a test manifest
19
19
  writeFileSync(
20
- join(FIXTURES_DIR, "enact.yaml"),
20
+ join(FIXTURES_DIR, "skill.yaml"),
21
21
  `enact: "2.0.0"
22
22
  name: "test/sign-tool"
23
23
  version: "1.0.0"
package/tests/e2e.test.ts CHANGED
@@ -17,7 +17,9 @@ import {
17
17
  type ToolManifest,
18
18
  applyDefaults,
19
19
  loadManifestFromDir,
20
+ prepareActionCommand,
20
21
  prepareCommand,
22
+ scriptToAction,
21
23
  toolNameToPath,
22
24
  tryResolveTool,
23
25
  validateInputs,
@@ -77,7 +79,7 @@ describe("E2E: Fixture Validation", () => {
77
79
  expect(loaded?.manifest.name).toBe("test/greeter");
78
80
  expect(loaded?.manifest.version).toBe("1.0.0");
79
81
  expect(loaded?.manifest.from).toBe("alpine:latest");
80
- expect(loaded?.manifest.command).toContain("echo");
82
+ expect(loaded?.manifest.scripts?.greet).toBeDefined();
81
83
  });
82
84
 
83
85
  test("echo-tool fixture has valid Markdown manifest", () => {
@@ -88,15 +90,12 @@ describe("E2E: Fixture Validation", () => {
88
90
  expect(loaded?.format).toBe("md");
89
91
  });
90
92
 
91
- test("calculator fixture has valid manifest with complex schema", () => {
93
+ test("calculator fixture has valid manifest with scripts", () => {
92
94
  const loaded = loadManifestFromDir(CALCULATOR_TOOL);
93
95
  expect(loaded).not.toBeNull();
94
96
  expect(loaded?.manifest.name).toBe("test/calculator");
95
97
  expect(loaded?.manifest.from).toBe("python:3.12-alpine");
96
- expect(loaded?.manifest.inputSchema?.properties?.operation).toBeDefined();
97
- expect(loaded?.manifest.inputSchema?.required).toContain("operation");
98
- expect(loaded?.manifest.inputSchema?.required).toContain("a");
99
- expect(loaded?.manifest.inputSchema?.required).toContain("b");
98
+ expect(loaded?.manifest.scripts?.calculate).toBeDefined();
100
99
  });
101
100
 
102
101
  test("invalid-tool fixture is missing required fields", () => {
@@ -126,7 +125,9 @@ describe("E2E: Tool Installation Flow", () => {
126
125
 
127
126
  expect(manifest.name).toBe("test/greeter");
128
127
  expect(existsSync(destPath)).toBe(true);
129
- expect(existsSync(join(destPath, "enact.yaml"))).toBe(true);
128
+ expect(
129
+ existsSync(join(destPath, "enact.yaml")) || existsSync(join(destPath, "skill.yaml"))
130
+ ).toBe(true);
130
131
 
131
132
  // Verify installed manifest can be loaded
132
133
  const reloaded = loadManifestFromDir(destPath);
@@ -243,39 +244,41 @@ describe("E2E: Input Validation Flow", () => {
243
244
  });
244
245
 
245
246
  test("validates greeter with default input", () => {
246
- // Apply defaults first, then validate
247
- const withDefaults = applyDefaults({}, greeterManifest.inputSchema);
248
- const result = validateInputs(withDefaults, greeterManifest.inputSchema);
247
+ // Convert script to action to get its inputSchema
248
+ const action = scriptToAction("greet", greeterManifest.scripts!.greet!);
249
+ const withDefaults = applyDefaults({}, action.inputSchema);
250
+ const result = validateInputs(withDefaults, action.inputSchema);
249
251
  expect(result.valid).toBe(true);
250
252
  // Should have default applied
251
253
  expect(withDefaults.name).toBe("World");
252
254
  });
253
255
 
254
256
  test("validates greeter with custom input", () => {
255
- const result = validateInputs({ name: "Alice" }, greeterManifest.inputSchema);
257
+ const action = scriptToAction("greet", greeterManifest.scripts!.greet!);
258
+ const result = validateInputs({ name: "Alice" }, action.inputSchema);
256
259
  expect(result.valid).toBe(true);
257
260
  expect(result.coercedValues?.name).toBe("Alice");
258
261
  });
259
262
 
260
263
  test("validates calculator with all required inputs", () => {
261
- const result = validateInputs({ operation: "add", a: 5, b: 3 }, calculatorManifest.inputSchema);
264
+ const action = scriptToAction("calculate", calculatorManifest.scripts!.calculate!);
265
+ const result = validateInputs({ operation: "add", a: 5, b: 3 }, action.inputSchema);
262
266
  expect(result.valid).toBe(true);
263
267
  });
264
268
 
265
269
  test("fails validation when required input is missing", () => {
270
+ const action = scriptToAction("calculate", calculatorManifest.scripts!.calculate!);
266
271
  const result = validateInputs(
267
272
  { operation: "add", a: 5 }, // missing 'b'
268
- calculatorManifest.inputSchema
273
+ action.inputSchema
269
274
  );
270
275
  expect(result.valid).toBe(false);
271
276
  expect(result.errors.length).toBeGreaterThan(0);
272
277
  });
273
278
 
274
279
  test("fails validation with invalid enum value", () => {
275
- const result = validateInputs(
276
- { operation: "invalid", a: 5, b: 3 },
277
- calculatorManifest.inputSchema
278
- );
280
+ const action = scriptToAction("calculate", calculatorManifest.scripts!.calculate!);
281
+ const result = validateInputs({ operation: "invalid", a: 5, b: 3 }, action.inputSchema);
279
282
  expect(result.valid).toBe(false);
280
283
  });
281
284
  });
@@ -291,11 +294,15 @@ describe("E2E: Command Preparation Flow", () => {
291
294
  expect(preparedStr).not.toContain("${name}");
292
295
  });
293
296
 
294
- test("prepares calculator command with multiple inputs", () => {
297
+ test("prepares calculator command with multiple inputs (scripts)", () => {
295
298
  const loaded = loadManifestFromDir(CALCULATOR_TOOL);
296
- const command = loaded?.manifest.command!;
299
+ const action = scriptToAction("calculate", loaded!.manifest.scripts!.calculate!);
297
300
 
298
- const prepared = prepareCommand(command, { operation: "add", a: 5, b: 3 });
301
+ const prepared = prepareActionCommand(
302
+ action.command as string[],
303
+ { operation: "add", a: 5, b: 3 },
304
+ action.inputSchema
305
+ );
299
306
  const preparedStr = prepared.join(" ");
300
307
 
301
308
  expect(preparedStr).toContain("add");
@@ -472,7 +479,7 @@ describe("E2E: Full Workflow", () => {
472
479
  }
473
480
  });
474
481
 
475
- test("complete install -> resolve -> validate -> prepare flow", () => {
482
+ test("complete install -> resolve -> validate -> prepare flow (scripts)", () => {
476
483
  // 1. Install tool
477
484
  const destBase = join(tempDir, ".enact", "tools");
478
485
  const { manifest } = installTool(GREETER_TOOL, destBase);
@@ -482,18 +489,23 @@ describe("E2E: Full Workflow", () => {
482
489
  const resolution = tryResolveTool("test/greeter", { startDir: tempDir });
483
490
  expect(resolution).not.toBeNull();
484
491
 
485
- // 3. Validate inputs
486
- const validation = validateInputs({ name: "TestUser" }, manifest.inputSchema);
492
+ // 3. Convert script to action and validate
493
+ const action = scriptToAction("greet", manifest.scripts!.greet!);
494
+ const validation = validateInputs({ name: "TestUser" }, action.inputSchema);
487
495
  expect(validation.valid).toBe(true);
488
496
 
489
- // 4. Prepare command
490
- const prepared = prepareCommand(manifest.command!, validation.coercedValues!);
497
+ // 4. Prepare action command
498
+ const prepared = prepareActionCommand(
499
+ action.command as string[],
500
+ validation.coercedValues!,
501
+ action.inputSchema
502
+ );
491
503
  const preparedStr = prepared.join(" ");
492
504
  expect(preparedStr).toContain("TestUser");
493
505
  expect(preparedStr).toContain("Hello");
494
506
  });
495
507
 
496
- test("complete calculator workflow", () => {
508
+ test("complete calculator workflow (scripts)", () => {
497
509
  // 1. Install tool
498
510
  const destBase = join(tempDir, ".enact", "tools");
499
511
  const { manifest } = installTool(CALCULATOR_TOOL, destBase);
@@ -502,7 +514,9 @@ describe("E2E: Full Workflow", () => {
502
514
  const resolution = tryResolveTool("test/calculator", { startDir: tempDir });
503
515
  expect(resolution).not.toBeNull();
504
516
 
505
- // 3. Validate multiple operations
517
+ // 3. Convert script to action and validate multiple operations
518
+ const action = scriptToAction("calculate", manifest.scripts!.calculate!);
519
+
506
520
  const operations = [
507
521
  { operation: "add", a: 10, b: 5 },
508
522
  { operation: "subtract", a: 10, b: 5 },
@@ -511,10 +525,14 @@ describe("E2E: Full Workflow", () => {
511
525
  ];
512
526
 
513
527
  for (const inputs of operations) {
514
- const validation = validateInputs(inputs, manifest.inputSchema);
528
+ const validation = validateInputs(inputs, action.inputSchema);
515
529
  expect(validation.valid).toBe(true);
516
530
 
517
- const prepared = prepareCommand(manifest.command!, validation.coercedValues!);
531
+ const prepared = prepareActionCommand(
532
+ action.command as string[],
533
+ validation.coercedValues!,
534
+ action.inputSchema
535
+ );
518
536
  const preparedStr = prepared.join(" ");
519
537
  expect(preparedStr).toContain(inputs.operation);
520
538
  expect(preparedStr).toContain(String(inputs.a));
@@ -522,7 +540,7 @@ describe("E2E: Full Workflow", () => {
522
540
  }
523
541
  });
524
542
 
525
- test("handles markdown tool workflow", () => {
543
+ test("handles markdown tool workflow (scripts)", () => {
526
544
  // Install markdown-based tool
527
545
  const destBase = join(tempDir, ".enact", "tools");
528
546
  const { manifest } = installTool(ECHO_TOOL, destBase);
@@ -532,12 +550,16 @@ describe("E2E: Full Workflow", () => {
532
550
  const resolution = tryResolveTool("test/echo-tool", { startDir: tempDir });
533
551
  expect(resolution).not.toBeNull();
534
552
 
535
- // Validate
536
- const validation = validateInputs({ text: "Hello from markdown tool!" }, manifest.inputSchema);
553
+ // Convert script to action, validate, prepare
554
+ const action = scriptToAction("echo", manifest.scripts!.echo!);
555
+ const validation = validateInputs({ text: "Hello from markdown tool!" }, action.inputSchema);
537
556
  expect(validation.valid).toBe(true);
538
557
 
539
- // Prepare
540
- const prepared = prepareCommand(manifest.command!, validation.coercedValues!);
558
+ const prepared = prepareActionCommand(
559
+ action.command as string[],
560
+ validation.coercedValues!,
561
+ action.inputSchema
562
+ );
541
563
  const preparedStr = prepared.join(" ");
542
564
  expect(preparedStr).toContain("Hello from markdown tool!");
543
565
  });
@@ -0,0 +1,38 @@
1
+ enact: "2.0.0"
2
+ name: test/calculator
3
+ version: "2.0.0"
4
+ description: A calculator tool that performs basic math operations
5
+ from: python:3.12-alpine
6
+
7
+ scripts:
8
+ calculate:
9
+ command: "python3 -c \"import json; print(json.dumps({'result': eval('{{a}} + {{b}}' if '{{operation}}'=='add' else '{{a}} - {{b}}' if '{{operation}}'=='subtract' else '{{a}} * {{b}}' if '{{operation}}'=='multiply' else '{{a}} / {{b}}'), 'operation': '{{operation}}'}))\""
10
+ inputSchema:
11
+ type: object
12
+ properties:
13
+ operation:
14
+ type: string
15
+ enum:
16
+ - add
17
+ - subtract
18
+ - multiply
19
+ - divide
20
+ description: The math operation to perform
21
+ a:
22
+ type: number
23
+ description: First operand
24
+ b:
25
+ type: number
26
+ description: Second operand
27
+ required:
28
+ - operation
29
+ - a
30
+ - b
31
+
32
+ outputSchema:
33
+ type: object
34
+ properties:
35
+ result:
36
+ type: number
37
+ operation:
38
+ type: string
@@ -4,15 +4,8 @@ name: test/echo-tool
4
4
  version: "1.0.0"
5
5
  description: A tool that echoes its input for testing
6
6
  from: alpine:latest
7
- command: echo '{"output":"${text}"}'
8
- inputSchema:
9
- type: object
10
- properties:
11
- text:
12
- type: string
13
- description: Text to echo
14
- required:
15
- - text
7
+ scripts:
8
+ echo: "echo '{\"output\":\"{{text}}\"}'"
16
9
  outputSchema:
17
10
  type: object
18
11
  properties:
@@ -27,5 +20,5 @@ A simple tool that echoes back the input text. Used for testing.
27
20
  ## Usage
28
21
 
29
22
  ```bash
30
- enact run test/echo-tool --input text="Hello"
23
+ enact run test/echo-tool:echo --input text="Hello"
31
24
  ```
@@ -11,9 +11,3 @@ env:
11
11
  SECRET_VAR:
12
12
  secret: true
13
13
  description: A secret environment variable
14
- inputSchema:
15
- type: object
16
- properties:
17
- showEnv:
18
- type: boolean
19
- default: false
@@ -0,0 +1,22 @@
1
+ enact: "2.0.0"
2
+ name: test/greeter
3
+ version: "1.0.0"
4
+ description: A simple greeting tool for testing
5
+ from: alpine:latest
6
+
7
+ scripts:
8
+ greet:
9
+ command: "echo '{\"message\":\"Hello, {{name}}!\"}'"
10
+ inputSchema:
11
+ type: object
12
+ properties:
13
+ name:
14
+ type: string
15
+ description: Name to greet
16
+ default: World
17
+
18
+ outputSchema:
19
+ type: object
20
+ properties:
21
+ message:
22
+ type: string
@@ -280,7 +280,9 @@ dist `;
280
280
  expect(shouldIgnore("lib/utils.js", "utils.js")).toBe(false);
281
281
  });
282
282
 
283
- test("allows enact manifest files", () => {
283
+ test("allows manifest files", () => {
284
+ expect(shouldIgnore("skill.yaml", "skill.yaml")).toBe(false);
285
+ expect(shouldIgnore("skill.yml", "skill.yml")).toBe(false);
284
286
  expect(shouldIgnore("enact.md", "enact.md")).toBe(false);
285
287
  expect(shouldIgnore("enact.yaml", "enact.yaml")).toBe(false);
286
288
  expect(shouldIgnore("enact.yml", "enact.yml")).toBe(false);
package/tsconfig.json CHANGED
@@ -13,6 +13,7 @@
13
13
  { "path": "../shared" },
14
14
  { "path": "../secrets" },
15
15
  { "path": "../execution" },
16
- { "path": "../api" }
16
+ { "path": "../api" },
17
+ { "path": "../registry" }
17
18
  ]
18
19
  }