Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ When testing code that uses SqlAgent, you can mock the facade:

```php
use Knobik\SqlAgent\Facades\SqlAgent;
use Knobik\SqlAgent\Contracts\AgentResponse;
use Knobik\SqlAgent\Data\AgentResponse;

public function test_it_handles_sql_agent_response(): void
{
Expand Down
2 changes: 0 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
"illuminate/support": "^11.0|^12.0",
"illuminate/database": "^11.0|^12.0",
"illuminate/console": "^11.0|^12.0",
"spatie/laravel-data": "^4.0",
"doctrine/dbal": "^3.0|^4.0",
"prism-php/prism": "^0.99"
},
"require-dev": {
Expand Down
12 changes: 5 additions & 7 deletions src/Agent/SqlAgent.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Generator;
use Knobik\SqlAgent\Contracts\Agent;
use Knobik\SqlAgent\Contracts\AgentResponse;
use Knobik\SqlAgent\Data\AgentResponse;
use Knobik\SqlAgent\Llm\StreamChunk;
use Knobik\SqlAgent\Services\ConnectionRegistry;
use Knobik\SqlAgent\Services\ContextBuilder;
Expand Down Expand Up @@ -236,9 +236,9 @@ protected function syncFromRunSqlTool(array $tools): void
{
foreach ($tools as $tool) {
if ($tool instanceof RunSqlTool) {
$this->lastSql = $tool->lastSql;
$this->lastResults = $tool->lastResults;
$this->allQueries = $tool->executedQueries;
$this->lastSql = $tool->getLastSql();
$this->lastResults = $tool->getLastResults();
$this->allQueries = $tool->getExecutedQueries();

return;
}
Expand Down Expand Up @@ -336,9 +336,7 @@ protected function reset(): void
// Reset tool state
foreach ($this->toolRegistry->all() as $tool) {
if ($tool instanceof RunSqlTool) {
$tool->lastSql = null;
$tool->lastResults = null;
$tool->executedQueries = [];
$tool->reset();
}
}
}
Expand Down
38 changes: 2 additions & 36 deletions src/Agent/ToolRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public function register(Tool $tool): self
/**
* Register a single tool, throwing if a tool with the same name already exists.
*
* @internal
*
* @throws InvalidArgumentException
*/
public function registerStrict(Tool $tool): self
Expand Down Expand Up @@ -95,40 +97,4 @@ public function names(): array
{
return array_keys($this->tools);
}

/**
* Remove a tool by name.
*/
public function remove(string $name): self
{
unset($this->tools[$name]);

return $this;
}

/**
* Clear all registered tools.
*/
public function clear(): self
{
$this->tools = [];

return $this;
}

/**
* Get the number of registered tools.
*/
public function count(): int
{
return count($this->tools);
}

/**
* Check if the registry is empty.
*/
public function isEmpty(): bool
{
return empty($this->tools);
}
}
1 change: 1 addition & 0 deletions src/Contracts/Agent.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Knobik\SqlAgent\Contracts;

use Generator;
use Knobik\SqlAgent\Data\AgentResponse;

interface Agent
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?php

namespace Knobik\SqlAgent\Contracts;
declare(strict_types=1);

namespace Knobik\SqlAgent\Data;

class AgentResponse
{
Expand Down
3 changes: 1 addition & 2 deletions src/Data/BusinessRuleData.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
namespace Knobik\SqlAgent\Data;

use Knobik\SqlAgent\Enums\BusinessRuleType;
use Spatie\LaravelData\Data;

class BusinessRuleData extends Data
class BusinessRuleData
{
public function __construct(
public string $name,
Expand Down
4 changes: 1 addition & 3 deletions src/Data/ConnectionConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

namespace Knobik\SqlAgent\Data;

use Spatie\LaravelData\Data;

class ConnectionConfig extends Data
class ConnectionConfig
{
public function __construct(
/** The logical name (key in the config map). */
Expand Down
3 changes: 1 addition & 2 deletions src/Data/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
namespace Knobik\SqlAgent\Data;

use Illuminate\Support\Collection;
use Spatie\LaravelData\Data;

class Context extends Data
class Context
{
public function __construct(
public string $semanticModel,
Expand Down
3 changes: 1 addition & 2 deletions src/Data/EvaluationReport.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
use DateTimeImmutable;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\View;
use Spatie\LaravelData\Data;

class EvaluationReport extends Data
class EvaluationReport
{
public function __construct(
/** @var Collection<int, TestResult> */
Expand Down
4 changes: 1 addition & 3 deletions src/Data/GradeResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

namespace Knobik\SqlAgent\Data;

use Spatie\LaravelData\Data;

class GradeResult extends Data
class GradeResult
{
public function __construct(
public bool $passed,
Expand Down
4 changes: 1 addition & 3 deletions src/Data/QueryPatternData.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

namespace Knobik\SqlAgent\Data;

use Spatie\LaravelData\Data;

class QueryPatternData extends Data
class QueryPatternData
{
public function __construct(
public string $name,
Expand Down
4 changes: 1 addition & 3 deletions src/Data/TableSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

namespace Knobik\SqlAgent\Data;

use Spatie\LaravelData\Data;

class TableSchema extends Data
class TableSchema
{
public function __construct(
public string $tableName,
Expand Down
5 changes: 1 addition & 4 deletions src/Data/TestResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@

namespace Knobik\SqlAgent\Data;

use Knobik\SqlAgent\Contracts\AgentResponse;
use Spatie\LaravelData\Data;

class TestResult extends Data
class TestResult
{
public const STATUS_PASS = 'pass';

Expand Down
47 changes: 2 additions & 45 deletions src/Search/Strategies/MysqlFullTextStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Illuminate\Database\Eloquent\Builder;
use Knobik\SqlAgent\Contracts\FullTextSearchStrategy;
use Knobik\SqlAgent\Support\TextAnalyzer;

/**
* MySQL MATCH...AGAINST full-text search strategy.
Expand All @@ -21,7 +22,7 @@ public function __construct(

public function apply(Builder $query, string $searchTerm, array $columns, int $limit): Builder
{
$searchTerm = $this->prepareSearchTerm($searchTerm);
$searchTerm = TextAnalyzer::prepareSearchTerm($searchTerm);

if (empty($searchTerm)) {
return $query->limit($limit);
Expand All @@ -41,48 +42,4 @@ public function getName(): string
{
return 'mysql_fulltext';
}

/**
* Prepare the search term for MySQL full-text search.
*/
protected function prepareSearchTerm(string $term): string
{
// Extract keywords and filter stop words
$keywords = $this->extractKeywords($term);

return implode(' ', $keywords);
}

/**
* Extract keywords from a search term.
*
* @return array<string>
*/
protected function extractKeywords(string $text): array
{
$stopWords = [
'a', 'an', 'the', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
'should', 'may', 'might', 'must', 'can', 'to', 'of', 'in', 'for',
'on', 'with', 'at', 'by', 'from', 'as', 'into', 'through', 'during',
'before', 'after', 'above', 'below', 'between', 'under', 'again',
'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why',
'how', 'all', 'each', 'few', 'more', 'most', 'other', 'some', 'such',
'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too',
'very', 'just', 'and', 'but', 'if', 'or', 'because', 'until', 'while',
'what', 'which', 'who', 'whom', 'this', 'that', 'these', 'those',
'show', 'get', 'find', 'list', 'give', 'tell', 'many', 'much',
];

$words = preg_split('/[^a-zA-Z0-9]+/', strtolower($text), -1, PREG_SPLIT_NO_EMPTY);

if ($words === false) {
return [];
}

return array_values(array_filter(
$words,
fn (string $word) => strlen($word) > 2 && ! in_array($word, $stopWords)
));
}
}
47 changes: 2 additions & 45 deletions src/Search/Strategies/PostgresFullTextStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Illuminate\Database\Eloquent\Builder;
use Knobik\SqlAgent\Contracts\FullTextSearchStrategy;
use Knobik\SqlAgent\Support\TextAnalyzer;

/**
* PostgreSQL to_tsvector/to_tsquery full-text search strategy.
Expand All @@ -21,7 +22,7 @@ public function __construct(

public function apply(Builder $query, string $searchTerm, array $columns, int $limit): Builder
{
$searchTerm = $this->prepareSearchTerm($searchTerm);
$searchTerm = TextAnalyzer::prepareSearchTerm($searchTerm);

if (empty($searchTerm)) {
return $query->limit($limit);
Expand Down Expand Up @@ -50,48 +51,4 @@ public function getName(): string
{
return 'postgres_fulltext';
}

/**
* Prepare the search term for PostgreSQL full-text search.
*/
protected function prepareSearchTerm(string $term): string
{
// Extract keywords and filter stop words
$keywords = $this->extractKeywords($term);

return implode(' ', $keywords);
}

/**
* Extract keywords from a search term.
*
* @return array<string>
*/
protected function extractKeywords(string $text): array
{
$stopWords = [
'a', 'an', 'the', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
'should', 'may', 'might', 'must', 'can', 'to', 'of', 'in', 'for',
'on', 'with', 'at', 'by', 'from', 'as', 'into', 'through', 'during',
'before', 'after', 'above', 'below', 'between', 'under', 'again',
'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why',
'how', 'all', 'each', 'few', 'more', 'most', 'other', 'some', 'such',
'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too',
'very', 'just', 'and', 'but', 'if', 'or', 'because', 'until', 'while',
'what', 'which', 'who', 'whom', 'this', 'that', 'these', 'those',
'show', 'get', 'find', 'list', 'give', 'tell', 'many', 'much',
];

$words = preg_split('/[^a-zA-Z0-9]+/', strtolower($text), -1, PREG_SPLIT_NO_EMPTY);

if ($words === false) {
return [];
}

return array_values(array_filter(
$words,
fn (string $word) => strlen($word) > 2 && ! in_array($word, $stopWords)
));
}
}
Loading