@enactprotocol/cli 2.3.7 → 2.3.8

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 (44) hide show
  1. package/dist/commands/init/index.d.ts.map +1 -1
  2. package/dist/commands/init/index.js +94 -46
  3. package/dist/commands/init/index.js.map +1 -1
  4. package/dist/commands/init/templates/agent-agents.d.ts +1 -1
  5. package/dist/commands/init/templates/agent-agents.d.ts.map +1 -1
  6. package/dist/commands/init/templates/agent-agents.js +1 -1
  7. package/dist/commands/init/templates/default-skill-package.d.ts +5 -0
  8. package/dist/commands/init/templates/default-skill-package.d.ts.map +1 -0
  9. package/dist/commands/init/templates/default-skill-package.js +13 -0
  10. package/dist/commands/init/templates/default-skill-package.js.map +1 -0
  11. package/dist/commands/init/templates/default-skill-script.d.ts +5 -0
  12. package/dist/commands/init/templates/default-skill-script.d.ts.map +1 -0
  13. package/dist/commands/init/templates/default-skill-script.js +11 -0
  14. package/dist/commands/init/templates/default-skill-script.js.map +1 -0
  15. package/dist/commands/init/templates/index.d.ts +2 -0
  16. package/dist/commands/init/templates/index.d.ts.map +1 -1
  17. package/dist/commands/init/templates/index.js +2 -0
  18. package/dist/commands/init/templates/index.js.map +1 -1
  19. package/dist/commands/install/index.d.ts +2 -2
  20. package/dist/commands/install/index.js +18 -18
  21. package/dist/commands/install/index.js.map +1 -1
  22. package/dist/commands/list/index.d.ts +2 -2
  23. package/dist/commands/list/index.js +3 -3
  24. package/dist/commands/list/index.js.map +1 -1
  25. package/dist/commands/search/index.js +2 -2
  26. package/dist/commands/search/index.js.map +1 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.js +1 -1
  29. package/package.json +6 -6
  30. package/src/commands/init/index.ts +103 -46
  31. package/src/commands/init/templates/agent-agents.ts +1 -1
  32. package/src/commands/init/templates/default-skill-package.ts +12 -0
  33. package/src/commands/init/templates/default-skill-script.ts +10 -0
  34. package/src/commands/init/templates/index.ts +2 -0
  35. package/src/commands/install/README.md +1 -1
  36. package/src/commands/install/index.ts +18 -18
  37. package/src/commands/list/index.ts +3 -3
  38. package/src/commands/search/index.ts +2 -2
  39. package/src/index.ts +1 -1
  40. package/tests/commands/cache.test.ts +2 -2
  41. package/tests/commands/init.test.ts +66 -55
  42. package/tests/commands/install-integration.test.ts +6 -6
  43. package/tests/e2e.test.ts +10 -10
  44. package/tsconfig.tsbuildinfo +1 -1
@@ -107,7 +107,7 @@ describe("init command", () => {
107
107
  }
108
108
  });
109
109
 
110
- test("default mode creates AGENTS.md for tool consumers", async () => {
110
+ test("default mode creates skill.package.yaml", async () => {
111
111
  const program = new Command();
112
112
  program.exitOverride();
113
113
  configureInitCommand(program);
@@ -116,27 +116,23 @@ describe("init command", () => {
116
116
  process.chdir(testDir);
117
117
 
118
118
  try {
119
- await program.parseAsync(["node", "test", "init"]);
119
+ await program.parseAsync(["node", "test", "init", "--name", "test/my-tool"]);
120
120
  } catch {
121
121
  // Command may throw due to exitOverride
122
122
  } finally {
123
123
  process.chdir(originalCwd);
124
124
  }
125
125
 
126
- const agentsPath = join(testDir, "AGENTS.md");
127
- expect(existsSync(agentsPath)).toBe(true);
126
+ const packagePath = join(testDir, "skill.package.yaml");
127
+ expect(existsSync(packagePath)).toBe(true);
128
128
 
129
- const content = readFileSync(agentsPath, "utf-8");
130
- expect(content).toContain("enact search");
131
- expect(content).toContain("enact install");
132
- expect(content).toContain("Finding & Installing Tools");
133
-
134
- // Should NOT create enact.md in default mode
135
- const manifestPath = join(testDir, "enact.md");
136
- expect(existsSync(manifestPath)).toBe(false);
129
+ const content = readFileSync(packagePath, "utf-8");
130
+ expect(content).toContain("name: test/my-tool");
131
+ expect(content).toContain("enact:");
132
+ expect(content).toContain("scripts:");
137
133
  });
138
134
 
139
- test("default mode creates .enact/tools.json", async () => {
135
+ test("default mode creates hello.py", async () => {
140
136
  const program = new Command();
141
137
  program.exitOverride();
142
138
  configureInitCommand(program);
@@ -145,18 +141,19 @@ describe("init command", () => {
145
141
  process.chdir(testDir);
146
142
 
147
143
  try {
148
- await program.parseAsync(["node", "test", "init"]);
144
+ await program.parseAsync(["node", "test", "init", "--name", "test/my-tool"]);
149
145
  } catch {
150
146
  // Command may throw due to exitOverride
151
147
  } finally {
152
148
  process.chdir(originalCwd);
153
149
  }
154
150
 
155
- const toolsJsonPath = join(testDir, ".enact", "tools.json");
156
- expect(existsSync(toolsJsonPath)).toBe(true);
151
+ const scriptPath = join(testDir, "hello.py");
152
+ expect(existsSync(scriptPath)).toBe(true);
157
153
 
158
- const content = JSON.parse(readFileSync(toolsJsonPath, "utf-8"));
159
- expect(content).toEqual({ tools: {} });
154
+ const content = readFileSync(scriptPath, "utf-8");
155
+ expect(content).toContain("json.dumps");
156
+ expect(content).toContain("Hello");
160
157
  });
161
158
 
162
159
  test("--tool mode creates SKILL.md", async () => {
@@ -267,7 +264,7 @@ describe("init command", () => {
267
264
  expect(existsSync(join(testDir, "AGENTS.md"))).toBe(false);
268
265
  });
269
266
 
270
- test("--agent mode creates .enact/tools.json", async () => {
267
+ test("--agent mode creates agents/skills.json", async () => {
271
268
  const program = new Command();
272
269
  program.exitOverride();
273
270
  configureInitCommand(program);
@@ -283,14 +280,14 @@ describe("init command", () => {
283
280
  process.chdir(originalCwd);
284
281
  }
285
282
 
286
- const toolsJsonPath = join(testDir, ".enact", "tools.json");
287
- expect(existsSync(toolsJsonPath)).toBe(true);
283
+ const skillsJsonPath = join(testDir, "agents", "skills.json");
284
+ expect(existsSync(skillsJsonPath)).toBe(true);
288
285
 
289
- const content = JSON.parse(readFileSync(toolsJsonPath, "utf-8"));
286
+ const content = JSON.parse(readFileSync(skillsJsonPath, "utf-8"));
290
287
  expect(content).toEqual({ tools: {} });
291
288
  });
292
289
 
293
- test("--claude mode creates .enact/tools.json", async () => {
290
+ test("--claude mode creates agents/skills.json", async () => {
294
291
  const program = new Command();
295
292
  program.exitOverride();
296
293
  configureInitCommand(program);
@@ -306,20 +303,20 @@ describe("init command", () => {
306
303
  process.chdir(originalCwd);
307
304
  }
308
305
 
309
- const toolsJsonPath = join(testDir, ".enact", "tools.json");
310
- expect(existsSync(toolsJsonPath)).toBe(true);
306
+ const skillsJsonPath = join(testDir, "agents", "skills.json");
307
+ expect(existsSync(skillsJsonPath)).toBe(true);
311
308
 
312
- const content = JSON.parse(readFileSync(toolsJsonPath, "utf-8"));
309
+ const content = JSON.parse(readFileSync(skillsJsonPath, "utf-8"));
313
310
  expect(content).toEqual({ tools: {} });
314
311
  });
315
312
 
316
- test("--agent mode with --force overwrites existing .enact/tools.json", async () => {
317
- // Create existing .enact/tools.json with some content
318
- const enactDir = join(testDir, ".enact");
319
- mkdirSync(enactDir, { recursive: true });
320
- const toolsJsonPath = join(enactDir, "tools.json");
313
+ test("--agent mode with --force overwrites existing agents/skills.json", async () => {
314
+ // Create existing agents/skills.json with some content
315
+ const agentsDir = join(testDir, "agents");
316
+ mkdirSync(agentsDir, { recursive: true });
317
+ const skillsJsonPath = join(agentsDir, "skills.json");
321
318
  const existingContent = { tools: { "some/tool": "1.0.0" } };
322
- writeFileSync(toolsJsonPath, JSON.stringify(existingContent));
319
+ writeFileSync(skillsJsonPath, JSON.stringify(existingContent));
323
320
 
324
321
  const program = new Command();
325
322
  program.exitOverride();
@@ -336,17 +333,17 @@ describe("init command", () => {
336
333
  process.chdir(originalCwd);
337
334
  }
338
335
 
339
- const content = JSON.parse(readFileSync(toolsJsonPath, "utf-8"));
336
+ const content = JSON.parse(readFileSync(skillsJsonPath, "utf-8"));
340
337
  expect(content).toEqual({ tools: {} });
341
338
  });
342
339
 
343
- test("--agent mode preserves existing .enact/tools.json without --force", async () => {
344
- // Create existing .enact/tools.json with some content
345
- const enactDir = join(testDir, ".enact");
346
- mkdirSync(enactDir, { recursive: true });
347
- const toolsJsonPath = join(enactDir, "tools.json");
340
+ test("--agent mode preserves existing agents/skills.json without --force", async () => {
341
+ // Create existing agents/skills.json with some content
342
+ const agentsDir = join(testDir, "agents");
343
+ mkdirSync(agentsDir, { recursive: true });
344
+ const skillsJsonPath = join(agentsDir, "skills.json");
348
345
  const existingContent = { tools: { "some/tool": "1.0.0" } };
349
- writeFileSync(toolsJsonPath, JSON.stringify(existingContent));
346
+ writeFileSync(skillsJsonPath, JSON.stringify(existingContent));
350
347
 
351
348
  // Also create AGENTS.md so the command doesn't fail early
352
349
  writeFileSync(join(testDir, "AGENTS.md"), "existing");
@@ -359,10 +356,6 @@ describe("init command", () => {
359
356
  process.chdir(testDir);
360
357
 
361
358
  try {
362
- // Without --force, AGENTS.md check will fail and return early
363
- // So we need to test with --force on AGENTS.md but not tools.json
364
- // Actually the --force flag applies to both, so let's just verify
365
- // tools.json is preserved when it exists and no --force
366
359
  await program.parseAsync(["node", "test", "init", "--agent"]);
367
360
  } catch {
368
361
  // Command may throw due to exitOverride or warning about existing file
@@ -370,12 +363,12 @@ describe("init command", () => {
370
363
  process.chdir(originalCwd);
371
364
  }
372
365
 
373
- // tools.json should be preserved since AGENTS.md existed and no --force was used
374
- const content = JSON.parse(readFileSync(toolsJsonPath, "utf-8"));
366
+ // skills.json should be preserved since AGENTS.md existed and no --force was used
367
+ const content = JSON.parse(readFileSync(skillsJsonPath, "utf-8"));
375
368
  expect(content).toEqual(existingContent);
376
369
  });
377
370
 
378
- test("--tool mode does NOT create .enact/tools.json", async () => {
371
+ test("--tool mode does NOT create agents/skills.json", async () => {
379
372
  const program = new Command();
380
373
  program.exitOverride();
381
374
  configureInitCommand(program);
@@ -391,8 +384,8 @@ describe("init command", () => {
391
384
  process.chdir(originalCwd);
392
385
  }
393
386
 
394
- const toolsJsonPath = join(testDir, ".enact", "tools.json");
395
- expect(existsSync(toolsJsonPath)).toBe(false);
387
+ const skillsJsonPath = join(testDir, "agents", "skills.json");
388
+ expect(existsSync(skillsJsonPath)).toBe(false);
396
389
  });
397
390
 
398
391
  test("SKILL.md contains valid YAML frontmatter", async () => {
@@ -481,21 +474,39 @@ describe("init command", () => {
481
474
  expect(content).toContain("enact search");
482
475
  expect(content).toContain("enact install");
483
476
  expect(content).toContain("enact list");
484
- expect(content).toContain(".enact/tools.json");
477
+ expect(content).toContain("agents/skills.json");
485
478
  });
486
479
  });
487
480
 
488
481
  describe("option conflicts", () => {
489
- test("--agent is the default when no mode specified", () => {
482
+ test("default mode creates a skill when no mode specified", async () => {
490
483
  const program = new Command();
484
+ program.exitOverride();
491
485
  configureInitCommand(program);
492
486
 
493
- const initCmd = program.commands.find((cmd) => cmd.name() === "init");
494
- const opts = initCmd?.options ?? [];
495
- const agentOpt = opts.find((o) => o.long === "--agent");
487
+ const testDir = join(import.meta.dir, ".test-init-default");
488
+ if (existsSync(testDir)) {
489
+ rmSync(testDir, { recursive: true });
490
+ }
491
+ mkdirSync(testDir, { recursive: true });
492
+
493
+ const originalCwd = process.cwd();
494
+ process.chdir(testDir);
495
+
496
+ try {
497
+ await program.parseAsync(["node", "test", "init", "--name", "test/tool"]);
498
+ } catch {
499
+ // Command may throw due to exitOverride
500
+ } finally {
501
+ process.chdir(originalCwd);
502
+ }
503
+
504
+ // Default should create skill files, not AGENTS.md
505
+ expect(existsSync(join(testDir, "skill.package.yaml"))).toBe(true);
506
+ expect(existsSync(join(testDir, "hello.py"))).toBe(true);
507
+ expect(existsSync(join(testDir, "AGENTS.md"))).toBe(false);
496
508
 
497
- // Description should indicate it's the default
498
- expect(agentOpt?.description).toContain("default");
509
+ rmSync(testDir, { recursive: true });
499
510
  });
500
511
  });
501
512
 
@@ -167,9 +167,9 @@ describe("install integration", () => {
167
167
  test("global install extracts to skills path", async () => {
168
168
  const { getToolCachePath } = await import("@enactprotocol/shared");
169
169
 
170
- // Verify skill path structure (~/.agent/skills/{name}/, no version subdir)
170
+ // Verify skill path structure (~/.agents/skills/{name}/, no version subdir)
171
171
  const skillPath = getToolCachePath("test/sample-tool", "1.0.0");
172
- expect(skillPath).toContain(".agent");
172
+ expect(skillPath).toContain(".agents");
173
173
  expect(skillPath).toContain("skills");
174
174
  expect(skillPath).toContain("test/sample-tool");
175
175
  });
@@ -260,7 +260,7 @@ describe("tools.json edge cases", () => {
260
260
  const EDGE_TEST_DIR = join(TEST_BASE, "edge-cases");
261
261
 
262
262
  beforeAll(() => {
263
- mkdirSync(join(EDGE_TEST_DIR, ".enact"), { recursive: true });
263
+ mkdirSync(join(EDGE_TEST_DIR, "agents"), { recursive: true });
264
264
  });
265
265
 
266
266
  afterAll(() => {
@@ -270,10 +270,10 @@ describe("tools.json edge cases", () => {
270
270
  });
271
271
 
272
272
  beforeEach(() => {
273
- // Ensure .enact directory exists
274
- mkdirSync(join(EDGE_TEST_DIR, ".enact"), { recursive: true });
273
+ // Ensure agents directory exists
274
+ mkdirSync(join(EDGE_TEST_DIR, "agents"), { recursive: true });
275
275
 
276
- const jsonPath = join(EDGE_TEST_DIR, ".enact", "tools.json");
276
+ const jsonPath = join(EDGE_TEST_DIR, "agents", "skills.json");
277
277
  if (existsSync(jsonPath)) {
278
278
  rmSync(jsonPath);
279
279
  }
package/tests/e2e.test.ts CHANGED
@@ -119,8 +119,8 @@ describe("E2E: Tool Installation Flow", () => {
119
119
  }
120
120
  });
121
121
 
122
- test("installs tool to project .enact/tools directory", () => {
123
- const destBase = join(tempDir, ".enact", "tools");
122
+ test("installs tool to project agents/skills directory", () => {
123
+ const destBase = join(tempDir, "agents", "skills");
124
124
  const { manifest, destPath } = installTool(GREETER_TOOL, destBase);
125
125
 
126
126
  expect(manifest.name).toBe("test/greeter");
@@ -138,7 +138,7 @@ describe("E2E: Tool Installation Flow", () => {
138
138
  });
139
139
 
140
140
  test("installs markdown tool correctly", () => {
141
- const destBase = join(tempDir, ".enact", "tools");
141
+ const destBase = join(tempDir, "agents", "skills");
142
142
  const { manifest, destPath } = installTool(ECHO_TOOL, destBase);
143
143
 
144
144
  expect(manifest.name).toBe("test/echo-tool");
@@ -146,7 +146,7 @@ describe("E2E: Tool Installation Flow", () => {
146
146
  });
147
147
 
148
148
  test("installs multiple tools without conflict", () => {
149
- const destBase = join(tempDir, ".enact", "tools");
149
+ const destBase = join(tempDir, "agents", "skills");
150
150
 
151
151
  const result1 = installTool(GREETER_TOOL, destBase);
152
152
  const result2 = installTool(ECHO_TOOL, destBase);
@@ -163,7 +163,7 @@ describe("E2E: Tool Installation Flow", () => {
163
163
  });
164
164
 
165
165
  test("overwrites existing tool on reinstall", () => {
166
- const destBase = join(tempDir, ".enact", "tools");
166
+ const destBase = join(tempDir, "agents", "skills");
167
167
 
168
168
  // First install
169
169
  const result1 = installTool(GREETER_TOOL, destBase);
@@ -192,7 +192,7 @@ describe("E2E: Tool Resolution Flow", () => {
192
192
  mkdirSync(resolveTempDir, { recursive: true });
193
193
 
194
194
  // Install tools
195
- const destBase = join(resolveTempDir, ".enact", "tools");
195
+ const destBase = join(resolveTempDir, "agents", "skills");
196
196
  installTool(GREETER_TOOL, destBase);
197
197
  installTool(ECHO_TOOL, destBase);
198
198
  installTool(CALCULATOR_TOOL, destBase);
@@ -212,7 +212,7 @@ describe("E2E: Tool Resolution Flow", () => {
212
212
 
213
213
  test("resolves tool by path", () => {
214
214
  // Resolve from installed location
215
- const toolPath = join(resolveTempDir, ".enact", "tools", "test", "greeter");
215
+ const toolPath = join(resolveTempDir, "agents", "skills", "test", "greeter");
216
216
  const resolution = tryResolveTool(toolPath);
217
217
  expect(resolution).not.toBeNull();
218
218
  expect(resolution?.manifest.name).toBe("test/greeter");
@@ -483,7 +483,7 @@ describe("E2E: Full Workflow", () => {
483
483
 
484
484
  test("complete install -> resolve -> validate -> prepare flow (scripts)", () => {
485
485
  // 1. Install tool
486
- const destBase = join(tempDir, ".enact", "tools");
486
+ const destBase = join(tempDir, "agents", "skills");
487
487
  const { manifest } = installTool(GREETER_TOOL, destBase);
488
488
  expect(manifest.name).toBe("test/greeter");
489
489
 
@@ -509,7 +509,7 @@ describe("E2E: Full Workflow", () => {
509
509
 
510
510
  test("complete calculator workflow (scripts)", () => {
511
511
  // 1. Install tool
512
- const destBase = join(tempDir, ".enact", "tools");
512
+ const destBase = join(tempDir, "agents", "skills");
513
513
  const { manifest } = installTool(CALCULATOR_TOOL, destBase);
514
514
 
515
515
  // 2. Resolve tool
@@ -544,7 +544,7 @@ describe("E2E: Full Workflow", () => {
544
544
 
545
545
  test("handles markdown tool workflow (scripts)", () => {
546
546
  // Install markdown-based tool
547
- const destBase = join(tempDir, ".enact", "tools");
547
+ const destBase = join(tempDir, "agents", "skills");
548
548
  const { manifest } = installTool(ECHO_TOOL, destBase);
549
549
  expect(manifest.name).toBe("test/echo-tool");
550
550