@elyracode/coding-agent 0.4.1 → 0.4.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.4.2] - 2026-05-11
6
+
7
+ ### Added
8
+ - RILT stack extension (`@elyracode/stack-rilt`): React 19, Inertia.js 2, Laravel, Tailwind CSS 4, shadcn/ui
9
+ - Stack detector now recognizes RILT projects (React + Inertia + Laravel + Tailwind)
10
+
5
11
  ## [0.4.1] - 2026-05-11
6
12
 
7
13
  ### Added
@@ -4,7 +4,7 @@ export interface DetectedFramework {
4
4
  version?: string;
5
5
  }
6
6
  /** Known stack profiles that can be suggested for installation */
7
- export type KnownStack = "TALL" | "VILT";
7
+ export type KnownStack = "TALL" | "RILT" | "VILT";
8
8
  /** Result of stack detection */
9
9
  export interface StackDetectionResult {
10
10
  /** All detected frameworks */
@@ -1 +1 @@
1
- {"version":3,"file":"stack-detector.d.ts","sourceRoot":"","sources":["../../src/core/stack-detector.ts"],"names":[],"mappings":"AAGA,mDAAmD;AACnD,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,kEAAkE;AAClE,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzC,gCAAgC;AAChC,MAAM,WAAW,oBAAoB;IACpC,8BAA8B;IAC9B,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,yEAAyE;IACzE,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,yDAAyD;AACzD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAiH7D;AASD,0DAA0D;AAC1D,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAO7D","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/** Individual framework detected in the project */\nexport interface DetectedFramework {\n\tname: string;\n\tversion?: string;\n}\n\n/** Known stack profiles that can be suggested for installation */\nexport type KnownStack = \"TALL\" | \"VILT\";\n\n/** Result of stack detection */\nexport interface StackDetectionResult {\n\t/** All detected frameworks */\n\tframeworks: DetectedFramework[];\n\t/** Recognized stack profile (if frameworks match a known combination) */\n\tstack?: KnownStack;\n\t/** Human-readable summary for system prompt injection */\n\tsummary: string;\n}\n\n/** Detect the technology stack in a project directory */\nexport function detectStack(cwd: string): StackDetectionResult {\n\tconst frameworks: DetectedFramework[] = [];\n\n\t// Parse composer.json for PHP/Laravel dependencies\n\tconst composerPath = join(cwd, \"composer.json\");\n\tif (existsSync(composerPath)) {\n\t\ttry {\n\t\t\tconst composer = JSON.parse(readFileSync(composerPath, \"utf-8\"));\n\t\t\tconst deps = { ...composer.require, ...composer[\"require-dev\"] };\n\n\t\t\tif (deps[\"laravel/framework\"]) {\n\t\t\t\tframeworks.push({ name: \"Laravel\", version: extractVersion(deps[\"laravel/framework\"]) });\n\t\t\t}\n\t\t\tif (deps[\"livewire/livewire\"]) {\n\t\t\t\tframeworks.push({ name: \"Livewire\", version: extractVersion(deps[\"livewire/livewire\"]) });\n\t\t\t}\n\t\t\tif (deps[\"livewire/flux\"]) {\n\t\t\t\tframeworks.push({ name: \"Flux UI\", version: extractVersion(deps[\"livewire/flux\"]) });\n\t\t\t}\n\t\t\tif (deps[\"inertiajs/inertia-laravel\"]) {\n\t\t\t\tframeworks.push({ name: \"Inertia\", version: extractVersion(deps[\"inertiajs/inertia-laravel\"]) });\n\t\t\t}\n\t\t\tif (deps[\"laravel/reverb\"]) {\n\t\t\t\tframeworks.push({ name: \"Reverb\", version: extractVersion(deps[\"laravel/reverb\"]) });\n\t\t\t}\n\t\t\tif (deps[\"laravel/sanctum\"]) {\n\t\t\t\tframeworks.push({ name: \"Sanctum\", version: extractVersion(deps[\"laravel/sanctum\"]) });\n\t\t\t}\n\t\t\tif (deps[\"filament/filament\"]) {\n\t\t\t\tframeworks.push({ name: \"Filament\", version: extractVersion(deps[\"filament/filament\"]) });\n\t\t\t}\n\t\t\tif (deps[\"laravel/ai\"]) {\n\t\t\t\tframeworks.push({ name: \"Laravel AI SDK\", version: extractVersion(deps[\"laravel/ai\"]) });\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore malformed composer.json\n\t\t}\n\t}\n\n\t// Parse package.json for JS/frontend dependencies\n\tconst packagePath = join(cwd, \"package.json\");\n\tif (existsSync(packagePath)) {\n\t\ttry {\n\t\t\tconst pkg = JSON.parse(readFileSync(packagePath, \"utf-8\"));\n\t\t\tconst deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n\t\t\tif (deps.vue) {\n\t\t\t\tframeworks.push({ name: \"Vue\", version: extractVersion(deps.vue) });\n\t\t\t}\n\t\t\tif (deps.alpinejs) {\n\t\t\t\tframeworks.push({ name: \"Alpine.js\", version: extractVersion(deps.alpinejs) });\n\t\t\t}\n\t\t\tif (deps.tailwindcss) {\n\t\t\t\tframeworks.push({ name: \"Tailwind CSS\", version: extractVersion(deps.tailwindcss) });\n\t\t\t}\n\t\t\tif (\n\t\t\t\tdeps[\"@inertiajs/vue3\"] ||\n\t\t\t\tdeps[\"@inertiajs/vue2\"] ||\n\t\t\t\tdeps[\"@inertiajs/react\"] ||\n\t\t\t\tdeps[\"@inertiajs/svelte\"]\n\t\t\t) {\n\t\t\t\t// Inertia frontend adapter -- version from whichever is present\n\t\t\t\tconst inertiaFe =\n\t\t\t\t\tdeps[\"@inertiajs/vue3\"] ||\n\t\t\t\t\tdeps[\"@inertiajs/vue2\"] ||\n\t\t\t\t\tdeps[\"@inertiajs/react\"] ||\n\t\t\t\t\tdeps[\"@inertiajs/svelte\"];\n\t\t\t\tif (!frameworks.some((f) => f.name === \"Inertia\")) {\n\t\t\t\t\tframeworks.push({ name: \"Inertia\", version: extractVersion(inertiaFe) });\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (deps.react || deps[\"react-dom\"]) {\n\t\t\t\tframeworks.push({ name: \"React\", version: extractVersion(deps.react || deps[\"react-dom\"]) });\n\t\t\t}\n\t\t\tif (deps.svelte) {\n\t\t\t\tframeworks.push({ name: \"Svelte\", version: extractVersion(deps.svelte) });\n\t\t\t}\n\t\t\tif (deps.typescript) {\n\t\t\t\tframeworks.push({ name: \"TypeScript\", version: extractVersion(deps.typescript) });\n\t\t\t}\n\t\t\tif (deps.vite) {\n\t\t\t\tframeworks.push({ name: \"Vite\", version: extractVersion(deps.vite) });\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore malformed package.json\n\t\t}\n\t}\n\n\tif (frameworks.length === 0) {\n\t\treturn { frameworks, summary: \"\" };\n\t}\n\n\t// Detect known stack profiles\n\tconst has = (name: string) => frameworks.some((f) => f.name === name);\n\tlet stack: KnownStack | undefined;\n\n\tif (has(\"Laravel\") && has(\"Tailwind CSS\") && has(\"Alpine.js\") && has(\"Livewire\")) {\n\t\tstack = \"TALL\";\n\t} else if (has(\"Laravel\") && has(\"Tailwind CSS\") && has(\"Inertia\") && has(\"Vue\")) {\n\t\tstack = \"VILT\";\n\t}\n\n\t// Build human-readable summary\n\tconst frameworkList = frameworks.map((f) => (f.version ? `${f.name} ${f.version}` : f.name)).join(\", \");\n\tlet summary = `Detected frameworks: ${frameworkList}`;\n\tif (stack === \"TALL\") {\n\t\tconst hasFlux = has(\"Flux UI\");\n\t\tsummary = `TALL stack project (Tailwind, Alpine.js, Laravel, Livewire${hasFlux ? \", Flux UI\" : \"\"}).\\n${frameworkList}`;\n\t} else if (stack === \"VILT\") {\n\t\tsummary = `VILT stack project (Vue, Inertia, Laravel, Tailwind).\\n${frameworkList}`;\n\t}\n\n\treturn { frameworks, stack, summary };\n}\n\n/** Strip semver constraint prefixes (^, ~, >=, etc.) to get a clean version */\nfunction extractVersion(constraint: string | undefined): string | undefined {\n\tif (!constraint) return undefined;\n\tconst match = constraint.match(/(\\d+\\.\\d+(?:\\.\\d+)?)/);\n\treturn match?.[1];\n}\n\n/** Get the suggested package name for a detected stack */\nexport function getSuggestedPackage(stack: KnownStack): string {\n\tswitch (stack) {\n\t\tcase \"TALL\":\n\t\t\treturn \"@elyracode/stack-tall\";\n\t\tcase \"VILT\":\n\t\t\treturn \"@elyracode/stack-vilt\";\n\t}\n}\n"]}
1
+ {"version":3,"file":"stack-detector.d.ts","sourceRoot":"","sources":["../../src/core/stack-detector.ts"],"names":[],"mappings":"AAGA,mDAAmD;AACnD,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,kEAAkE;AAClE,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAElD,gCAAgC;AAChC,MAAM,WAAW,oBAAoB;IACpC,8BAA8B;IAC9B,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,yEAAyE;IACzE,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,yDAAyD;AACzD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAqH7D;AASD,0DAA0D;AAC1D,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAS7D","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/** Individual framework detected in the project */\nexport interface DetectedFramework {\n\tname: string;\n\tversion?: string;\n}\n\n/** Known stack profiles that can be suggested for installation */\nexport type KnownStack = \"TALL\" | \"RILT\" | \"VILT\";\n\n/** Result of stack detection */\nexport interface StackDetectionResult {\n\t/** All detected frameworks */\n\tframeworks: DetectedFramework[];\n\t/** Recognized stack profile (if frameworks match a known combination) */\n\tstack?: KnownStack;\n\t/** Human-readable summary for system prompt injection */\n\tsummary: string;\n}\n\n/** Detect the technology stack in a project directory */\nexport function detectStack(cwd: string): StackDetectionResult {\n\tconst frameworks: DetectedFramework[] = [];\n\n\t// Parse composer.json for PHP/Laravel dependencies\n\tconst composerPath = join(cwd, \"composer.json\");\n\tif (existsSync(composerPath)) {\n\t\ttry {\n\t\t\tconst composer = JSON.parse(readFileSync(composerPath, \"utf-8\"));\n\t\t\tconst deps = { ...composer.require, ...composer[\"require-dev\"] };\n\n\t\t\tif (deps[\"laravel/framework\"]) {\n\t\t\t\tframeworks.push({ name: \"Laravel\", version: extractVersion(deps[\"laravel/framework\"]) });\n\t\t\t}\n\t\t\tif (deps[\"livewire/livewire\"]) {\n\t\t\t\tframeworks.push({ name: \"Livewire\", version: extractVersion(deps[\"livewire/livewire\"]) });\n\t\t\t}\n\t\t\tif (deps[\"livewire/flux\"]) {\n\t\t\t\tframeworks.push({ name: \"Flux UI\", version: extractVersion(deps[\"livewire/flux\"]) });\n\t\t\t}\n\t\t\tif (deps[\"inertiajs/inertia-laravel\"]) {\n\t\t\t\tframeworks.push({ name: \"Inertia\", version: extractVersion(deps[\"inertiajs/inertia-laravel\"]) });\n\t\t\t}\n\t\t\tif (deps[\"laravel/reverb\"]) {\n\t\t\t\tframeworks.push({ name: \"Reverb\", version: extractVersion(deps[\"laravel/reverb\"]) });\n\t\t\t}\n\t\t\tif (deps[\"laravel/sanctum\"]) {\n\t\t\t\tframeworks.push({ name: \"Sanctum\", version: extractVersion(deps[\"laravel/sanctum\"]) });\n\t\t\t}\n\t\t\tif (deps[\"filament/filament\"]) {\n\t\t\t\tframeworks.push({ name: \"Filament\", version: extractVersion(deps[\"filament/filament\"]) });\n\t\t\t}\n\t\t\tif (deps[\"laravel/ai\"]) {\n\t\t\t\tframeworks.push({ name: \"Laravel AI SDK\", version: extractVersion(deps[\"laravel/ai\"]) });\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore malformed composer.json\n\t\t}\n\t}\n\n\t// Parse package.json for JS/frontend dependencies\n\tconst packagePath = join(cwd, \"package.json\");\n\tif (existsSync(packagePath)) {\n\t\ttry {\n\t\t\tconst pkg = JSON.parse(readFileSync(packagePath, \"utf-8\"));\n\t\t\tconst deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n\t\t\tif (deps.vue) {\n\t\t\t\tframeworks.push({ name: \"Vue\", version: extractVersion(deps.vue) });\n\t\t\t}\n\t\t\tif (deps.alpinejs) {\n\t\t\t\tframeworks.push({ name: \"Alpine.js\", version: extractVersion(deps.alpinejs) });\n\t\t\t}\n\t\t\tif (deps.tailwindcss) {\n\t\t\t\tframeworks.push({ name: \"Tailwind CSS\", version: extractVersion(deps.tailwindcss) });\n\t\t\t}\n\t\t\tif (\n\t\t\t\tdeps[\"@inertiajs/vue3\"] ||\n\t\t\t\tdeps[\"@inertiajs/vue2\"] ||\n\t\t\t\tdeps[\"@inertiajs/react\"] ||\n\t\t\t\tdeps[\"@inertiajs/svelte\"]\n\t\t\t) {\n\t\t\t\t// Inertia frontend adapter -- version from whichever is present\n\t\t\t\tconst inertiaFe =\n\t\t\t\t\tdeps[\"@inertiajs/vue3\"] ||\n\t\t\t\t\tdeps[\"@inertiajs/vue2\"] ||\n\t\t\t\t\tdeps[\"@inertiajs/react\"] ||\n\t\t\t\t\tdeps[\"@inertiajs/svelte\"];\n\t\t\t\tif (!frameworks.some((f) => f.name === \"Inertia\")) {\n\t\t\t\t\tframeworks.push({ name: \"Inertia\", version: extractVersion(inertiaFe) });\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (deps.react || deps[\"react-dom\"]) {\n\t\t\t\tframeworks.push({ name: \"React\", version: extractVersion(deps.react || deps[\"react-dom\"]) });\n\t\t\t}\n\t\t\tif (deps.svelte) {\n\t\t\t\tframeworks.push({ name: \"Svelte\", version: extractVersion(deps.svelte) });\n\t\t\t}\n\t\t\tif (deps.typescript) {\n\t\t\t\tframeworks.push({ name: \"TypeScript\", version: extractVersion(deps.typescript) });\n\t\t\t}\n\t\t\tif (deps.vite) {\n\t\t\t\tframeworks.push({ name: \"Vite\", version: extractVersion(deps.vite) });\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore malformed package.json\n\t\t}\n\t}\n\n\tif (frameworks.length === 0) {\n\t\treturn { frameworks, summary: \"\" };\n\t}\n\n\t// Detect known stack profiles\n\tconst has = (name: string) => frameworks.some((f) => f.name === name);\n\tlet stack: KnownStack | undefined;\n\n\tif (has(\"Laravel\") && has(\"Tailwind CSS\") && has(\"Alpine.js\") && has(\"Livewire\")) {\n\t\tstack = \"TALL\";\n\t} else if (has(\"Laravel\") && has(\"Tailwind CSS\") && has(\"Inertia\") && has(\"React\")) {\n\t\tstack = \"RILT\";\n\t} else if (has(\"Laravel\") && has(\"Tailwind CSS\") && has(\"Inertia\") && has(\"Vue\")) {\n\t\tstack = \"VILT\";\n\t}\n\n\t// Build human-readable summary\n\tconst frameworkList = frameworks.map((f) => (f.version ? `${f.name} ${f.version}` : f.name)).join(\", \");\n\tlet summary = `Detected frameworks: ${frameworkList}`;\n\tif (stack === \"TALL\") {\n\t\tconst hasFlux = has(\"Flux UI\");\n\t\tsummary = `TALL stack project (Tailwind, Alpine.js, Laravel, Livewire${hasFlux ? \", Flux UI\" : \"\"}).\\n${frameworkList}`;\n\t} else if (stack === \"RILT\") {\n\t\tsummary = `RILT stack project (React, Inertia, Laravel, Tailwind).\\n${frameworkList}`;\n\t} else if (stack === \"VILT\") {\n\t\tsummary = `VILT stack project (Vue, Inertia, Laravel, Tailwind).\\n${frameworkList}`;\n\t}\n\n\treturn { frameworks, stack, summary };\n}\n\n/** Strip semver constraint prefixes (^, ~, >=, etc.) to get a clean version */\nfunction extractVersion(constraint: string | undefined): string | undefined {\n\tif (!constraint) return undefined;\n\tconst match = constraint.match(/(\\d+\\.\\d+(?:\\.\\d+)?)/);\n\treturn match?.[1];\n}\n\n/** Get the suggested package name for a detected stack */\nexport function getSuggestedPackage(stack: KnownStack): string {\n\tswitch (stack) {\n\t\tcase \"TALL\":\n\t\t\treturn \"@elyracode/stack-tall\";\n\t\tcase \"RILT\":\n\t\t\treturn \"@elyracode/stack-rilt\";\n\t\tcase \"VILT\":\n\t\t\treturn \"@elyracode/stack-vilt\";\n\t}\n}\n"]}
@@ -92,6 +92,9 @@ export function detectStack(cwd) {
92
92
  if (has("Laravel") && has("Tailwind CSS") && has("Alpine.js") && has("Livewire")) {
93
93
  stack = "TALL";
94
94
  }
95
+ else if (has("Laravel") && has("Tailwind CSS") && has("Inertia") && has("React")) {
96
+ stack = "RILT";
97
+ }
95
98
  else if (has("Laravel") && has("Tailwind CSS") && has("Inertia") && has("Vue")) {
96
99
  stack = "VILT";
97
100
  }
@@ -102,6 +105,9 @@ export function detectStack(cwd) {
102
105
  const hasFlux = has("Flux UI");
103
106
  summary = `TALL stack project (Tailwind, Alpine.js, Laravel, Livewire${hasFlux ? ", Flux UI" : ""}).\n${frameworkList}`;
104
107
  }
108
+ else if (stack === "RILT") {
109
+ summary = `RILT stack project (React, Inertia, Laravel, Tailwind).\n${frameworkList}`;
110
+ }
105
111
  else if (stack === "VILT") {
106
112
  summary = `VILT stack project (Vue, Inertia, Laravel, Tailwind).\n${frameworkList}`;
107
113
  }
@@ -119,6 +125,8 @@ export function getSuggestedPackage(stack) {
119
125
  switch (stack) {
120
126
  case "TALL":
121
127
  return "@elyracode/stack-tall";
128
+ case "RILT":
129
+ return "@elyracode/stack-rilt";
122
130
  case "VILT":
123
131
  return "@elyracode/stack-vilt";
124
132
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stack-detector.js","sourceRoot":"","sources":["../../src/core/stack-detector.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/** Individual framework detected in the project */\nexport interface DetectedFramework {\n\tname: string;\n\tversion?: string;\n}\n\n/** Known stack profiles that can be suggested for installation */\nexport type KnownStack = \"TALL\" | \"VILT\";\n\n/** Result of stack detection */\nexport interface StackDetectionResult {\n\t/** All detected frameworks */\n\tframeworks: DetectedFramework[];\n\t/** Recognized stack profile (if frameworks match a known combination) */\n\tstack?: KnownStack;\n\t/** Human-readable summary for system prompt injection */\n\tsummary: string;\n}\n\n/** Detect the technology stack in a project directory */\nexport function detectStack(cwd: string): StackDetectionResult {\n\tconst frameworks: DetectedFramework[] = [];\n\n\t// Parse composer.json for PHP/Laravel dependencies\n\tconst composerPath = join(cwd, \"composer.json\");\n\tif (existsSync(composerPath)) {\n\t\ttry {\n\t\t\tconst composer = JSON.parse(readFileSync(composerPath, \"utf-8\"));\n\t\t\tconst deps = { ...composer.require, ...composer[\"require-dev\"] };\n\n\t\t\tif (deps[\"laravel/framework\"]) {\n\t\t\t\tframeworks.push({ name: \"Laravel\", version: extractVersion(deps[\"laravel/framework\"]) });\n\t\t\t}\n\t\t\tif (deps[\"livewire/livewire\"]) {\n\t\t\t\tframeworks.push({ name: \"Livewire\", version: extractVersion(deps[\"livewire/livewire\"]) });\n\t\t\t}\n\t\t\tif (deps[\"livewire/flux\"]) {\n\t\t\t\tframeworks.push({ name: \"Flux UI\", version: extractVersion(deps[\"livewire/flux\"]) });\n\t\t\t}\n\t\t\tif (deps[\"inertiajs/inertia-laravel\"]) {\n\t\t\t\tframeworks.push({ name: \"Inertia\", version: extractVersion(deps[\"inertiajs/inertia-laravel\"]) });\n\t\t\t}\n\t\t\tif (deps[\"laravel/reverb\"]) {\n\t\t\t\tframeworks.push({ name: \"Reverb\", version: extractVersion(deps[\"laravel/reverb\"]) });\n\t\t\t}\n\t\t\tif (deps[\"laravel/sanctum\"]) {\n\t\t\t\tframeworks.push({ name: \"Sanctum\", version: extractVersion(deps[\"laravel/sanctum\"]) });\n\t\t\t}\n\t\t\tif (deps[\"filament/filament\"]) {\n\t\t\t\tframeworks.push({ name: \"Filament\", version: extractVersion(deps[\"filament/filament\"]) });\n\t\t\t}\n\t\t\tif (deps[\"laravel/ai\"]) {\n\t\t\t\tframeworks.push({ name: \"Laravel AI SDK\", version: extractVersion(deps[\"laravel/ai\"]) });\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore malformed composer.json\n\t\t}\n\t}\n\n\t// Parse package.json for JS/frontend dependencies\n\tconst packagePath = join(cwd, \"package.json\");\n\tif (existsSync(packagePath)) {\n\t\ttry {\n\t\t\tconst pkg = JSON.parse(readFileSync(packagePath, \"utf-8\"));\n\t\t\tconst deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n\t\t\tif (deps.vue) {\n\t\t\t\tframeworks.push({ name: \"Vue\", version: extractVersion(deps.vue) });\n\t\t\t}\n\t\t\tif (deps.alpinejs) {\n\t\t\t\tframeworks.push({ name: \"Alpine.js\", version: extractVersion(deps.alpinejs) });\n\t\t\t}\n\t\t\tif (deps.tailwindcss) {\n\t\t\t\tframeworks.push({ name: \"Tailwind CSS\", version: extractVersion(deps.tailwindcss) });\n\t\t\t}\n\t\t\tif (\n\t\t\t\tdeps[\"@inertiajs/vue3\"] ||\n\t\t\t\tdeps[\"@inertiajs/vue2\"] ||\n\t\t\t\tdeps[\"@inertiajs/react\"] ||\n\t\t\t\tdeps[\"@inertiajs/svelte\"]\n\t\t\t) {\n\t\t\t\t// Inertia frontend adapter -- version from whichever is present\n\t\t\t\tconst inertiaFe =\n\t\t\t\t\tdeps[\"@inertiajs/vue3\"] ||\n\t\t\t\t\tdeps[\"@inertiajs/vue2\"] ||\n\t\t\t\t\tdeps[\"@inertiajs/react\"] ||\n\t\t\t\t\tdeps[\"@inertiajs/svelte\"];\n\t\t\t\tif (!frameworks.some((f) => f.name === \"Inertia\")) {\n\t\t\t\t\tframeworks.push({ name: \"Inertia\", version: extractVersion(inertiaFe) });\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (deps.react || deps[\"react-dom\"]) {\n\t\t\t\tframeworks.push({ name: \"React\", version: extractVersion(deps.react || deps[\"react-dom\"]) });\n\t\t\t}\n\t\t\tif (deps.svelte) {\n\t\t\t\tframeworks.push({ name: \"Svelte\", version: extractVersion(deps.svelte) });\n\t\t\t}\n\t\t\tif (deps.typescript) {\n\t\t\t\tframeworks.push({ name: \"TypeScript\", version: extractVersion(deps.typescript) });\n\t\t\t}\n\t\t\tif (deps.vite) {\n\t\t\t\tframeworks.push({ name: \"Vite\", version: extractVersion(deps.vite) });\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore malformed package.json\n\t\t}\n\t}\n\n\tif (frameworks.length === 0) {\n\t\treturn { frameworks, summary: \"\" };\n\t}\n\n\t// Detect known stack profiles\n\tconst has = (name: string) => frameworks.some((f) => f.name === name);\n\tlet stack: KnownStack | undefined;\n\n\tif (has(\"Laravel\") && has(\"Tailwind CSS\") && has(\"Alpine.js\") && has(\"Livewire\")) {\n\t\tstack = \"TALL\";\n\t} else if (has(\"Laravel\") && has(\"Tailwind CSS\") && has(\"Inertia\") && has(\"Vue\")) {\n\t\tstack = \"VILT\";\n\t}\n\n\t// Build human-readable summary\n\tconst frameworkList = frameworks.map((f) => (f.version ? `${f.name} ${f.version}` : f.name)).join(\", \");\n\tlet summary = `Detected frameworks: ${frameworkList}`;\n\tif (stack === \"TALL\") {\n\t\tconst hasFlux = has(\"Flux UI\");\n\t\tsummary = `TALL stack project (Tailwind, Alpine.js, Laravel, Livewire${hasFlux ? \", Flux UI\" : \"\"}).\\n${frameworkList}`;\n\t} else if (stack === \"VILT\") {\n\t\tsummary = `VILT stack project (Vue, Inertia, Laravel, Tailwind).\\n${frameworkList}`;\n\t}\n\n\treturn { frameworks, stack, summary };\n}\n\n/** Strip semver constraint prefixes (^, ~, >=, etc.) to get a clean version */\nfunction extractVersion(constraint: string | undefined): string | undefined {\n\tif (!constraint) return undefined;\n\tconst match = constraint.match(/(\\d+\\.\\d+(?:\\.\\d+)?)/);\n\treturn match?.[1];\n}\n\n/** Get the suggested package name for a detected stack */\nexport function getSuggestedPackage(stack: KnownStack): string {\n\tswitch (stack) {\n\t\tcase \"TALL\":\n\t\t\treturn \"@elyracode/stack-tall\";\n\t\tcase \"VILT\":\n\t\t\treturn \"@elyracode/stack-vilt\";\n\t}\n}\n"]}
1
+ {"version":3,"file":"stack-detector.js","sourceRoot":"","sources":["../../src/core/stack-detector.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/** Individual framework detected in the project */\nexport interface DetectedFramework {\n\tname: string;\n\tversion?: string;\n}\n\n/** Known stack profiles that can be suggested for installation */\nexport type KnownStack = \"TALL\" | \"RILT\" | \"VILT\";\n\n/** Result of stack detection */\nexport interface StackDetectionResult {\n\t/** All detected frameworks */\n\tframeworks: DetectedFramework[];\n\t/** Recognized stack profile (if frameworks match a known combination) */\n\tstack?: KnownStack;\n\t/** Human-readable summary for system prompt injection */\n\tsummary: string;\n}\n\n/** Detect the technology stack in a project directory */\nexport function detectStack(cwd: string): StackDetectionResult {\n\tconst frameworks: DetectedFramework[] = [];\n\n\t// Parse composer.json for PHP/Laravel dependencies\n\tconst composerPath = join(cwd, \"composer.json\");\n\tif (existsSync(composerPath)) {\n\t\ttry {\n\t\t\tconst composer = JSON.parse(readFileSync(composerPath, \"utf-8\"));\n\t\t\tconst deps = { ...composer.require, ...composer[\"require-dev\"] };\n\n\t\t\tif (deps[\"laravel/framework\"]) {\n\t\t\t\tframeworks.push({ name: \"Laravel\", version: extractVersion(deps[\"laravel/framework\"]) });\n\t\t\t}\n\t\t\tif (deps[\"livewire/livewire\"]) {\n\t\t\t\tframeworks.push({ name: \"Livewire\", version: extractVersion(deps[\"livewire/livewire\"]) });\n\t\t\t}\n\t\t\tif (deps[\"livewire/flux\"]) {\n\t\t\t\tframeworks.push({ name: \"Flux UI\", version: extractVersion(deps[\"livewire/flux\"]) });\n\t\t\t}\n\t\t\tif (deps[\"inertiajs/inertia-laravel\"]) {\n\t\t\t\tframeworks.push({ name: \"Inertia\", version: extractVersion(deps[\"inertiajs/inertia-laravel\"]) });\n\t\t\t}\n\t\t\tif (deps[\"laravel/reverb\"]) {\n\t\t\t\tframeworks.push({ name: \"Reverb\", version: extractVersion(deps[\"laravel/reverb\"]) });\n\t\t\t}\n\t\t\tif (deps[\"laravel/sanctum\"]) {\n\t\t\t\tframeworks.push({ name: \"Sanctum\", version: extractVersion(deps[\"laravel/sanctum\"]) });\n\t\t\t}\n\t\t\tif (deps[\"filament/filament\"]) {\n\t\t\t\tframeworks.push({ name: \"Filament\", version: extractVersion(deps[\"filament/filament\"]) });\n\t\t\t}\n\t\t\tif (deps[\"laravel/ai\"]) {\n\t\t\t\tframeworks.push({ name: \"Laravel AI SDK\", version: extractVersion(deps[\"laravel/ai\"]) });\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore malformed composer.json\n\t\t}\n\t}\n\n\t// Parse package.json for JS/frontend dependencies\n\tconst packagePath = join(cwd, \"package.json\");\n\tif (existsSync(packagePath)) {\n\t\ttry {\n\t\t\tconst pkg = JSON.parse(readFileSync(packagePath, \"utf-8\"));\n\t\t\tconst deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n\t\t\tif (deps.vue) {\n\t\t\t\tframeworks.push({ name: \"Vue\", version: extractVersion(deps.vue) });\n\t\t\t}\n\t\t\tif (deps.alpinejs) {\n\t\t\t\tframeworks.push({ name: \"Alpine.js\", version: extractVersion(deps.alpinejs) });\n\t\t\t}\n\t\t\tif (deps.tailwindcss) {\n\t\t\t\tframeworks.push({ name: \"Tailwind CSS\", version: extractVersion(deps.tailwindcss) });\n\t\t\t}\n\t\t\tif (\n\t\t\t\tdeps[\"@inertiajs/vue3\"] ||\n\t\t\t\tdeps[\"@inertiajs/vue2\"] ||\n\t\t\t\tdeps[\"@inertiajs/react\"] ||\n\t\t\t\tdeps[\"@inertiajs/svelte\"]\n\t\t\t) {\n\t\t\t\t// Inertia frontend adapter -- version from whichever is present\n\t\t\t\tconst inertiaFe =\n\t\t\t\t\tdeps[\"@inertiajs/vue3\"] ||\n\t\t\t\t\tdeps[\"@inertiajs/vue2\"] ||\n\t\t\t\t\tdeps[\"@inertiajs/react\"] ||\n\t\t\t\t\tdeps[\"@inertiajs/svelte\"];\n\t\t\t\tif (!frameworks.some((f) => f.name === \"Inertia\")) {\n\t\t\t\t\tframeworks.push({ name: \"Inertia\", version: extractVersion(inertiaFe) });\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (deps.react || deps[\"react-dom\"]) {\n\t\t\t\tframeworks.push({ name: \"React\", version: extractVersion(deps.react || deps[\"react-dom\"]) });\n\t\t\t}\n\t\t\tif (deps.svelte) {\n\t\t\t\tframeworks.push({ name: \"Svelte\", version: extractVersion(deps.svelte) });\n\t\t\t}\n\t\t\tif (deps.typescript) {\n\t\t\t\tframeworks.push({ name: \"TypeScript\", version: extractVersion(deps.typescript) });\n\t\t\t}\n\t\t\tif (deps.vite) {\n\t\t\t\tframeworks.push({ name: \"Vite\", version: extractVersion(deps.vite) });\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore malformed package.json\n\t\t}\n\t}\n\n\tif (frameworks.length === 0) {\n\t\treturn { frameworks, summary: \"\" };\n\t}\n\n\t// Detect known stack profiles\n\tconst has = (name: string) => frameworks.some((f) => f.name === name);\n\tlet stack: KnownStack | undefined;\n\n\tif (has(\"Laravel\") && has(\"Tailwind CSS\") && has(\"Alpine.js\") && has(\"Livewire\")) {\n\t\tstack = \"TALL\";\n\t} else if (has(\"Laravel\") && has(\"Tailwind CSS\") && has(\"Inertia\") && has(\"React\")) {\n\t\tstack = \"RILT\";\n\t} else if (has(\"Laravel\") && has(\"Tailwind CSS\") && has(\"Inertia\") && has(\"Vue\")) {\n\t\tstack = \"VILT\";\n\t}\n\n\t// Build human-readable summary\n\tconst frameworkList = frameworks.map((f) => (f.version ? `${f.name} ${f.version}` : f.name)).join(\", \");\n\tlet summary = `Detected frameworks: ${frameworkList}`;\n\tif (stack === \"TALL\") {\n\t\tconst hasFlux = has(\"Flux UI\");\n\t\tsummary = `TALL stack project (Tailwind, Alpine.js, Laravel, Livewire${hasFlux ? \", Flux UI\" : \"\"}).\\n${frameworkList}`;\n\t} else if (stack === \"RILT\") {\n\t\tsummary = `RILT stack project (React, Inertia, Laravel, Tailwind).\\n${frameworkList}`;\n\t} else if (stack === \"VILT\") {\n\t\tsummary = `VILT stack project (Vue, Inertia, Laravel, Tailwind).\\n${frameworkList}`;\n\t}\n\n\treturn { frameworks, stack, summary };\n}\n\n/** Strip semver constraint prefixes (^, ~, >=, etc.) to get a clean version */\nfunction extractVersion(constraint: string | undefined): string | undefined {\n\tif (!constraint) return undefined;\n\tconst match = constraint.match(/(\\d+\\.\\d+(?:\\.\\d+)?)/);\n\treturn match?.[1];\n}\n\n/** Get the suggested package name for a detected stack */\nexport function getSuggestedPackage(stack: KnownStack): string {\n\tswitch (stack) {\n\t\tcase \"TALL\":\n\t\t\treturn \"@elyracode/stack-tall\";\n\t\tcase \"RILT\":\n\t\t\treturn \"@elyracode/stack-rilt\";\n\t\tcase \"VILT\":\n\t\t\treturn \"@elyracode/stack-vilt\";\n\t}\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "elyra-extension-custom-provider-anthropic",
3
3
  "private": true,
4
- "version": "0.4.1",
4
+ "version": "0.4.2",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "elyra-extension-custom-provider-gitlab-duo",
3
3
  "private": true,
4
- "version": "0.4.1",
4
+ "version": "0.4.2",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "elyra-extension-sandbox",
3
3
  "private": true,
4
- "version": "0.4.1",
4
+ "version": "0.4.2",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "elyra-extension-with-deps",
3
3
  "private": true,
4
- "version": "0.4.1",
4
+ "version": "0.4.2",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elyracode/coding-agent",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "elyraConfig": {
@@ -38,9 +38,9 @@
38
38
  "prepublishOnly": "npm run clean && npm run build"
39
39
  },
40
40
  "dependencies": {
41
- "@elyracode/agent-core": "^0.4.1",
42
- "@elyracode/ai": "^0.4.1",
43
- "@elyracode/tui": "^0.4.1",
41
+ "@elyracode/agent-core": "^0.4.2",
42
+ "@elyracode/ai": "^0.4.2",
43
+ "@elyracode/tui": "^0.4.2",
44
44
  "@silvia-odwyer/photon-node": "^0.3.4",
45
45
  "chalk": "^5.5.0",
46
46
  "cli-highlight": "^2.1.11",