@ekaone/json-cli 0.0.1 → 0.1.0

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Eka Prasetia <ekaone3033@gmail.com> (https://prasetia.me)
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eka Prasetia <ekaone3033@gmail.com> (https://prasetia.me)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
package/README.md CHANGED
@@ -1,21 +1,19 @@
1
1
  # json-cli
2
2
 
3
- > Under active development - not released yet
4
-
5
3
  AI-powered CLI task runner. Describe your goal in plain English — AI generates a validated JSON command plan — runner executes it step by step.
6
4
 
7
5
  ## Installation
8
6
 
9
7
  ```bash
10
- npm install @ekaone/json-cli
8
+ npm install -g @ekaone/json-cli
11
9
  ```
12
10
 
13
11
  ```bash
14
- pnpm install @ekaone/json-cli
12
+ pnpm install -g @ekaone/json-cli
15
13
  ```
16
14
 
17
15
  ```bash
18
- yarn install @ekaone/json-cli
16
+ yarn global add @ekaone/json-cli
19
17
  ```
20
18
 
21
19
  ## Usage
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/catalog.ts","../src/planner.ts","../src/runner.ts"],"sourcesContent":["/**\r\n * @file index.ts\r\n * @description Core entry point for @ekaone/json-cli.\r\n * @author Eka Prasetia\r\n * @website https://prasetia.me\r\n * @license MIT\r\n */\r\n\r\nexport { generatePlan } from \"./planner.js\";\r\nexport { runPlan } from \"./runner.js\";\r\nexport type { Plan, Step } from \"./catalog.js\";\r\nexport type { AIProvider } from \"./providers/types.js\";\r\n","import { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Allowed commands per type — the whitelist that prevents hallucination\n// ---------------------------------------------------------------------------\nexport const CATALOG = {\n npm: [\"install\", \"run\", \"build\", \"test\", \"publish\", \"ci\"],\n pnpm: [\"install\", \"run\", \"build\", \"test\", \"publish\", \"add\", \"remove\"],\n yarn: [\"install\", \"run\", \"build\", \"test\", \"publish\", \"add\", \"remove\"],\n bun: [\"install\", \"run\", \"build\", \"test\", \"publish\", \"add\", \"remove\"],\n git: [\"init\", \"add\", \"commit\", \"push\", \"pull\", \"clone\", \"status\", \"log\"],\n shell: [\"any\"], // escape hatch — always requires extra confirmation\n} as const;\n\nexport type CommandType = keyof typeof CATALOG;\n\n// ---------------------------------------------------------------------------\n// Zod schemas — Layer 2 defense against hallucinated output\n// ---------------------------------------------------------------------------\nexport const StepSchema = z.object({\n id: z.number(),\n type: z.enum([\"npm\", \"pnpm\", \"yarn\", \"bun\", \"git\", \"shell\"]),\n command: z.string(),\n args: z.array(z.string()).default([]),\n description: z.string(),\n cwd: z.string().optional(), // optional working directory override\n});\n\nexport const PlanSchema = z.object({\n goal: z.string(),\n steps: z.array(StepSchema).min(1).max(10),\n});\n\nexport type Step = z.infer<typeof StepSchema>;\nexport type Plan = z.infer<typeof PlanSchema>;\n\n// ---------------------------------------------------------------------------\n// Catalog validation — Layer 3: check command is in whitelist\n// ---------------------------------------------------------------------------\nexport function validateStep(step: Step): { valid: boolean; reason?: string } {\n const allowed = CATALOG[step.type];\n\n // shell type is always allowed but flagged for extra confirmation\n if (step.type === \"shell\") {\n return { valid: true };\n }\n\n if (!allowed.includes(step.command as never)) {\n return {\n valid: false,\n reason: `\"${step.command}\" is not an allowed command for type \"${step.type}\". Allowed: ${allowed.join(\", \")}`,\n };\n }\n\n return { valid: true };\n}\n\n// ---------------------------------------------------------------------------\n// Build the catalog string injected into AI system prompt\n// ---------------------------------------------------------------------------\nexport function buildCatalogPrompt(): string {\n const lines = Object.entries(CATALOG).map(([type, commands]) => {\n const list = commands[0] === \"any\" ? \"any shell command (use sparingly)\" : commands.join(\", \");\n return ` - ${type}: [${list}]`;\n });\n\n return `Allowed command types and commands:\\n${lines.join(\"\\n\")}`;\n}\n","import { buildCatalogPrompt, PlanSchema, validateStep } from \"./catalog.js\";\nimport type { AIProvider } from \"./providers/types.js\";\nimport type { Plan } from \"./catalog.js\";\n\n// ---------------------------------------------------------------------------\n// System prompt — constrains AI to only produce catalog-valid JSON\n// ---------------------------------------------------------------------------\nfunction buildSystemPrompt(): string {\n return `You are a CLI task planner. Given a user's goal, generate a JSON execution plan.\n\n${buildCatalogPrompt()}\n\nRules:\n- ONLY use command types and commands listed above\n- Prefer pnpm over npm unless the user specifies otherwise\n- Use \"shell\" type only when no other type fits\n- Keep steps minimal — don't add unnecessary steps\n- Each step must have a clear, short description\n\nRespond ONLY with valid JSON matching this exact shape, no markdown, no explanation:\n{\n \"goal\": \"string describing the overall goal\",\n \"steps\": [\n {\n \"id\": 1,\n \"type\": \"pnpm\",\n \"command\": \"run\",\n \"args\": [\"dev\"],\n \"description\": \"Start dev server\"\n }\n ]\n}`;\n}\n\n// ---------------------------------------------------------------------------\n// Main planner function\n// ---------------------------------------------------------------------------\nexport async function generatePlan(userPrompt: string, provider: AIProvider): Promise<Plan> {\n const raw = await provider.generate(userPrompt, buildSystemPrompt());\n\n // Strip markdown fences if any provider wraps output\n const cleaned = raw.replace(/```json|```/g, \"\").trim();\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(cleaned);\n } catch {\n throw new Error(`AI returned invalid JSON:\\n${cleaned}`);\n }\n\n // Layer 2: Zod shape validation\n const result = PlanSchema.safeParse(parsed);\n if (!result.success) {\n const issues = result.error.issues.map((i) => ` - ${i.path.join(\".\")}: ${i.message}`).join(\"\\n\");\n throw new Error(`Plan failed schema validation:\\n${issues}`);\n }\n\n // Layer 3: Catalog whitelist validation\n for (const step of result.data.steps) {\n const check = validateStep(step);\n if (!check.valid) {\n throw new Error(`Step ${step.id} failed catalog validation: ${check.reason}`);\n }\n }\n\n return result.data;\n}\n","import { execa } from \"execa\";\nimport type { Plan, Step } from \"./catalog.js\";\n\n// ---------------------------------------------------------------------------\n// Build the actual shell command from a Step\n// ---------------------------------------------------------------------------\nfunction resolveCommand(step: Step): { bin: string; args: string[] } {\n if (step.type === \"shell\") {\n // shell: command is the binary, args are the args\n return { bin: step.command, args: step.args };\n }\n\n // For npm/pnpm/yarn/bun/git: binary is the type, command + args follow\n return { bin: step.type, args: [step.command, ...step.args] };\n}\n\n// ---------------------------------------------------------------------------\n// Run a single step, streaming stdout/stderr live\n// ---------------------------------------------------------------------------\nexport async function runStep(step: Step): Promise<{ success: boolean; error?: string }> {\n const { bin, args } = resolveCommand(step);\n\n try {\n await execa(bin, args, {\n cwd: step.cwd ?? process.cwd(),\n stdout: \"inherit\", // stream directly to terminal\n stderr: \"inherit\",\n });\n return { success: true };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { success: false, error: message };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Run the full plan, stopping on first failure\n// ---------------------------------------------------------------------------\nexport async function runPlan(\n plan: Plan,\n onStep: (step: Step, index: number, total: number) => void\n): Promise<{ success: boolean; failedStep?: Step; error?: string }> {\n const total = plan.steps.length;\n\n for (let i = 0; i < total; i++) {\n const step = plan.steps[i];\n onStep(step, i, total);\n\n const result = await runStep(step);\n\n if (!result.success) {\n return { success: false, failedStep: step, error: result.error };\n }\n }\n\n return { success: true };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/catalog.ts","../src/planner.ts","../src/runner.ts"],"sourcesContent":["/**\n * @file index.ts\n * @description Core entry point for @ekaone/json-cli.\n * @author Eka Prasetia\n * @website https://prasetia.me\n * @license MIT\n */\n\nexport { generatePlan } from \"./planner.js\";\nexport { runPlan } from \"./runner.js\";\nexport type { Plan, Step } from \"./catalog.js\";\nexport type { AIProvider } from \"./providers/types.js\";\n","import { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Allowed commands per type — the whitelist that prevents hallucination\n// ---------------------------------------------------------------------------\nexport const CATALOG = {\n npm: [\"install\", \"run\", \"build\", \"test\", \"publish\", \"ci\"],\n pnpm: [\"install\", \"run\", \"build\", \"test\", \"publish\", \"add\", \"remove\"],\n yarn: [\"install\", \"run\", \"build\", \"test\", \"publish\", \"add\", \"remove\"],\n bun: [\"install\", \"run\", \"build\", \"test\", \"publish\", \"add\", \"remove\"],\n git: [\"init\", \"add\", \"commit\", \"push\", \"pull\", \"clone\", \"status\", \"log\"],\n shell: [\"any\"], // escape hatch — always requires extra confirmation\n} as const;\n\nexport type CommandType = keyof typeof CATALOG;\n\n// ---------------------------------------------------------------------------\n// Zod schemas — Layer 2 defense against hallucinated output\n// ---------------------------------------------------------------------------\nexport const StepSchema = z.object({\n id: z.number(),\n type: z.enum([\"npm\", \"pnpm\", \"yarn\", \"bun\", \"git\", \"shell\"]),\n command: z.string(),\n args: z.array(z.string()).default([]),\n description: z.string(),\n cwd: z.string().optional(), // optional working directory override\n});\n\nexport const PlanSchema = z.object({\n goal: z.string(),\n steps: z.array(StepSchema).min(1).max(10),\n});\n\nexport type Step = z.infer<typeof StepSchema>;\nexport type Plan = z.infer<typeof PlanSchema>;\n\n// ---------------------------------------------------------------------------\n// Catalog validation — Layer 3: check command is in whitelist\n// ---------------------------------------------------------------------------\nexport function validateStep(step: Step): { valid: boolean; reason?: string } {\n const allowed = CATALOG[step.type];\n\n // shell type is always allowed but flagged for extra confirmation\n if (step.type === \"shell\") {\n return { valid: true };\n }\n\n if (!allowed.includes(step.command as never)) {\n return {\n valid: false,\n reason: `\"${step.command}\" is not an allowed command for type \"${step.type}\". Allowed: ${allowed.join(\", \")}`,\n };\n }\n\n return { valid: true };\n}\n\n// ---------------------------------------------------------------------------\n// Build the catalog string injected into AI system prompt\n// ---------------------------------------------------------------------------\nexport function buildCatalogPrompt(): string {\n const lines = Object.entries(CATALOG).map(([type, commands]) => {\n const list = commands[0] === \"any\" ? \"any shell command (use sparingly)\" : commands.join(\", \");\n return ` - ${type}: [${list}]`;\n });\n\n return `Allowed command types and commands:\\n${lines.join(\"\\n\")}`;\n}\n","import { buildCatalogPrompt, PlanSchema, validateStep } from \"./catalog.js\";\nimport type { AIProvider } from \"./providers/types.js\";\nimport type { Plan } from \"./catalog.js\";\n\n// ---------------------------------------------------------------------------\n// System prompt — constrains AI to only produce catalog-valid JSON\n// ---------------------------------------------------------------------------\nfunction buildSystemPrompt(): string {\n return `You are a CLI task planner. Given a user's goal, generate a JSON execution plan.\n\n${buildCatalogPrompt()}\n\nRules:\n- ONLY use command types and commands listed above\n- Prefer pnpm over npm unless the user specifies otherwise\n- Use \"shell\" type only when no other type fits\n- Keep steps minimal — don't add unnecessary steps\n- Each step must have a clear, short description\n\nRespond ONLY with valid JSON matching this exact shape, no markdown, no explanation:\n{\n \"goal\": \"string describing the overall goal\",\n \"steps\": [\n {\n \"id\": 1,\n \"type\": \"pnpm\",\n \"command\": \"run\",\n \"args\": [\"dev\"],\n \"description\": \"Start dev server\"\n }\n ]\n}`;\n}\n\n// ---------------------------------------------------------------------------\n// Main planner function\n// ---------------------------------------------------------------------------\nexport async function generatePlan(userPrompt: string, provider: AIProvider): Promise<Plan> {\n const raw = await provider.generate(userPrompt, buildSystemPrompt());\n\n // Strip markdown fences if any provider wraps output\n const cleaned = raw.replace(/```json|```/g, \"\").trim();\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(cleaned);\n } catch {\n throw new Error(`AI returned invalid JSON:\\n${cleaned}`);\n }\n\n // Layer 2: Zod shape validation\n const result = PlanSchema.safeParse(parsed);\n if (!result.success) {\n const issues = result.error.issues.map((i) => ` - ${i.path.join(\".\")}: ${i.message}`).join(\"\\n\");\n throw new Error(`Plan failed schema validation:\\n${issues}`);\n }\n\n // Layer 3: Catalog whitelist validation\n for (const step of result.data.steps) {\n const check = validateStep(step);\n if (!check.valid) {\n throw new Error(`Step ${step.id} failed catalog validation: ${check.reason}`);\n }\n }\n\n return result.data;\n}\n","import { execa } from \"execa\";\nimport type { Plan, Step } from \"./catalog.js\";\n\n// ---------------------------------------------------------------------------\n// Build the actual shell command from a Step\n// ---------------------------------------------------------------------------\nfunction resolveCommand(step: Step): { bin: string; args: string[] } {\n if (step.type === \"shell\") {\n // shell: command is the binary, args are the args\n return { bin: step.command, args: step.args };\n }\n\n // For npm/pnpm/yarn/bun/git: binary is the type, command + args follow\n return { bin: step.type, args: [step.command, ...step.args] };\n}\n\n// ---------------------------------------------------------------------------\n// Run a single step, streaming stdout/stderr live\n// ---------------------------------------------------------------------------\nexport async function runStep(step: Step): Promise<{ success: boolean; error?: string }> {\n const { bin, args } = resolveCommand(step);\n\n try {\n await execa(bin, args, {\n cwd: step.cwd ?? process.cwd(),\n stdout: \"inherit\", // stream directly to terminal\n stderr: \"inherit\",\n });\n return { success: true };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { success: false, error: message };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Run the full plan, stopping on first failure\n// ---------------------------------------------------------------------------\nexport async function runPlan(\n plan: Plan,\n onStep: (step: Step, index: number, total: number) => void\n): Promise<{ success: boolean; failedStep?: Step; error?: string }> {\n const total = plan.steps.length;\n\n for (let i = 0; i < total; i++) {\n const step = plan.steps[i];\n onStep(step, i, total);\n\n const result = await runStep(step);\n\n if (!result.success) {\n return { success: false, failedStep: step, error: result.error };\n }\n }\n\n return { success: true };\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ekaone/json-cli",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "description": "AI-powered CLI task runner with JSON command plans",
5
5
  "keywords": [
6
6
  "ai",