@enactprotocol/cli 2.2.4 → 2.3.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 (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 +47 -4
  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 +54 -0
  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 +142 -41
  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 +77 -4
  42. package/src/commands/learn/index.ts +67 -0
  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 +195 -48
  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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AA+BH,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAgCH,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -7,9 +7,9 @@
7
7
  */
8
8
  import { ensureGlobalSetup } from "@enactprotocol/shared";
9
9
  import { Command } from "commander";
10
- import { configureAuthCommand, configureCacheCommand, configureConfigCommand, configureEnvCommand, configureExecCommand, configureInfoCommand, configureInitCommand, configureInspectCommand, configureInstallCommand, configureLearnCommand, configureListCommand, configureMcpCommand, configurePublishCommand, configureReportCommand, configureRunCommand, configureSearchCommand, configureSetupCommand, configureSignCommand, configureTrustCommand, configureUnyankCommand, configureValidateCommand, configureVisibilityCommand, configureYankCommand, } from "./commands";
10
+ import { configureAuthCommand, configureCacheCommand, configureConfigCommand, configureEnvCommand, configureExecCommand, configureInfoCommand, configureInitCommand, configureInspectCommand, configureInstallCommand, configureLearnCommand, configureListCommand, configureMcpCommand, configurePublishCommand, configureReportCommand, configureRunCommand, configureSearchCommand, configureServeCommand, configureSetupCommand, configureSignCommand, configureTrustCommand, configureUnyankCommand, configureValidateCommand, configureVisibilityCommand, configureYankCommand, } from "./commands";
11
11
  import { error, formatError } from "./utils";
12
- export const version = "2.2.4";
12
+ export const version = "2.3.1";
13
13
  // Main CLI entry point
14
14
  async function main() {
15
15
  // Ensure global setup is complete on first run
@@ -49,6 +49,8 @@ async function main() {
49
49
  configureMcpCommand(program);
50
50
  // Validation command
51
51
  configureValidateCommand(program);
52
+ // Self-hosted registry
53
+ configureServeCommand(program);
52
54
  // Global error handler - handle Commander's help/version exits gracefully
53
55
  program.exitOverride((err) => {
54
56
  // Commander throws errors for help, version, and other "exit" scenarios
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -47,7 +47,7 @@ export class ToolNotFoundError extends CliError {
47
47
  export class ManifestError extends CliError {
48
48
  constructor(message, path) {
49
49
  const fullMessage = path ? `${message} in ${path}` : message;
50
- super(fullMessage, EXIT_MANIFEST_ERROR, "Ensure the directory contains a valid enact.yaml or enact.md file.");
50
+ super(fullMessage, EXIT_MANIFEST_ERROR, "Ensure the directory contains a valid skill.yaml or SKILL.md file.");
51
51
  this.name = "ManifestError";
52
52
  }
53
53
  }
@@ -288,7 +288,7 @@ export const ErrorMessages = {
288
288
  message: `No manifest found in ${dir}`,
289
289
  suggestions: [
290
290
  `Create a manifest: ${colors.command("enact init")}`,
291
- "Ensure the directory contains enact.yaml or enact.md",
291
+ "Ensure the directory contains skill.yaml or SKILL.md",
292
292
  ],
293
293
  }),
294
294
  invalidManifest: (errors) => ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enactprotocol/cli",
3
- "version": "2.2.4",
3
+ "version": "2.3.1",
4
4
  "description": "Command-line interface for Enact - the npm for AI tools",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -34,10 +34,11 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@clack/prompts": "^0.11.0",
37
- "@enactprotocol/api": "2.2.4",
38
- "@enactprotocol/execution": "2.2.4",
39
- "@enactprotocol/secrets": "2.2.4",
40
- "@enactprotocol/shared": "2.2.4",
37
+ "@enactprotocol/api": "2.3.1",
38
+ "@enactprotocol/execution": "2.3.1",
39
+ "@enactprotocol/registry": "2.3.1",
40
+ "@enactprotocol/secrets": "2.3.1",
41
+ "@enactprotocol/shared": "2.3.1",
41
42
  "commander": "^12.1.0",
42
43
  "picocolors": "^1.1.1"
43
44
  },
@@ -6,7 +6,7 @@
6
6
 
7
7
  import { existsSync, readdirSync, rmSync, statSync } from "node:fs";
8
8
  import { join } from "node:path";
9
- import { getCacheDir, tryLoadManifestFromDir } from "@enactprotocol/shared";
9
+ import { getSkillsDir, tryLoadManifestFromDir } from "@enactprotocol/shared";
10
10
  import type { Command } from "commander";
11
11
  import type { CommandContext, GlobalOptions } from "../../types";
12
12
  import {
@@ -114,7 +114,7 @@ function listCachedTools(cacheDir: string): CachedTool[] {
114
114
  * Cache list handler
115
115
  */
116
116
  async function listHandler(options: CacheOptions, _ctx: CommandContext): Promise<void> {
117
- const cacheDir = getCacheDir();
117
+ const cacheDir = getSkillsDir();
118
118
  const tools = listCachedTools(cacheDir);
119
119
 
120
120
  if (options.json) {
@@ -165,7 +165,7 @@ async function listHandler(options: CacheOptions, _ctx: CommandContext): Promise
165
165
  * Cache clean handler - remove old/unused tools
166
166
  */
167
167
  async function cleanHandler(options: CacheOptions, ctx: CommandContext): Promise<void> {
168
- const cacheDir = getCacheDir();
168
+ const cacheDir = getSkillsDir();
169
169
  const tools = listCachedTools(cacheDir);
170
170
 
171
171
  if (tools.length === 0) {
@@ -207,7 +207,7 @@ async function cleanHandler(options: CacheOptions, ctx: CommandContext): Promise
207
207
  * Cache clear handler - remove entire cache
208
208
  */
209
209
  async function clearHandler(options: CacheOptions, ctx: CommandContext): Promise<void> {
210
- const cacheDir = getCacheDir();
210
+ const cacheDir = getSkillsDir();
211
211
 
212
212
  if (!existsSync(cacheDir)) {
213
213
  info("Cache directory does not exist.");
@@ -243,7 +243,7 @@ async function clearHandler(options: CacheOptions, ctx: CommandContext): Promise
243
243
  * Cache info handler
244
244
  */
245
245
  async function infoHandler(options: CacheOptions, _ctx: CommandContext): Promise<void> {
246
- const cacheDir = getCacheDir();
246
+ const cacheDir = getSkillsDir();
247
247
  const exists = existsSync(cacheDir);
248
248
  const tools = exists ? listCachedTools(cacheDir) : [];
249
249
  const size = exists ? getDirSize(cacheDir) : 0;
@@ -139,7 +139,7 @@ When a tool runs, environment variables are resolved in this order:
139
139
 
140
140
  1. **Local** - `.enact/.env` in the project directory
141
141
  2. **Global** - `~/.enact/.env`
142
- 3. **Manifest defaults** - Default values from `enact.yaml`
142
+ 3. **Manifest defaults** - Default values from `skill.yaml`
143
143
 
144
144
  ## Secret Namespaces
145
145
 
@@ -38,3 +38,6 @@ export { configureMcpCommand } from "./mcp";
38
38
 
39
39
  // Validation command
40
40
  export { configureValidateCommand } from "./validate";
41
+
42
+ // Self-hosted registry
43
+ export { configureServeCommand } from "./serve";
@@ -9,7 +9,7 @@
9
9
  import { mkdirSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
10
10
  import { dirname, join, resolve } from "node:path";
11
11
  import { createApiClient, downloadBundle, getToolInfo } from "@enactprotocol/api";
12
- import { getCacheDir, loadConfig, pathExists } from "@enactprotocol/shared";
12
+ import { loadConfig, pathExists } from "@enactprotocol/shared";
13
13
  import type { Command } from "commander";
14
14
  import type { CommandContext, GlobalOptions } from "../../types";
15
15
  import {
@@ -65,7 +65,8 @@ function formatBytes(bytes: number): string {
65
65
  * Extract a tar.gz bundle to a directory
66
66
  */
67
67
  async function extractBundle(bundleData: ArrayBuffer, destPath: string): Promise<void> {
68
- const tempFile = join(getCacheDir(), `inspect-${Date.now()}.tar.gz`);
68
+ const { tmpdir } = await import("node:os");
69
+ const tempFile = join(tmpdir(), `enact-inspect-${Date.now()}.tar.gz`);
69
70
  mkdirSync(dirname(tempFile), { recursive: true });
70
71
  writeFileSync(tempFile, Buffer.from(bundleData));
71
72
 
@@ -96,7 +96,7 @@ When installing by name, the command searches for the tool in this order:
96
96
 
97
97
  1. Project tools (`.enact/tools/`)
98
98
  2. User tools (`~/.enact/tools/`)
99
- 3. Cache (`~/.enact/cache/`)
99
+ 3. Skills directory (`~/.agent/skills/`)
100
100
  4. Registry (future)
101
101
 
102
102
  ## Directory Structure
@@ -112,7 +112,7 @@ After installation, tools are organized by their namespaced name:
112
112
  │ └── ...
113
113
  └── EnactProtocol/
114
114
  └── pdf-extract/
115
- ├── enact.yaml
115
+ ├── skill.yaml
116
116
  └── ...
117
117
  ```
118
118
 
@@ -2,7 +2,7 @@
2
2
  * enact install command
3
3
  *
4
4
  * Install a tool to the project or globally.
5
- * All tools are extracted to ~/.enact/cache/{tool}/{version}/
5
+ * All tools are extracted to ~/.agent/skills/{tool}/
6
6
  * - Project install: Adds entry to .enact/tools.json
7
7
  * - Global install: Adds entry to ~/.enact/tools.json
8
8
  *
@@ -25,7 +25,6 @@ import {
25
25
  addAlias,
26
26
  addMcpTool,
27
27
  addToolToRegistry,
28
- getCacheDir,
29
28
  getInstalledVersion,
30
29
  getMinimumAttestations,
31
30
  getProjectEnactDir,
@@ -110,7 +109,8 @@ function isLocalPath(toolName: string): boolean {
110
109
  */
111
110
  async function extractBundle(bundleData: ArrayBuffer, destPath: string): Promise<void> {
112
111
  // Create a temporary file for the bundle
113
- const tempFile = join(getCacheDir(), `bundle-${Date.now()}.tar.gz`);
112
+ const { tmpdir } = await import("node:os");
113
+ const tempFile = join(tmpdir(), `enact-bundle-${Date.now()}.tar.gz`);
114
114
  mkdirSync(dirname(tempFile), { recursive: true });
115
115
  writeFileSync(tempFile, Buffer.from(bundleData));
116
116
 
@@ -149,6 +149,40 @@ function formatBytes(bytes: number): string {
149
149
  return `${(bytes / k ** i).toFixed(1)} ${sizes[i]}`;
150
150
  }
151
151
 
152
+ /**
153
+ * Run postinstall hook commands in the tool directory.
154
+ * Runs each command sequentially; throws on first failure.
155
+ */
156
+ async function runPostinstallHook(
157
+ toolDir: string,
158
+ hookCommands: string | string[],
159
+ _toolName: string,
160
+ verbose?: boolean
161
+ ): Promise<void> {
162
+ const commands = Array.isArray(hookCommands) ? hookCommands : [hookCommands];
163
+
164
+ for (const cmd of commands) {
165
+ if (verbose) {
166
+ dim(` Running: ${cmd}`);
167
+ }
168
+
169
+ const proc = Bun.spawn(["sh", "-c", cmd], {
170
+ cwd: toolDir,
171
+ stdout: verbose ? "inherit" : "pipe",
172
+ stderr: "pipe",
173
+ env: { ...process.env },
174
+ });
175
+
176
+ const exitCode = await proc.exited;
177
+ if (exitCode !== 0) {
178
+ const stderr = await new Response(proc.stderr).text();
179
+ throw new Error(
180
+ `postinstall hook failed (exit ${exitCode}): ${cmd}${stderr ? `\n${stderr.trim()}` : ""}`
181
+ );
182
+ }
183
+ }
184
+ }
185
+
152
186
  /**
153
187
  * Install from the registry
154
188
  */
@@ -438,6 +472,26 @@ async function installFromRegistry(
438
472
  throw new RegistryError(`Failed to extract bundle: ${formatError(err)}`);
439
473
  }
440
474
 
475
+ // Run postinstall hook if the manifest defines one
476
+ const extractedManifest = loadManifestFromDir(cachePath);
477
+ if (extractedManifest?.manifest.hooks?.postinstall) {
478
+ try {
479
+ await withSpinner(
480
+ "Running postinstall hook...",
481
+ async () =>
482
+ runPostinstallHook(
483
+ cachePath,
484
+ extractedManifest.manifest.hooks!.postinstall!,
485
+ toolName,
486
+ options.verbose
487
+ ),
488
+ `${symbols.success} postinstall complete`
489
+ );
490
+ } catch (err) {
491
+ info(`${symbols.warning} postinstall hook failed: ${formatError(err)}`);
492
+ }
493
+ }
494
+
441
495
  // Update tools.json for the appropriate scope
442
496
  addToolToRegistry(toolName, targetVersion!, scope, isGlobal ? undefined : ctx.cwd);
443
497
 
@@ -485,7 +539,7 @@ async function installFromRegistry(
485
539
  * Install from a local path
486
540
  *
487
541
  * Both global and project installs:
488
- * 1. Copy tool to cache (~/.enact/cache/{tool}/{version}/)
542
+ * 1. Copy tool to ~/.agent/skills/{tool}/
489
543
  * 2. Update tools.json (global: ~/.enact/tools.json, project: .enact/tools.json)
490
544
  */
491
545
  async function installFromPath(
@@ -547,6 +601,25 @@ async function installFromPath(
547
601
  `${symbols.success} Installed ${manifest.name}`
548
602
  );
549
603
 
604
+ // Run postinstall hook if the manifest defines one
605
+ if (manifest.hooks?.postinstall) {
606
+ try {
607
+ await withSpinner(
608
+ "Running postinstall hook...",
609
+ async () =>
610
+ runPostinstallHook(
611
+ cachePath,
612
+ manifest.hooks!.postinstall!,
613
+ manifest.name,
614
+ options.verbose
615
+ ),
616
+ `${symbols.success} postinstall complete`
617
+ );
618
+ } catch (err) {
619
+ info(`${symbols.warning} postinstall hook failed: ${formatError(err)}`);
620
+ }
621
+ }
622
+
550
623
  // Update tools.json for the appropriate scope
551
624
  addToolToRegistry(manifest.name, version, scope, isGlobal ? undefined : ctx.cwd);
552
625
 
@@ -18,6 +18,7 @@ import {
18
18
  verifyAllAttestations,
19
19
  } from "@enactprotocol/api";
20
20
  import {
21
+ type ActionsManifest,
21
22
  getMinimumAttestations,
22
23
  getTrustPolicy,
23
24
  getTrustedAuditors,
@@ -45,6 +46,48 @@ interface LearnOptions extends GlobalOptions {
45
46
  local?: boolean;
46
47
  }
47
48
 
49
+ /**
50
+ * Display available actions from an ActionsManifest
51
+ */
52
+ function displayActions(actionsManifest: ActionsManifest): void {
53
+ newline();
54
+ header("Available Actions");
55
+ newline();
56
+
57
+ // Iterate over action map (name is the key)
58
+ for (const [actionName, action] of Object.entries(actionsManifest.actions)) {
59
+ info(` ${actionName}`);
60
+ if (action.description) {
61
+ dim(` ${action.description}`);
62
+ }
63
+
64
+ // Show input parameters
65
+ if (action.inputSchema?.properties) {
66
+ const required = new Set(
67
+ Array.isArray(action.inputSchema.required) ? action.inputSchema.required : []
68
+ );
69
+ const props = action.inputSchema.properties as Record<
70
+ string,
71
+ { type?: string; description?: string }
72
+ >;
73
+ const paramNames = Object.keys(props);
74
+
75
+ if (paramNames.length > 0) {
76
+ dim(" Parameters:");
77
+ for (const paramName of paramNames) {
78
+ const prop = props[paramName];
79
+ const isRequired = required.has(paramName);
80
+ const reqLabel = isRequired ? " (required)" : "";
81
+ dim(` - ${paramName}: ${prop?.type ?? "any"}${reqLabel}`);
82
+ }
83
+ }
84
+ }
85
+ newline();
86
+ }
87
+
88
+ dim("Run an action with: enact run <skill>:<action> --args '{...}'");
89
+ }
90
+
48
91
  /**
49
92
  * Learn command handler
50
93
  */
@@ -69,6 +112,13 @@ async function learnHandler(
69
112
  version: resolution.manifest.version,
70
113
  documentation: content,
71
114
  source: "local",
115
+ actions: resolution.actionsManifest
116
+ ? Object.entries(resolution.actionsManifest.actions).map(([name, a]) => ({
117
+ name,
118
+ description: a.description,
119
+ inputSchema: a.inputSchema,
120
+ }))
121
+ : null,
72
122
  });
73
123
  return;
74
124
  }
@@ -77,6 +127,11 @@ async function learnHandler(
77
127
  dim("(installed locally)");
78
128
  newline();
79
129
  console.log(content);
130
+
131
+ // Display actions if available
132
+ if (resolution.actionsManifest) {
133
+ displayActions(resolution.actionsManifest);
134
+ }
80
135
  return;
81
136
  }
82
137
 
@@ -87,6 +142,13 @@ async function learnHandler(
87
142
  version: resolution.manifest.version,
88
143
  documentation: resolution.manifest.doc ?? resolution.manifest.description ?? null,
89
144
  source: "local",
145
+ actions: resolution.actionsManifest
146
+ ? Object.entries(resolution.actionsManifest.actions).map(([name, a]) => ({
147
+ name,
148
+ description: a.description,
149
+ inputSchema: a.inputSchema,
150
+ }))
151
+ : null,
90
152
  });
91
153
  return;
92
154
  }
@@ -97,6 +159,11 @@ async function learnHandler(
97
159
  console.log(
98
160
  resolution.manifest.doc ?? resolution.manifest.description ?? "No documentation available."
99
161
  );
162
+
163
+ // Display actions if available
164
+ if (resolution.actionsManifest) {
165
+ displayActions(resolution.actionsManifest);
166
+ }
100
167
  return;
101
168
  }
102
169
 
@@ -5,7 +5,7 @@
5
5
  * - Default: project tools (via .enact/tools.json)
6
6
  * - --global/-g: global tools (via ~/.enact/tools.json)
7
7
  *
8
- * All tools are stored in ~/.enact/cache/{tool}/{version}/
8
+ * All tools are stored in ~/.agent/skills/{tool}/
9
9
  */
10
10
 
11
11
  import {
@@ -10,7 +10,7 @@ enact run <tool> [options]
10
10
 
11
11
  ## Description
12
12
 
13
- The `run` command executes a tool using the command defined in its manifest (`enact.yaml` or `enact.md`). The tool runs in an isolated container environment with:
13
+ The `run` command executes a tool using the command defined in its manifest (`skill.yaml` or `SKILL.md`). The tool runs in an isolated container environment with:
14
14
 
15
15
  - Input validation against the tool's JSON Schema
16
16
  - Automatic secret resolution from the OS keyring