Skip to content

Commit 2658580

Browse files
authored
Introduce fluent methods for CustomTool (#14)
1 parent 8c50c47 commit 2658580

File tree

3 files changed

+77
-118
lines changed

3 files changed

+77
-118
lines changed

README.md

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -60,38 +60,17 @@ Loop::tool(
6060
CustomTool::make(
6161
name: 'custom_tool',
6262
description: 'This is a custom tool',
63-
parameters: [
64-
'name' => ['type' => 'string', 'description' => 'The name of the user', 'required' => true],
65-
'age' => ['type' => 'integer', 'description' => 'The age of the user'],
66-
],
67-
handler: function (string $name, ?int $age = null) {
63+
)
64+
->withStringParameter(name: 'name', description: 'The name of the user', required: true)
65+
->withIntegerParameter(name: 'age', description: 'The age of the user')
66+
->using(function (string $name, ?int $age = null) {
6867
return sprintf('Hello, %s! You are %d years old.', $name, $age ?? 'unknown');
69-
},
70-
),
68+
}),
69+
);
7170
);
7271
```
7372

74-
The available parameters types are:
75-
76-
```
77-
[
78-
parameters: [
79-
'name' => ['type' => 'string', 'description' => 'The name of the user', 'required' => true],
80-
'age' => ['type' => 'integer', 'description' => 'The age of the user'],
81-
'address' => [
82-
'type' => 'object',
83-
'description' => 'The address of the user',
84-
'properties' => [
85-
'street' => ['type' => 'string', 'description' => 'The street of the user'],
86-
'city' => ['type' => 'string', 'description' => 'The city of the user'],
87-
'state' => ['type' => 'string', 'description' => 'The state of the user'],
88-
'zip' => ['type' => 'string', 'description' => 'The zip of the user'],
89-
],
90-
'required' => ['street', 'city', 'state', 'zip'],
91-
]],
92-
],
93-
]
94-
```
73+
The available parameters types can be found in the [Prism Tool Documentation](https://prismphp.com/core-concepts/tools-function-calling.html#parameter-definition).
9574

9675
### Custom Tool Objects
9776

phpstan.neon.dist

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ parameters:
1212
- config
1313

1414
excludePaths:
15-
- src/Tools/Filament
1615
- src/Tools/StripeTool.php
1716

1817
checkOctaneCompatibility: true

src/Tools/CustomTool.php

Lines changed: 70 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -6,127 +6,108 @@
66
use Kirschbaum\Loop\Concerns\Makeable;
77
use Kirschbaum\Loop\Contracts\Tool;
88
use Prism\Prism\Contracts\Schema;
9-
use Prism\Prism\Schema\BooleanSchema;
10-
use Prism\Prism\Schema\NumberSchema;
11-
use Prism\Prism\Schema\ObjectSchema;
12-
use Prism\Prism\Schema\StringSchema;
139
use Prism\Prism\Tool as PrismTool;
1410

1511
class CustomTool implements Tool
1612
{
1713
use Makeable;
1814

15+
private PrismTool $prismTool;
16+
1917
public function __construct(
2018
public readonly string $name,
2119
public readonly string $description,
22-
/** @var array<string, array{type?: string, description?: string, required?: bool}> */
23-
public readonly array $parameters,
24-
public readonly Closure $handler,
25-
) {}
26-
27-
public function build(): PrismTool
28-
{
29-
$tool = app(PrismTool::class)
20+
) {
21+
$this->prismTool = app(PrismTool::class)
3022
->as($this->getName())
3123
->for($this->description);
24+
}
3225

33-
$this->buildParameters($tool);
34-
35-
return $tool->using($this->handler);
26+
public function build(): PrismTool
27+
{
28+
return $this->prismTool;
3629
}
3730

3831
public function getName(): string
3932
{
4033
return $this->name;
4134
}
4235

43-
private function buildParameters(PrismTool $tool): void
36+
public function using(Closure|callable $handler): self
4437
{
45-
foreach ($this->parameters as $name => $config) {
46-
$type = $config['type'] ?? 'string';
47-
$description = $config['description'] ?? '';
48-
$required = $config['required'] ?? false;
49-
50-
match ($type) {
51-
'string' => $tool->withStringParameter($name, $description, required: $required),
52-
'integer', 'number' => $tool->withNumberParameter($name, $description, required: $required),
53-
'boolean' => $tool->withBooleanParameter($name, $description, required: $required),
54-
'object' => $this->buildObjectParameter($tool, $name, $config),
55-
default => $tool->withStringParameter($name, $description, required: $required),
56-
};
57-
}
38+
$this->prismTool->using(fn: $handler);
39+
40+
return $this;
5841
}
5942

60-
/**
61-
* @param array<string, mixed> $config
62-
*/
63-
private function buildObjectParameter(PrismTool $tool, string $name, array $config): void
64-
{
65-
/** @var string $description */
66-
$description = $config['description'] ?? '';
43+
public function withArrayParameter(
44+
string $name,
45+
string $description,
46+
Schema $items,
47+
bool $required = true,
48+
): self {
49+
$this->prismTool->withArrayParameter($name, $description, $items, $required);
6750

68-
/** @var bool $required */
69-
$required = $config['required'] ?? false;
51+
return $this;
52+
}
7053

71-
/** @var array<string, array<string, mixed>> $properties */
72-
$properties = $config['properties'] ?? [];
54+
public function withBooleanParameter(string $name, string $description, bool $required = true): self
55+
{
56+
$this->prismTool->withBooleanParameter($name, $description, $required);
7357

74-
/** @var array<int, string> $requiredFields */
75-
$requiredFields = $config['required'] ?? [];
58+
return $this;
59+
}
7660

77-
/** @var bool $allowAdditional */
78-
$allowAdditional = $config['allow_additional_properties'] ?? false;
61+
/**
62+
* @param array<int, string|int|float> $options
63+
*/
64+
public function withEnumParameter(
65+
string $name,
66+
string $description,
67+
array $options,
68+
bool $required = true,
69+
): self {
70+
$this->prismTool->withEnumParameter($name, $description, $options, $required);
71+
72+
return $this;
73+
}
7974

80-
$schemaProperties = $this->buildSchemaArray($properties);
75+
public function withNumberParameter(string $name, string $description, bool $required = true): self
76+
{
77+
$this->prismTool->withNumberParameter($name, $description, $required);
8178

82-
$tool->withObjectParameter(
83-
name: $name,
84-
description: $description,
85-
properties: $schemaProperties,
86-
requiredFields: $requiredFields,
87-
allowAdditionalProperties: $allowAdditional,
88-
required: $required
89-
);
79+
return $this;
9080
}
9181

9282
/**
93-
* @param array<string, array<string, mixed>> $parameters
94-
* @return array<Schema>
83+
* @param array<int, Schema> $properties
84+
* @param array<int, string> $requiredFields
9585
*/
96-
private function buildSchemaArray(array $parameters): array
86+
public function withObjectParameter(
87+
string $name,
88+
string $description,
89+
array $properties,
90+
array $requiredFields = [],
91+
bool $allowAdditionalProperties = false,
92+
bool $required = true,
93+
): self {
94+
95+
$this->prismTool->withObjectParameter($name, $description, $properties, $requiredFields, $allowAdditionalProperties, $required);
96+
97+
return $this;
98+
}
99+
100+
public function withParameter(Schema $parameter, bool $required = true): self
101+
{
102+
$this->prismTool->withParameter($parameter, $required);
103+
104+
return $this;
105+
}
106+
107+
public function withStringParameter(string $name, string $description, bool $required = true): self
97108
{
98-
$schemaArray = [];
99-
100-
foreach ($parameters as $name => $config) {
101-
$type = $config['type'] ?? 'string';
102-
103-
/** @var string $description */
104-
$description = $config['description'] ?? '';
105-
106-
/** @var array<string, array<string, mixed>> $properties */
107-
$properties = $config['properties'] ?? [];
108-
109-
/** @var array<int, string> $requiredFields */
110-
$requiredFields = $config['required_fields'] ?? [];
111-
112-
/** @var bool $allowAdditional */
113-
$allowAdditional = $config['allow_additional_properties'] ?? false;
114-
115-
$schemaArray[] = match ($type) {
116-
'string' => new StringSchema($name, $description),
117-
'integer', 'number' => new NumberSchema($name, $description),
118-
'boolean' => new BooleanSchema($name, $description),
119-
'object' => new ObjectSchema(
120-
$name,
121-
$description,
122-
$this->buildSchemaArray($properties),
123-
$requiredFields,
124-
$allowAdditional,
125-
),
126-
default => new StringSchema($name, $description),
127-
};
128-
}
129-
130-
return $schemaArray;
109+
$this->prismTool->withStringParameter($name, $description, $required);
110+
111+
return $this;
131112
}
132113
}

0 commit comments

Comments
 (0)