Skip to content

Commit 009f2f9

Browse files
committed
Fix AI commands to use new runway config syntax
1 parent 095a466 commit 009f2f9

File tree

7 files changed

+310
-331
lines changed

7 files changed

+310
-331
lines changed

composer.json

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
"require-dev": {
4545
"ext-pdo_sqlite": "*",
4646
"flightphp/container": "^1.0",
47-
"flightphp/runway": "^0.2.3 || ^1.0",
47+
"flightphp/runway": "^1.2",
4848
"league/container": "^4.2",
4949
"level-2/dice": "^4.0",
5050
"phpstan/extension-installer": "^1.4",
@@ -62,21 +62,22 @@
6262
"sort-packages": true
6363
},
6464
"scripts": {
65-
"test": "vendor/bin/phpunit-watcher watch",
65+
"test": "phpunit",
66+
"test-watcher": "phpunit-watcher watch",
6667
"test-ci": "phpunit",
6768
"test-coverage": "rm -f clover.xml && XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html=coverage --coverage-clover=clover.xml && vendor/bin/coverage-check clover.xml 100",
6869
"test-server": "echo \"Running Test Server\" && php -S localhost:8000 -t tests/server/",
6970
"test-server-v2": "echo \"Running Test Server\" && php -S localhost:8000 -t tests/server-v2/",
7071
"test-coverage:win": "del clover.xml && phpunit --coverage-html=coverage --coverage-clover=clover.xml && coverage-check clover.xml 100",
71-
"test-performance": [
72-
"echo \"Running Performance Tests...\"",
73-
"php -S localhost:8077 -t tests/performance/ > /dev/null 2>&1 & echo $! > server.pid",
74-
"sleep 2",
75-
"bash tests/performance/performance_tests.sh",
76-
"kill `cat server.pid`",
77-
"rm server.pid",
78-
"echo \"Performance Tests Completed.\""
79-
],
72+
"test-performance": [
73+
"echo \"Running Performance Tests...\"",
74+
"php -S localhost:8077 -t tests/performance/ > /dev/null 2>&1 & echo $! > server.pid",
75+
"sleep 2",
76+
"bash tests/performance/performance_tests.sh",
77+
"kill `cat server.pid`",
78+
"rm server.pid",
79+
"echo \"Performance Tests Completed.\""
80+
],
8081
"lint": "phpstan --no-progress --memory-limit=256M -cphpstan.neon",
8182
"beautify": "phpcbf --standard=phpcs.xml",
8283
"phpcs": "phpcs --standard=phpcs.xml -n",
@@ -92,4 +93,4 @@
9293
"replace": {
9394
"mikecao/flight": "2.0.2"
9495
}
95-
}
96+
}

flight/Engine.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ public function _start(): void
621621
$response->write(ob_get_clean());
622622
}
623623

624-
// Run any before middlewares
624+
// Run any after middlewares
625625
if (count($route->middleware) > 0) {
626626
// process the middleware in reverse order now
627627
$atLeastOneMiddlewareFailed = $this->processMiddleware($route, 'after');

flight/commands/AiGenerateInstructionsCommand.php

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,23 @@
44

55
namespace flight\commands;
66

7-
use Ahc\Cli\Input\Command;
8-
97
/**
10-
* @property-read ?string $credsFile
8+
* @property-read ?string $configFile
119
* @property-read ?string $baseDir
1210
*/
13-
class AiGenerateInstructionsCommand extends Command
11+
class AiGenerateInstructionsCommand extends AbstractBaseCommand
1412
{
1513
/**
1614
* Constructor for the AiGenerateInstructionsCommand class.
1715
*
1816
* Initializes a new instance of the command.
17+
*
18+
* @param array<string,mixed> $config Config from config.php
1919
*/
20-
public function __construct()
20+
public function __construct(array $config)
2121
{
22-
parent::__construct('ai:generate-instructions', 'Generate project-specific AI coding instructions');
23-
$this->option('--creds-file', 'Path to .runway-creds.json file', null, '');
24-
$this->option('--base-dir', 'Project base directory (for testing or custom use)', null, '');
22+
parent::__construct('ai:generate-instructions', 'Generate project-specific AI coding instructions', $config);
23+
$this->option('--config-file', 'Path to .runway-config.json file (deprecated, use config.php instead)', null, '');
2524
}
2625

2726
/**
@@ -37,12 +36,19 @@ public function __construct()
3736
public function execute()
3837
{
3938
$io = $this->app()->io();
40-
$baseDir = $this->baseDir ? rtrim($this->baseDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : getcwd() . DIRECTORY_SEPARATOR;
41-
$runwayCredsFile = $this->credsFile ?: $baseDir . '.runway-creds.json';
4239

43-
// Check for runway creds
44-
if (!file_exists($runwayCredsFile)) {
45-
$io->error('Missing .runway-creds.json. Please run the \'ai:init\' command first.', true);
40+
if (empty($this->config['runway'])) {
41+
$configFile = $this->configFile;
42+
$io = $this->app()->io();
43+
$io->warn('The --config-file option is deprecated. Move your config values to the \'runway\' key in the config.php file for configuration.', true);
44+
$runwayConfig = json_decode(file_get_contents($configFile), true) ?? [];
45+
} else {
46+
$runwayConfig = $this->config['runway'];
47+
}
48+
49+
// Check for runway creds ai
50+
if (empty($runwayConfig['ai'])) {
51+
$io->error('Missing AI configuration. Please run the \'ai:init\' command first.', true);
4652
return 1;
4753
}
4854

@@ -61,8 +67,8 @@ public function execute()
6167
$other = $io->prompt('Any other important requirements or context? (optional)', 'no');
6268

6369
// Prepare prompt for LLM
64-
$contextFile = $baseDir . '.github/copilot-instructions.md';
65-
$context = file_exists($contextFile) ? file_get_contents($contextFile) : '';
70+
$contextFile = $this->projectRoot . '.github/copilot-instructions.md';
71+
$context = file_exists($contextFile) === true ? file_get_contents($contextFile) : '';
6672
$userDetails = [
6773
'Project Description' => $projectDesc,
6874
'Database' => $database,
@@ -80,18 +86,18 @@ public function execute()
8086
$detailsText .= "$k: $v\n";
8187
}
8288
$prompt = <<<EOT
83-
You are an AI coding assistant. Update the following project instructions for this FlightPHP project based on the latest user answers. Only output the new instructions, no extra commentary.
89+
You are an AI coding assistant. Update the following project instructions for this Flight PHP project based on the latest user answers. Only output the new instructions, no extra commentary.
8490
User answers:
8591
$detailsText
8692
Current instructions:
8793
$context
8894
EOT; // phpcs:ignore
8995

9096
// Read LLM creds
91-
$creds = json_decode(file_get_contents($runwayCredsFile), true);
92-
$apiKey = $creds['api_key'] ?? '';
93-
$model = $creds['model'] ?? 'gpt-4o';
94-
$baseUrl = $creds['base_url'] ?? 'https://api.openai.com';
97+
$creds = $runwayConfig['ai'];
98+
$apiKey = $creds['api_key'];
99+
$model = $creds['model'];
100+
$baseUrl = $creds['base_url'];
95101

96102
// Prepare curl call (OpenAI compatible)
97103
$headers = [
@@ -123,16 +129,20 @@ public function execute()
123129
}
124130

125131
// Write to files
126-
$io->info('Updating .github/copilot-instructions.md, .cursor/rules/project-overview.mdc, and .windsurfrules...', true);
127-
if (!is_dir($baseDir . '.github')) {
128-
mkdir($baseDir . '.github', 0755, true);
132+
$io->info('Updating .github/copilot-instructions.md, .cursor/rules/project-overview.mdc, .gemini/GEMINI.md and .windsurfrules...', true);
133+
if (!is_dir($this->projectRoot . '.github')) {
134+
mkdir($this->projectRoot . '.github', 0755, true);
135+
}
136+
if (!is_dir($this->projectRoot . '.cursor/rules')) {
137+
mkdir($this->projectRoot . '.cursor/rules', 0755, true);
129138
}
130-
if (!is_dir($baseDir . '.cursor/rules')) {
131-
mkdir($baseDir . '.cursor/rules', 0755, true);
139+
if (!is_dir($this->projectRoot . '.gemini')) {
140+
mkdir($this->projectRoot . '.gemini', 0755, true);
132141
}
133-
file_put_contents($baseDir . '.github/copilot-instructions.md', $instructions);
134-
file_put_contents($baseDir . '.cursor/rules/project-overview.mdc', $instructions);
135-
file_put_contents($baseDir . '.windsurfrules', $instructions);
142+
file_put_contents($this->projectRoot . '.github/copilot-instructions.md', $instructions);
143+
file_put_contents($this->projectRoot . '.cursor/rules/project-overview.mdc', $instructions);
144+
file_put_contents($this->projectRoot . '.gemini/GEMINI.md', $instructions);
145+
file_put_contents($this->projectRoot . '.windsurfrules', $instructions);
136146
$io->ok('AI instructions updated successfully.', true);
137147
return 0;
138148
}

flight/commands/AiInitCommand.php

Lines changed: 14 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,22 @@
44

55
namespace flight\commands;
66

7-
use Ahc\Cli\Input\Command;
8-
97
/**
10-
* @property-read ?string $gitignoreFile
11-
* @property-read ?string $credsFile
8+
* @property-read ?string $credsFile Deprecated, use config.php instead
129
*/
13-
class AiInitCommand extends Command
10+
class AiInitCommand extends AbstractBaseCommand
1411
{
1512
/**
1613
* Constructor for the AiInitCommand class.
1714
*
1815
* Initializes the command instance and sets up any required dependencies.
16+
*
17+
* @param array<string,mixed> $config Config from config.php
1918
*/
20-
public function __construct()
19+
public function __construct(array $config)
2120
{
22-
parent::__construct('ai:init', 'Initialize LLM API credentials and settings');
23-
$this
24-
->option('--gitignore-file', 'Path to .gitignore file', null, '')
25-
->option('--creds-file', 'Path to .runway-creds.json file', null, '');
21+
parent::__construct('ai:init', 'Initialize LLM API credentials and settings', $config);
22+
$this->option('--creds-file', 'Path to .runway-creds.json file (deprecated, use config.php instead)', null, '');
2623
}
2724

2825
/**
@@ -36,21 +33,6 @@ public function execute()
3633

3734
$io->info('Welcome to AI Init!', true);
3835

39-
$baseDir = getcwd() . DIRECTORY_SEPARATOR;
40-
$runwayCredsFile = $this->credsFile ?: $baseDir . '.runway-creds.json';
41-
$gitignoreFile = $this->gitignoreFile ?: $baseDir . '.gitignore';
42-
43-
// make sure the .runway-creds.json file is not already present
44-
if (file_exists($runwayCredsFile)) {
45-
$io->error('.runway-creds.json file already exists. Please remove it before running this command.', true);
46-
// prompt to overwrite
47-
$overwrite = $io->confirm('Do you want to overwrite the existing .runway-creds.json file?', 'n');
48-
if ($overwrite === false) {
49-
$io->info('Exiting without changes.', true);
50-
return 0;
51-
}
52-
}
53-
5436
// Prompt for API provider with validation
5537
$allowedApis = [
5638
'1' => 'openai',
@@ -88,50 +70,26 @@ public function execute()
8870
// Validate model input
8971
switch ($api) {
9072
case 'openai':
91-
$defaultModel = 'gpt-4o';
73+
$defaultModel = 'gpt-5';
9274
break;
9375
case 'grok':
94-
$defaultModel = 'grok-3-beta';
76+
$defaultModel = 'grok-4.1-fast-non-reasoning';
9577
break;
9678
case 'claude':
97-
$defaultModel = 'claude-3-opus';
79+
$defaultModel = 'claude-sonnet-4-5';
9880
break;
9981
}
100-
$model = trim($io->prompt('Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc)', $defaultModel));
82+
$model = trim($io->prompt('Enter the model name you want to use (e.g. gpt-5, claude-sonnet-4-5, etc)', $defaultModel));
10183

102-
$creds = [
84+
$runwayAiConfig = [
10385
'provider' => $api,
10486
'api_key' => $apiKey,
10587
'model' => $model,
10688
'base_url' => $baseUrl,
10789
];
90+
$this->setRunwayConfigValue('ai', $runwayAiConfig);
10891

109-
$json = json_encode($creds, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
110-
$file = $runwayCredsFile;
111-
file_put_contents($file, $json);
112-
113-
// change permissions to 600
114-
chmod($file, 0600);
115-
116-
$io->ok('Credentials saved to ' . $file, true);
117-
118-
// run a check to make sure that the creds file is in the .gitignore file
119-
// use $gitignoreFile instead of hardcoded path
120-
if (!file_exists($gitignoreFile)) {
121-
// create the .gitignore file if it doesn't exist
122-
file_put_contents($gitignoreFile, basename($runwayCredsFile) . "\n");
123-
$io->info(basename($gitignoreFile) . ' file created and ' . basename($runwayCredsFile) . ' added to it.', true);
124-
} else {
125-
// check if the creds file is already in the .gitignore file
126-
$gitignoreContents = file_get_contents($gitignoreFile);
127-
if (strpos($gitignoreContents, basename($runwayCredsFile)) === false) {
128-
// add the creds file to the .gitignore file
129-
file_put_contents($gitignoreFile, "\n" . basename($runwayCredsFile) . "\n", FILE_APPEND);
130-
$io->info(basename($runwayCredsFile) . ' added to ' . basename($gitignoreFile) . ' file.', true);
131-
} else {
132-
$io->info(basename($runwayCredsFile) . ' is already in the ' . basename($gitignoreFile) . ' file.', true);
133-
}
134-
}
92+
$io->ok('Credentials saved to app/config/config.php', true);
13593

13694
return 0;
13795
}

tests/classes/NoExitInteractor.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace tests\classes;
6+
7+
use Ahc\Cli\IO\Interactor;
8+
9+
class NoExitInteractor extends Interactor
10+
{
11+
public function error(string $text, bool $exit = false): self
12+
{
13+
$this->writer()->error($text, 0);
14+
return $this;
15+
}
16+
public function warn(string $text, bool $exit = false): self
17+
{
18+
$this->writer()->warn($text, 0);
19+
return $this;
20+
}
21+
}

0 commit comments

Comments
 (0)