@enactprotocol/cli 2.1.5 → 2.1.7
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.
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +1 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +100 -58
- package/dist/commands/init/index.js.map +1 -1
- package/dist/commands/learn/index.d.ts +12 -0
- package/dist/commands/learn/index.d.ts.map +1 -0
- package/dist/commands/learn/index.js +90 -0
- package/dist/commands/learn/index.js.map +1 -0
- package/dist/commands/run/index.d.ts.map +1 -1
- package/dist/commands/run/index.js +36 -6
- package/dist/commands/run/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/commands/index.ts +1 -0
- package/src/commands/init/index.ts +112 -62
- package/src/commands/learn/index.ts +107 -0
- package/src/commands/run/index.ts +39 -5
- package/src/index.ts +4 -2
- package/tests/commands/init.test.ts +199 -12
- package/tests/commands/learn.test.ts +231 -0
- package/tests/commands/run.test.ts +70 -1
- package/tsconfig.tsbuildinfo +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAK/B,uBAAuB;AACvB,KAAK,UAAU,IAAI;IACjB,+CAA+C;IAC/C,iBAAiB,EAAE,CAAC;IAEpB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,OAAO,CAAC;SACb,WAAW,CAAC,6DAA6D,CAAC;SAC1E,OAAO,CAAC,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enactprotocol/cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.7",
|
|
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,10 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@clack/prompts": "^0.11.0",
|
|
37
|
-
"@enactprotocol/api": "2.1.
|
|
38
|
-
"@enactprotocol/execution": "2.1.
|
|
39
|
-
"@enactprotocol/secrets": "2.1.
|
|
40
|
-
"@enactprotocol/shared": "2.1.
|
|
37
|
+
"@enactprotocol/api": "2.1.7",
|
|
38
|
+
"@enactprotocol/execution": "2.1.7",
|
|
39
|
+
"@enactprotocol/secrets": "2.1.7",
|
|
40
|
+
"@enactprotocol/shared": "2.1.7",
|
|
41
41
|
"commander": "^12.1.0",
|
|
42
42
|
"picocolors": "^1.1.1"
|
|
43
43
|
},
|
package/src/commands/index.ts
CHANGED
|
@@ -17,6 +17,7 @@ export { configureConfigCommand } from "./config";
|
|
|
17
17
|
// Registry commands (Phase 8)
|
|
18
18
|
export { configureSearchCommand } from "./search";
|
|
19
19
|
export { configureGetCommand } from "./get";
|
|
20
|
+
export { configureLearnCommand } from "./learn";
|
|
20
21
|
export { configurePublishCommand } from "./publish";
|
|
21
22
|
export { configureAuthCommand } from "./auth";
|
|
22
23
|
export { configureCacheCommand } from "./cache";
|
|
@@ -80,8 +80,8 @@ Enact tools are containerized, cryptographically-signed executables. Each tool i
|
|
|
80
80
|
|
|
81
81
|
| Task | Command |
|
|
82
82
|
|------|---------|
|
|
83
|
-
| Run local tool | \`enact run ./ --input "key=value"\` |
|
|
84
83
|
| Run with JSON | \`enact run ./ --args '{"key": "value"}'\` |
|
|
84
|
+
| Run from file | \`enact run ./ --input-file inputs.json\` |
|
|
85
85
|
| Dry run | \`enact run ./ --args '{}' --dry-run\` |
|
|
86
86
|
| Sign & publish | \`enact sign ./ && enact publish ./\` |
|
|
87
87
|
|
|
@@ -149,6 +149,20 @@ command: python /work/main.py "\${input}"
|
|
|
149
149
|
command: python /work/main.py \${input}
|
|
150
150
|
\`\`\`
|
|
151
151
|
|
|
152
|
+
**Optional params:** Missing optional params become empty strings. Always provide defaults:
|
|
153
|
+
\`\`\`yaml
|
|
154
|
+
inputSchema:
|
|
155
|
+
properties:
|
|
156
|
+
greeting:
|
|
157
|
+
type: string
|
|
158
|
+
default: "Hello" # Recommended for optional params
|
|
159
|
+
\`\`\`
|
|
160
|
+
|
|
161
|
+
Or handle empty in shell:
|
|
162
|
+
\`\`\`yaml
|
|
163
|
+
command: "echo \${greeting:-Hello} \${name}"
|
|
164
|
+
\`\`\`
|
|
165
|
+
|
|
152
166
|
Modifiers:
|
|
153
167
|
- \`\${param}\` — auto-quoted (handles spaces, JSON, special chars)
|
|
154
168
|
- \`\${param:raw}\` — raw, no quoting (use carefully)
|
|
@@ -268,9 +282,9 @@ Return JSON: {"issues": [...], "score": 75}
|
|
|
268
282
|
## Troubleshooting
|
|
269
283
|
|
|
270
284
|
\`\`\`bash
|
|
271
|
-
enact run ./ --
|
|
272
|
-
enact run ./ --args '{}' --dry-run
|
|
273
|
-
enact list
|
|
285
|
+
enact run ./ --args '{"x": "y"}' --verbose # Verbose output
|
|
286
|
+
enact run ./ --args '{}' --dry-run # Preview command
|
|
287
|
+
enact list # List installed tools
|
|
274
288
|
\`\`\`
|
|
275
289
|
`,
|
|
276
290
|
|
|
@@ -416,6 +430,30 @@ function loadTemplate(templateName: string, replacements: Record<string, string>
|
|
|
416
430
|
return content;
|
|
417
431
|
}
|
|
418
432
|
|
|
433
|
+
/**
|
|
434
|
+
* Create .enact/tools.json for project tool tracking
|
|
435
|
+
*/
|
|
436
|
+
function createEnactProjectDir(targetDir: string, force: boolean): boolean {
|
|
437
|
+
const enactDir = join(targetDir, ".enact");
|
|
438
|
+
const toolsJsonPath = join(enactDir, "tools.json");
|
|
439
|
+
|
|
440
|
+
// Check if tools.json already exists
|
|
441
|
+
if (existsSync(toolsJsonPath) && !force) {
|
|
442
|
+
info(".enact/tools.json already exists, skipping");
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Create .enact directory if it doesn't exist
|
|
447
|
+
if (!existsSync(enactDir)) {
|
|
448
|
+
mkdirSync(enactDir, { recursive: true });
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Write empty tools.json
|
|
452
|
+
const toolsJson = { tools: {} };
|
|
453
|
+
writeFileSync(toolsJsonPath, `${JSON.stringify(toolsJson, null, 2)}\n`, "utf-8");
|
|
454
|
+
return true;
|
|
455
|
+
}
|
|
456
|
+
|
|
419
457
|
/**
|
|
420
458
|
* Get the current logged-in username
|
|
421
459
|
*/
|
|
@@ -500,24 +538,64 @@ async function getCurrentUsername(): Promise<string | null> {
|
|
|
500
538
|
async function initHandler(options: InitOptions, ctx: CommandContext): Promise<void> {
|
|
501
539
|
const targetDir = ctx.cwd;
|
|
502
540
|
|
|
503
|
-
// Determine mode: --
|
|
504
|
-
const
|
|
541
|
+
// Determine mode: --tool, --claude, or --agent (default)
|
|
542
|
+
const isToolMode = options.tool;
|
|
505
543
|
const isClaudeMode = options.claude;
|
|
506
|
-
// Default to
|
|
544
|
+
// Default to agent mode if no flag specified
|
|
507
545
|
|
|
508
|
-
// Handle --
|
|
509
|
-
if (
|
|
546
|
+
// Handle --tool mode: create enact.md + AGENTS.md for tool development
|
|
547
|
+
if (isToolMode) {
|
|
548
|
+
const manifestPath = join(targetDir, "enact.md");
|
|
510
549
|
const agentsPath = join(targetDir, "AGENTS.md");
|
|
511
|
-
|
|
512
|
-
|
|
550
|
+
|
|
551
|
+
if (existsSync(manifestPath) && !options.force) {
|
|
552
|
+
warning(`Tool manifest already exists at: ${manifestPath}`);
|
|
513
553
|
info("Use --force to overwrite");
|
|
514
554
|
return;
|
|
515
555
|
}
|
|
516
|
-
|
|
517
|
-
|
|
556
|
+
|
|
557
|
+
// Get username for the tool name
|
|
558
|
+
let toolName = options.name;
|
|
559
|
+
|
|
560
|
+
if (!toolName) {
|
|
561
|
+
const username = await getCurrentUsername();
|
|
562
|
+
if (username) {
|
|
563
|
+
toolName = `${username}/my-tool`;
|
|
564
|
+
info(`Using logged-in username: ${username}`);
|
|
565
|
+
} else {
|
|
566
|
+
toolName = "my-tool";
|
|
567
|
+
info("Not logged in - using generic tool name");
|
|
568
|
+
info("Run 'enact auth login' to use your username in tool names");
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Load templates with placeholder replacement
|
|
573
|
+
const replacements = { TOOL_NAME: toolName };
|
|
574
|
+
const manifestContent = loadTemplate("tool-enact.md", replacements);
|
|
575
|
+
const agentsContent = loadTemplate("tool-agents.md", replacements);
|
|
576
|
+
|
|
577
|
+
// Ensure directory exists
|
|
578
|
+
if (!existsSync(targetDir)) {
|
|
579
|
+
mkdirSync(targetDir, { recursive: true });
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// Write enact.md
|
|
583
|
+
writeFileSync(manifestPath, manifestContent, "utf-8");
|
|
584
|
+
success(`Created tool manifest: ${manifestPath}`);
|
|
585
|
+
|
|
586
|
+
// Write AGENTS.md (only if it doesn't exist or --force is used)
|
|
587
|
+
if (!existsSync(agentsPath) || options.force) {
|
|
588
|
+
writeFileSync(agentsPath, agentsContent, "utf-8");
|
|
589
|
+
success(`Created AGENTS.md: ${agentsPath}`);
|
|
590
|
+
} else {
|
|
591
|
+
info("AGENTS.md already exists, skipping (use --force to overwrite)");
|
|
592
|
+
}
|
|
593
|
+
|
|
518
594
|
info("");
|
|
519
|
-
info("
|
|
520
|
-
info("
|
|
595
|
+
info("Next steps:");
|
|
596
|
+
info(" 1. Edit enact.md to customize your tool");
|
|
597
|
+
info(" 2. Run 'enact run ./' to test your tool");
|
|
598
|
+
info(" 3. Run 'enact publish' to share your tool");
|
|
521
599
|
return;
|
|
522
600
|
}
|
|
523
601
|
|
|
@@ -531,63 +609,35 @@ async function initHandler(options: InitOptions, ctx: CommandContext): Promise<v
|
|
|
531
609
|
}
|
|
532
610
|
writeFileSync(claudePath, loadTemplate("claude.md"), "utf-8");
|
|
533
611
|
success(`Created CLAUDE.md: ${claudePath}`);
|
|
612
|
+
|
|
613
|
+
// Create .enact/tools.json
|
|
614
|
+
if (createEnactProjectDir(targetDir, options.force ?? false)) {
|
|
615
|
+
success("Created .enact/tools.json");
|
|
616
|
+
}
|
|
617
|
+
|
|
534
618
|
info("");
|
|
535
619
|
info("This file helps Claude understand how to use Enact tools in your project.");
|
|
536
620
|
return;
|
|
537
621
|
}
|
|
538
622
|
|
|
539
|
-
// Handle
|
|
540
|
-
const manifestPath = join(targetDir, "enact.md");
|
|
623
|
+
// Handle default (agent) mode: create AGENTS.md for projects using Enact tools
|
|
541
624
|
const agentsPath = join(targetDir, "AGENTS.md");
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
warning(`Tool manifest already exists at: ${manifestPath}`);
|
|
625
|
+
if (existsSync(agentsPath) && !options.force) {
|
|
626
|
+
warning(`AGENTS.md already exists at: ${agentsPath}`);
|
|
545
627
|
info("Use --force to overwrite");
|
|
546
628
|
return;
|
|
547
629
|
}
|
|
630
|
+
writeFileSync(agentsPath, loadTemplate("agent-agents.md"), "utf-8");
|
|
631
|
+
success(`Created AGENTS.md: ${agentsPath}`);
|
|
548
632
|
|
|
549
|
-
//
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
if (!toolName) {
|
|
553
|
-
const username = await getCurrentUsername();
|
|
554
|
-
if (username) {
|
|
555
|
-
toolName = `${username}/my-tool`;
|
|
556
|
-
info(`Using logged-in username: ${username}`);
|
|
557
|
-
} else {
|
|
558
|
-
toolName = "my-tool";
|
|
559
|
-
info("Not logged in - using generic tool name");
|
|
560
|
-
info("Run 'enact auth login' to use your username in tool names");
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
// Load templates with placeholder replacement
|
|
565
|
-
const replacements = { TOOL_NAME: toolName };
|
|
566
|
-
const manifestContent = loadTemplate("tool-enact.md", replacements);
|
|
567
|
-
const agentsContent = loadTemplate("tool-agents.md", replacements);
|
|
568
|
-
|
|
569
|
-
// Ensure directory exists
|
|
570
|
-
if (!existsSync(targetDir)) {
|
|
571
|
-
mkdirSync(targetDir, { recursive: true });
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
// Write enact.md
|
|
575
|
-
writeFileSync(manifestPath, manifestContent, "utf-8");
|
|
576
|
-
success(`Created tool manifest: ${manifestPath}`);
|
|
577
|
-
|
|
578
|
-
// Write AGENTS.md (only if it doesn't exist or --force is used)
|
|
579
|
-
if (!existsSync(agentsPath) || options.force) {
|
|
580
|
-
writeFileSync(agentsPath, agentsContent, "utf-8");
|
|
581
|
-
success(`Created AGENTS.md: ${agentsPath}`);
|
|
582
|
-
} else {
|
|
583
|
-
info("AGENTS.md already exists, skipping (use --force to overwrite)");
|
|
633
|
+
// Create .enact/tools.json
|
|
634
|
+
if (createEnactProjectDir(targetDir, options.force ?? false)) {
|
|
635
|
+
success("Created .enact/tools.json");
|
|
584
636
|
}
|
|
585
637
|
|
|
586
638
|
info("");
|
|
587
|
-
info("
|
|
588
|
-
info("
|
|
589
|
-
info(" 2. Run 'enact run ./' to test your tool");
|
|
590
|
-
info(" 3. Run 'enact publish' to share your tool");
|
|
639
|
+
info("This file helps AI agents understand how to use Enact tools in your project.");
|
|
640
|
+
info("Run 'enact search <query>' to find tools, 'enact install <tool>' to add them.");
|
|
591
641
|
}
|
|
592
642
|
|
|
593
643
|
/**
|
|
@@ -599,9 +649,9 @@ export function configureInitCommand(program: Command): void {
|
|
|
599
649
|
.description("Initialize Enact in the current directory")
|
|
600
650
|
.option("-n, --name <name>", "Tool name (default: username/my-tool)")
|
|
601
651
|
.option("-f, --force", "Overwrite existing files")
|
|
602
|
-
.option("--tool", "Create a new Enact tool (
|
|
603
|
-
.option("--agent", "Create AGENTS.md
|
|
604
|
-
.option("--claude", "Create CLAUDE.md
|
|
652
|
+
.option("--tool", "Create a new Enact tool (enact.md + AGENTS.md)")
|
|
653
|
+
.option("--agent", "Create AGENTS.md + .enact/tools.json (default)")
|
|
654
|
+
.option("--claude", "Create CLAUDE.md + .enact/tools.json")
|
|
605
655
|
.option("-v, --verbose", "Show detailed output")
|
|
606
656
|
.action(async (options: InitOptions) => {
|
|
607
657
|
const ctx: CommandContext = {
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* enact learn command
|
|
3
|
+
*
|
|
4
|
+
* Display the documentation (enact.md) for a tool.
|
|
5
|
+
* Fetches and displays the raw manifest content for easy reading.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createApiClient, getToolInfo, getToolVersion } from "@enactprotocol/api";
|
|
9
|
+
import { loadConfig } from "@enactprotocol/shared";
|
|
10
|
+
import type { Command } from "commander";
|
|
11
|
+
import type { CommandContext, GlobalOptions } from "../../types";
|
|
12
|
+
import { dim, error, formatError, header, json, newline } from "../../utils";
|
|
13
|
+
|
|
14
|
+
interface LearnOptions extends GlobalOptions {
|
|
15
|
+
ver?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Learn command handler
|
|
20
|
+
*/
|
|
21
|
+
async function learnHandler(
|
|
22
|
+
toolName: string,
|
|
23
|
+
options: LearnOptions,
|
|
24
|
+
_ctx: CommandContext
|
|
25
|
+
): Promise<void> {
|
|
26
|
+
const config = loadConfig();
|
|
27
|
+
const registryUrl =
|
|
28
|
+
process.env.ENACT_REGISTRY_URL ??
|
|
29
|
+
config.registry?.url ??
|
|
30
|
+
"https://siikwkfgsmouioodghho.supabase.co/functions/v1";
|
|
31
|
+
const authToken = config.registry?.authToken;
|
|
32
|
+
const client = createApiClient({
|
|
33
|
+
baseUrl: registryUrl,
|
|
34
|
+
authToken: authToken,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
// Get the version to fetch - either specified or latest
|
|
39
|
+
let version = options.ver;
|
|
40
|
+
if (!version) {
|
|
41
|
+
const toolInfo = await getToolInfo(client, toolName);
|
|
42
|
+
version = toolInfo.latestVersion;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Get the version info which includes rawManifest
|
|
46
|
+
const versionInfo = await getToolVersion(client, toolName, version);
|
|
47
|
+
|
|
48
|
+
if (options.json) {
|
|
49
|
+
json({
|
|
50
|
+
name: toolName,
|
|
51
|
+
version: versionInfo.version,
|
|
52
|
+
documentation: versionInfo.rawManifest ?? null,
|
|
53
|
+
});
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!versionInfo.rawManifest) {
|
|
58
|
+
error(`No documentation found for ${toolName}@${version}`);
|
|
59
|
+
dim("This tool may not have an enact.md file.");
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Display the documentation
|
|
64
|
+
header(`${toolName}@${version}`);
|
|
65
|
+
newline();
|
|
66
|
+
console.log(versionInfo.rawManifest);
|
|
67
|
+
} catch (err) {
|
|
68
|
+
if (err instanceof Error) {
|
|
69
|
+
if (err.message.includes("not_found") || err.message.includes("404")) {
|
|
70
|
+
error(`Tool not found: ${toolName}`);
|
|
71
|
+
dim("Check the tool name or search with: enact search <query>");
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
if (err.message.includes("fetch")) {
|
|
75
|
+
error("Unable to connect to registry. Check your internet connection.");
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
throw err;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Configure the learn command
|
|
85
|
+
*/
|
|
86
|
+
export function configureLearnCommand(program: Command): void {
|
|
87
|
+
program
|
|
88
|
+
.command("learn <tool>")
|
|
89
|
+
.description("Display documentation (enact.md) for a tool")
|
|
90
|
+
.option("--ver <version>", "Show documentation for a specific version")
|
|
91
|
+
.option("--json", "Output as JSON")
|
|
92
|
+
.action(async (toolName: string, options: LearnOptions) => {
|
|
93
|
+
const ctx: CommandContext = {
|
|
94
|
+
cwd: process.cwd(),
|
|
95
|
+
options,
|
|
96
|
+
isCI: Boolean(process.env.CI),
|
|
97
|
+
isInteractive: process.stdout.isTTY ?? false,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
await learnHandler(toolName, options, ctx);
|
|
102
|
+
} catch (err) {
|
|
103
|
+
error(formatError(err));
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
@@ -61,6 +61,7 @@ import {
|
|
|
61
61
|
|
|
62
62
|
interface RunOptions extends GlobalOptions {
|
|
63
63
|
args?: string;
|
|
64
|
+
inputFile?: string;
|
|
64
65
|
input?: string[];
|
|
65
66
|
timeout?: string;
|
|
66
67
|
noCache?: boolean;
|
|
@@ -70,14 +71,46 @@ interface RunOptions extends GlobalOptions {
|
|
|
70
71
|
|
|
71
72
|
/**
|
|
72
73
|
* Parse input arguments from various formats
|
|
74
|
+
*
|
|
75
|
+
* Priority order (later sources override earlier):
|
|
76
|
+
* 1. --input-file (JSON file)
|
|
77
|
+
* 2. --args (inline JSON)
|
|
78
|
+
* 3. --input (key=value pairs)
|
|
79
|
+
*
|
|
80
|
+
* Recommended for agents: Use --args or --input-file with JSON
|
|
73
81
|
*/
|
|
74
82
|
function parseInputArgs(
|
|
75
83
|
argsJson: string | undefined,
|
|
84
|
+
inputFile: string | undefined,
|
|
76
85
|
inputFlags: string[] | undefined
|
|
77
86
|
): Record<string, unknown> {
|
|
78
87
|
const inputs: Record<string, unknown> = {};
|
|
79
88
|
|
|
80
|
-
// Parse --
|
|
89
|
+
// Parse --input-file JSON file (loaded first, can be overridden)
|
|
90
|
+
if (inputFile) {
|
|
91
|
+
try {
|
|
92
|
+
const { readFileSync, existsSync } = require("node:fs");
|
|
93
|
+
const { resolve } = require("node:path");
|
|
94
|
+
const filePath = resolve(inputFile);
|
|
95
|
+
|
|
96
|
+
if (!existsSync(filePath)) {
|
|
97
|
+
throw new Error(`Input file not found: ${inputFile}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const content = readFileSync(filePath, "utf-8");
|
|
101
|
+
const parsed = JSON.parse(content);
|
|
102
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
103
|
+
Object.assign(inputs, parsed);
|
|
104
|
+
}
|
|
105
|
+
} catch (err) {
|
|
106
|
+
if (err instanceof Error && err.message.startsWith("Input file not found")) {
|
|
107
|
+
throw err;
|
|
108
|
+
}
|
|
109
|
+
throw new Error(`Invalid JSON in input file: ${formatError(err)}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Parse --args JSON (overrides file)
|
|
81
114
|
if (argsJson) {
|
|
82
115
|
try {
|
|
83
116
|
const parsed = JSON.parse(argsJson);
|
|
@@ -89,7 +122,7 @@ function parseInputArgs(
|
|
|
89
122
|
}
|
|
90
123
|
}
|
|
91
124
|
|
|
92
|
-
// Parse --input key=value pairs
|
|
125
|
+
// Parse --input key=value pairs (overrides both)
|
|
93
126
|
if (inputFlags) {
|
|
94
127
|
for (const input of inputFlags) {
|
|
95
128
|
const eqIndex = input.indexOf("=");
|
|
@@ -501,7 +534,7 @@ async function runHandler(tool: string, options: RunOptions, ctx: CommandContext
|
|
|
501
534
|
const manifest = resolution.manifest;
|
|
502
535
|
|
|
503
536
|
// Parse inputs
|
|
504
|
-
const inputs = parseInputArgs(options.args, options.input);
|
|
537
|
+
const inputs = parseInputArgs(options.args, options.inputFile, options.input);
|
|
505
538
|
|
|
506
539
|
// Apply defaults from schema
|
|
507
540
|
const inputsWithDefaults = manifest.inputSchema
|
|
@@ -669,8 +702,9 @@ export function configureRunCommand(program: Command): void {
|
|
|
669
702
|
.command("run")
|
|
670
703
|
.description("Execute a tool with its manifest-defined command")
|
|
671
704
|
.argument("<tool>", "Tool to run (name, path, or '.' for current directory)")
|
|
672
|
-
.option("-a, --args <json>", "Input arguments as JSON")
|
|
673
|
-
.option("-
|
|
705
|
+
.option("-a, --args <json>", "Input arguments as JSON string (recommended)")
|
|
706
|
+
.option("-f, --input-file <path>", "Load input arguments from JSON file")
|
|
707
|
+
.option("-i, --input <key=value...>", "Input arguments as key=value pairs (simple values only)")
|
|
674
708
|
.option("-t, --timeout <duration>", "Execution timeout (e.g., 30s, 5m)")
|
|
675
709
|
.option("--no-cache", "Disable container caching")
|
|
676
710
|
.option("--local", "Only resolve from local sources")
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
configureInitCommand,
|
|
20
20
|
configureInspectCommand,
|
|
21
21
|
configureInstallCommand,
|
|
22
|
+
configureLearnCommand,
|
|
22
23
|
configureListCommand,
|
|
23
24
|
configurePublishCommand,
|
|
24
25
|
configureReportCommand,
|
|
@@ -32,7 +33,7 @@ import {
|
|
|
32
33
|
} from "./commands";
|
|
33
34
|
import { error, formatError } from "./utils";
|
|
34
35
|
|
|
35
|
-
export const version = "2.1.
|
|
36
|
+
export const version = "2.1.7";
|
|
36
37
|
|
|
37
38
|
// Export types for external use
|
|
38
39
|
export type { GlobalOptions, CommandContext } from "./types";
|
|
@@ -47,7 +48,7 @@ async function main() {
|
|
|
47
48
|
program
|
|
48
49
|
.name("enact")
|
|
49
50
|
.description("Enact - Verified, portable protocol for AI-executable tools")
|
|
50
|
-
.version(version);
|
|
51
|
+
.version(version, "-v, --version", "output the version number");
|
|
51
52
|
|
|
52
53
|
// Configure all commands
|
|
53
54
|
configureSetupCommand(program);
|
|
@@ -63,6 +64,7 @@ async function main() {
|
|
|
63
64
|
// Registry commands (Phase 8)
|
|
64
65
|
configureSearchCommand(program);
|
|
65
66
|
configureGetCommand(program);
|
|
67
|
+
configureLearnCommand(program);
|
|
66
68
|
configurePublishCommand(program);
|
|
67
69
|
configureAuthCommand(program);
|
|
68
70
|
configureCacheCommand(program);
|