taskmonkey-cli 0.2.0 → 0.4.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/bin/tm.js +8 -0
- package/package.json +1 -1
- package/src/commands/optimize-prompt.js +64 -0
- package/src/commands/pull.js +284 -43
package/bin/tm.js
CHANGED
|
@@ -10,6 +10,7 @@ import { logs } from '../src/commands/logs.js';
|
|
|
10
10
|
import { chat } from '../src/commands/chat.js';
|
|
11
11
|
import { testChat } from '../src/commands/test-chat.js';
|
|
12
12
|
import { testConversations } from '../src/commands/test-conversations.js';
|
|
13
|
+
import { optimizePrompt } from '../src/commands/optimize-prompt.js';
|
|
13
14
|
|
|
14
15
|
const program = new Command();
|
|
15
16
|
|
|
@@ -72,4 +73,11 @@ program
|
|
|
72
73
|
.option('-v, --verbose', 'Show response excerpts')
|
|
73
74
|
.action(testConversations);
|
|
74
75
|
|
|
76
|
+
program
|
|
77
|
+
.command('optimize-prompt')
|
|
78
|
+
.description('Analyze test failures and suggest prompt improvements via GPT-4')
|
|
79
|
+
.option('-t, --task <slug>', 'Monkey task slug')
|
|
80
|
+
.option('-m, --model <model>', 'OpenAI model', 'gpt-4o')
|
|
81
|
+
.action(optimizePrompt);
|
|
82
|
+
|
|
75
83
|
program.parse();
|
package/package.json
CHANGED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { createClient } from '../lib/api.js';
|
|
4
|
+
|
|
5
|
+
export async function optimizePrompt(options) {
|
|
6
|
+
const client = createClient();
|
|
7
|
+
|
|
8
|
+
const spinner = ora('Running tests and analyzing...').start();
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
const result = await client.post('/api/test/optimize-prompt', {
|
|
12
|
+
task: options.task || null,
|
|
13
|
+
model: options.model || 'gpt-4o',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
spinner.stop();
|
|
17
|
+
|
|
18
|
+
// Test results
|
|
19
|
+
const rate = result.rate || (result.total > 0 ? Math.round((result.passed / result.total) * 100) : 100);
|
|
20
|
+
const rateColor = rate === 100 ? chalk.green : rate >= 70 ? chalk.yellow : chalk.red;
|
|
21
|
+
console.log(rateColor(`${result.passed}/${result.total} bestanden (${rate}%)`));
|
|
22
|
+
|
|
23
|
+
if (result.passed === result.total) {
|
|
24
|
+
console.log(chalk.green('\nAlle Tests bestanden — kein Optimierungsbedarf.'));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Show failures
|
|
29
|
+
if (result.failures?.length > 0) {
|
|
30
|
+
console.log(chalk.red(`\n${result.failures.length} fehlgeschlagen:`));
|
|
31
|
+
for (const f of result.failures) {
|
|
32
|
+
console.log(chalk.red(` ✗ ${f.test}`));
|
|
33
|
+
for (const err of f.errors) {
|
|
34
|
+
console.log(chalk.gray(` ${err}`));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Show suggestion
|
|
40
|
+
if (result.suggestion?.reasoning) {
|
|
41
|
+
console.log(chalk.cyan('\n━━━ GPT-4 Optimierungsvorschlag ━━━\n'));
|
|
42
|
+
console.log(chalk.white(result.suggestion.reasoning));
|
|
43
|
+
|
|
44
|
+
if (result.suggestion.changes?.length > 0) {
|
|
45
|
+
console.log(chalk.cyan('\nÄnderungen:'));
|
|
46
|
+
for (const change of result.suggestion.changes) {
|
|
47
|
+
console.log(chalk.white(` • ${change}`));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (result.suggestion.new_prompt) {
|
|
52
|
+
console.log(chalk.cyan('\n━━━ Neuer Prompt ━━━\n'));
|
|
53
|
+
console.log(chalk.gray(result.suggestion.new_prompt));
|
|
54
|
+
console.log(chalk.cyan('\n━━━━━━━━━━━━━━━━━━━━\n'));
|
|
55
|
+
console.log(chalk.yellow('Tipp: Kopiere den Prompt in deine Config, dann:'));
|
|
56
|
+
console.log(chalk.gray(' tm sync && tm test-conversations'));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
} catch (err) {
|
|
61
|
+
spinner.fail(err.message);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
}
|
package/src/commands/pull.js
CHANGED
|
@@ -55,6 +55,14 @@ export async function pull() {
|
|
|
55
55
|
written++;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
// Create AGENTS.md (for Codex, Copilot, etc.) if it doesn't exist
|
|
59
|
+
const agentsMdPath = join(config._configDir, 'AGENTS.md');
|
|
60
|
+
if (!existsSync(agentsMdPath)) {
|
|
61
|
+
writeFileSync(agentsMdPath, generateAgentsMd(config.tenant));
|
|
62
|
+
console.log(chalk.cyan(` AGENTS.md (created)`));
|
|
63
|
+
written++;
|
|
64
|
+
}
|
|
65
|
+
|
|
58
66
|
// Install Claude Code skills to .claude/commands/
|
|
59
67
|
const skillsInstalled = installSkills(config._configDir);
|
|
60
68
|
written += skillsInstalled;
|
|
@@ -90,76 +98,309 @@ function installSkills(targetDir) {
|
|
|
90
98
|
function generateClaudeMd(tenant) {
|
|
91
99
|
return `# TaskMonkey Tenant: ${tenant}
|
|
92
100
|
|
|
93
|
-
|
|
101
|
+
Willkommen! Du arbeitest an der Konfiguration des **${tenant}**-Tenants auf der TaskMonkey-Plattform.
|
|
102
|
+
TaskMonkey ist eine KI-Chat-Plattform mit konfigurierbaren Tools, Prompts und Monkey Tasks.
|
|
103
|
+
|
|
104
|
+
## Erste Schritte
|
|
105
|
+
|
|
106
|
+
1. Lies \`docs/TenantConfig.md\` — die vollständige Referenz aller Config-Keys
|
|
107
|
+
2. Schau dir die bestehenden Dateien an, besonders \`monkey_tasks/\` und \`prompts/\`
|
|
108
|
+
3. Starte \`tm watch\` in einem separaten Terminal für Auto-Sync
|
|
109
|
+
4. Teste Änderungen mit \`tm chat\` oder \`tm test-chat "deine nachricht"\`
|
|
110
|
+
|
|
111
|
+
## CLI Befehle (\`tm\`)
|
|
94
112
|
|
|
95
|
-
|
|
96
|
-
|
|
113
|
+
| Befehl | Beschreibung |
|
|
114
|
+
|--------|-------------|
|
|
115
|
+
| \`tm pull\` | Config-Dateien vom Server herunterladen |
|
|
116
|
+
| \`tm sync\` | Lokale Dateien zum Server hochladen |
|
|
117
|
+
| \`tm watch\` | Auto-Sync bei Dateiänderung (in separatem Terminal laufen lassen) |
|
|
118
|
+
| \`tm chat\` | Interaktiver Chat im Terminal |
|
|
119
|
+
| \`tm chat --task inventur\` | Chat mit spezifischem Monkey Task |
|
|
120
|
+
| \`tm chat --public\` | Öffentlicher Chat (wie Endkunde) |
|
|
121
|
+
| \`tm test-tool <name> key=value\` | Einzelnes Tool testen |
|
|
122
|
+
| \`tm test-chat "nachricht"\` | Einzelne Chat-Nachricht testen |
|
|
123
|
+
| \`tm test-conversations\` | Alle conversation_tests ausführen |
|
|
124
|
+
| \`tm optimize-prompt\` | GPT-4 analysiert Test-Failures und schlägt Prompt-Verbesserungen vor |
|
|
125
|
+
| \`tm logs\` | Server-Logs live streamen |
|
|
97
126
|
|
|
98
127
|
## Verzeichnisstruktur
|
|
99
128
|
|
|
100
129
|
\`\`\`
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
130
|
+
monkey_tasks/ # Monkey Task Definitionen
|
|
131
|
+
inventur.php # Name, Tools, Prompt, sheetView etc.
|
|
132
|
+
wareneingang.php # Jeder Task in einer Datei
|
|
133
|
+
prompts/ # Allgemeine Prompts
|
|
134
|
+
system.php # System-Prompt für öffentlichen Chat
|
|
135
|
+
first_message.php # Begrüßungsnachricht
|
|
106
136
|
tools/ # Tool-Konfigurationen
|
|
107
|
-
jtl/
|
|
108
|
-
|
|
109
|
-
google_sheets/ # Google Sheets Tools
|
|
110
|
-
support/ # Support Tools
|
|
137
|
+
jtl/items/ # z.B. searchItems.php, updateStock.php
|
|
138
|
+
google_sheets/ # z.B. readFromGoogleSheet.php
|
|
111
139
|
scan.php # Barcode/QR Scanner Konfiguration
|
|
112
|
-
apis.php # API-Verbindungen
|
|
140
|
+
apis.php # API-Verbindungen
|
|
141
|
+
docs/ # Dokumentation (TenantConfig.md, ToolRunner.md)
|
|
142
|
+
.tmrc # Login-Daten (NICHT committen!)
|
|
113
143
|
\`\`\`
|
|
114
144
|
|
|
115
|
-
## CLI Befehle
|
|
116
|
-
|
|
117
|
-
\`\`\`bash
|
|
118
|
-
tm login # Einloggen und Tenant wählen
|
|
119
|
-
tm pull # Config-Dateien vom Server herunterladen
|
|
120
|
-
tm sync # Lokale Dateien zum Server hochladen
|
|
121
|
-
tm watch # Auto-Sync bei Dateiänderung
|
|
122
|
-
tm test-tool <name> [key=value ...] # Tool auf dem Server testen
|
|
123
|
-
tm test-tool <name> --dry-run # Tool im Simulationsmodus testen
|
|
124
|
-
tm logs # Server-Logs live streamen
|
|
125
|
-
\`\`\`
|
|
126
|
-
|
|
127
|
-
## Workflow
|
|
128
|
-
|
|
129
|
-
1. **Datei bearbeiten** — z.B. einen Prompt in \`monkey_tasks/inventur.php\` ändern
|
|
130
|
-
2. **Synchronisieren** — \`tm sync\` oder \`tm watch\` für Auto-Sync
|
|
131
|
-
3. **Testen** — Im Chat ausprobieren oder \`tm test-tool\` für direktes Tool-Testing
|
|
132
|
-
4. **Logs prüfen** — \`tm logs\` bei Problemen
|
|
133
|
-
|
|
134
145
|
## Config-Format
|
|
135
146
|
|
|
136
|
-
Jede .php Datei gibt ein Array
|
|
147
|
+
Jede .php Datei gibt ein Array mit Dot-Notation Keys zurück:
|
|
137
148
|
|
|
138
149
|
\`\`\`php
|
|
139
150
|
<?php
|
|
140
151
|
return [
|
|
141
152
|
'monkey_tasks.inventur' => [
|
|
142
153
|
'name' => 'Inventur',
|
|
143
|
-
'description' => 'Lagerbestand erfassen',
|
|
154
|
+
'description' => 'Lagerbestand erfassen und aktualisieren',
|
|
144
155
|
'icon' => '✅',
|
|
145
|
-
'tools' => ['searchItems', '
|
|
156
|
+
'tools' => ['searchItems', 'getStockBySku', 'updateStock'],
|
|
146
157
|
],
|
|
147
158
|
'monkey_tasks.inventur.prompt' => <<<'PROMPT'
|
|
148
|
-
Du bist der Inventur-Assistent
|
|
159
|
+
Du bist der Inventur-Assistent.
|
|
160
|
+
Wenn der User eine SKU oder einen Artikelnamen nennt, suche mit searchItems.
|
|
149
161
|
PROMPT,
|
|
150
162
|
];
|
|
151
163
|
\`\`\`
|
|
152
164
|
|
|
153
|
-
|
|
165
|
+
## Tool-Konfiguration
|
|
166
|
+
|
|
167
|
+
Tools können auf drei Arten definiert werden:
|
|
168
|
+
|
|
169
|
+
### 1. API-Only (einfache API-Calls)
|
|
170
|
+
\`\`\`php
|
|
171
|
+
'tools.getCustomer' => [
|
|
172
|
+
'api' => 'jtl',
|
|
173
|
+
'endpoint' => 'customers/{customerId}',
|
|
174
|
+
'method' => 'GET',
|
|
175
|
+
'description' => 'Holt Kundendaten',
|
|
176
|
+
'parameters' => [
|
|
177
|
+
'type' => 'object',
|
|
178
|
+
'properties' => [
|
|
179
|
+
'customerId' => ['type' => 'integer'],
|
|
180
|
+
],
|
|
181
|
+
'required' => ['customerId'],
|
|
182
|
+
],
|
|
183
|
+
],
|
|
184
|
+
\`\`\`
|
|
185
|
+
|
|
186
|
+
### 2. API + Pre/Postprocess
|
|
187
|
+
\`\`\`php
|
|
188
|
+
'tools.getOrderItems' => [
|
|
189
|
+
'api' => 'jtl',
|
|
190
|
+
'endpoint' => 'salesOrders/{orderId}/lineitems',
|
|
191
|
+
'method' => 'GET',
|
|
192
|
+
'preprocess' => function(array \\$args, array \\$ctx): array {
|
|
193
|
+
// Lookup oder Validierung vor dem API-Call
|
|
194
|
+
return ['orderId' => \\$ctx['tool']('verifyOrder', \\$args)['orderId']];
|
|
195
|
+
},
|
|
196
|
+
'postprocess' => function(array \\$results, array \\$args, array \\$ctx): array {
|
|
197
|
+
// Ergebnis filtern/transformieren
|
|
198
|
+
return ['items' => array_filter(\\$results, fn(\\$i) => \\$i['Type'] === 1)];
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
\`\`\`
|
|
202
|
+
|
|
203
|
+
### 3. Handler (komplexe Logik)
|
|
204
|
+
\`\`\`php
|
|
205
|
+
'tools.myCustomTool' => [
|
|
206
|
+
'description' => 'Beschreibung für die KI',
|
|
207
|
+
'internal' => true,
|
|
208
|
+
'handler' => function(array \\$results, array \\$args, array \\$ctx): array {
|
|
209
|
+
\\$logger = \\$ctx['logger'];
|
|
210
|
+
\\$logger->info("Starte...");
|
|
211
|
+
|
|
212
|
+
// Andere Tools aufrufen
|
|
213
|
+
\\$item = \\$ctx['tool']('searchItems', ['searchSku' => \\$args['sku']]);
|
|
214
|
+
|
|
215
|
+
// API-Calls via Cake HTTP Client
|
|
216
|
+
\\$api = \\$ctx['config']['apis']['jtl'];
|
|
217
|
+
\\$http = new \\Cake\\Http\\Client(['timeout' => 60]);
|
|
218
|
+
\\$response = \\$http->get(\\$api['base_url'] . '/items', [], ['headers' => \\$api['headers']]);
|
|
219
|
+
|
|
220
|
+
\\$logger->success("Fertig");
|
|
221
|
+
return ['success' => true, 'data' => \\$response->getJson()];
|
|
222
|
+
},
|
|
223
|
+
'parameters' => [
|
|
224
|
+
'type' => 'object',
|
|
225
|
+
'properties' => [
|
|
226
|
+
'sku' => ['type' => 'string', 'description' => 'Artikel-SKU'],
|
|
227
|
+
],
|
|
228
|
+
'required' => ['sku'],
|
|
229
|
+
],
|
|
230
|
+
],
|
|
231
|
+
\`\`\`
|
|
232
|
+
|
|
233
|
+
## Verfügbare Tool-Handler-Klassen
|
|
234
|
+
|
|
235
|
+
Diese PHP-Klassen stehen als Handler zur Verfügung (Referenz: \`[ClassName, 'methodName']\`):
|
|
236
|
+
|
|
237
|
+
| Klasse | Methoden | Beschreibung |
|
|
238
|
+
|--------|----------|-------------|
|
|
239
|
+
| \`JtlTools\` | searchItems, findBySku, getStockBySku, updateStock, verifyOrder, getOrderLineItems, ... | JTL Wawi API (Artikel, Bestellungen, Lager) |
|
|
240
|
+
| \`GoogleSheetsTools\` | readFromGoogleSheet, writeToGoogleSheet | Google Sheets lesen/schreiben |
|
|
241
|
+
| \`GoogleDriveTools\` | listFiles, readFile, uploadFile, createFile, searchFiles | Google Drive |
|
|
242
|
+
| \`BankingTools\` | getBalance, searchTransactions, listAccounts, matchInvoiceData | Banking/FinAPI |
|
|
243
|
+
| \`DropboxTools\` | uploadToDropbox, listDropboxFiles, readDropboxFile | Dropbox |
|
|
244
|
+
| \`PdfTools\` | extractInvoiceFromPdf, extractTextFromPdf | PDF-Verarbeitung |
|
|
245
|
+
| \`DatabaseGatewayTools\` | deployGateway, executeQuery, removeGateway | Remote-SQL via temporärem Gateway |
|
|
246
|
+
| \`BloomifyTools\` | getProducts, createComplaint, createSupportRequest | Bloomify-spezifisch |
|
|
247
|
+
| \`SuggestionsTools\` | setSuggestions | Chat-Suggestions setzen |
|
|
248
|
+
|
|
249
|
+
## Handler-Kontext (\`\\$ctx\`)
|
|
250
|
+
|
|
251
|
+
Jeder Handler bekommt einen Kontext mit:
|
|
252
|
+
|
|
253
|
+
\`\`\`php
|
|
254
|
+
\\$ctx['config'] // Tenant-Konfiguration (APIs, Tools, etc.)
|
|
255
|
+
\\$ctx['tenant'] // Tenant-Code (z.B. "bloomify")
|
|
256
|
+
\\$ctx['logger'] // TaskLogger: ->info(), ->success(), ->error(), ->warning()
|
|
257
|
+
\\$ctx['tool'] // Funktion zum Aufrufen anderer Tools: \\$ctx['tool']('toolName', \\$args)
|
|
258
|
+
\\$ctx['chat_id'] // Chat-Session ID
|
|
259
|
+
\\$ctx['testMode'] // true wenn im Simulationsmodus
|
|
260
|
+
\`\`\`
|
|
261
|
+
|
|
262
|
+
## Verfügbare Vendor-Libraries
|
|
263
|
+
|
|
264
|
+
\`\`\`php
|
|
265
|
+
\\Cake\\Http\\Client // HTTP-Requests (GET, POST, etc.)
|
|
266
|
+
\\Cake\\Cache\\Cache // Caching (read, write, delete)
|
|
267
|
+
\\Cake\\ORM\\TableRegistry // Datenbank-Zugriff
|
|
268
|
+
\\Cake\\Core\\Configure // App-Konfiguration lesen
|
|
269
|
+
\\Google_Service_Sheets // Google Sheets API
|
|
270
|
+
\\Google_Service_Drive // Google Drive API
|
|
271
|
+
\\GuzzleHttp\\Client // Alternative HTTP-Library
|
|
272
|
+
\`\`\`
|
|
273
|
+
|
|
274
|
+
## Conversation Tests
|
|
275
|
+
|
|
276
|
+
Definiere Tests um Prompt-Änderungen automatisch zu validieren:
|
|
277
|
+
|
|
278
|
+
\`\`\`php
|
|
279
|
+
'conversation_tests' => [
|
|
280
|
+
[
|
|
281
|
+
'description' => 'Erdbeere suchen',
|
|
282
|
+
'user_message' => 'welche erdbeeren habt ihr?',
|
|
283
|
+
'expect_tool_calls' => ['getProducts'],
|
|
284
|
+
'expect_response_contains' => ['Erdbeere', 'Preis'],
|
|
285
|
+
],
|
|
286
|
+
[
|
|
287
|
+
'description' => 'Bestand abfragen',
|
|
288
|
+
'user_message' => 'wie viele Tomaten haben wir?',
|
|
289
|
+
'expect_tool_calls' => ['searchItems', 'getStockBySku'],
|
|
290
|
+
],
|
|
291
|
+
],
|
|
292
|
+
\`\`\`
|
|
293
|
+
|
|
294
|
+
Ausführen: \`tm test-conversations\`
|
|
295
|
+
Optimieren: \`tm optimize-prompt\`
|
|
154
296
|
|
|
155
297
|
## Wichtige Regeln
|
|
156
298
|
|
|
157
|
-
-
|
|
158
|
-
-
|
|
159
|
-
-
|
|
160
|
-
-
|
|
161
|
-
-
|
|
162
|
-
-
|
|
299
|
+
- Nur \`.php\` Dateien werden synchronisiert
|
|
300
|
+
- PHP-Syntax wird vor dem Schreiben auf dem Server geprüft
|
|
301
|
+
- \`.tmrc\` nie committen (enthält Login-Token)
|
|
302
|
+
- \`internal: true\` bei Tools = nur für Monkey Tasks, nicht für öffentliche Chats
|
|
303
|
+
- Handler-Signatur: \`function(array \\$results, array \\$args, array \\$ctx): array\`
|
|
304
|
+
- Immer \`['success' => true/false]\` im Return-Array
|
|
305
|
+
- \`\\$ctx['tool']('name', \\$args)\` für verschachtelte Tool-Aufrufe
|
|
163
306
|
`;
|
|
164
307
|
}
|
|
165
308
|
|
|
309
|
+
function generateAgentsMd(tenant) {
|
|
310
|
+
return `# TaskMonkey Tenant: ${tenant}
|
|
311
|
+
|
|
312
|
+
This directory contains the configuration for the **${tenant}** tenant on the TaskMonkey AI platform.
|
|
313
|
+
Use the \`tm\` CLI to sync changes and test.
|
|
314
|
+
|
|
315
|
+
## Setup
|
|
316
|
+
|
|
317
|
+
\`\`\`bash
|
|
318
|
+
npm install -g taskmonkey-cli
|
|
319
|
+
tm login
|
|
320
|
+
tm pull
|
|
321
|
+
\`\`\`
|
|
322
|
+
|
|
323
|
+
## Commands
|
|
324
|
+
|
|
325
|
+
- \`tm sync\` — Upload local config files to server
|
|
326
|
+
- \`tm watch\` — Auto-sync on file change
|
|
327
|
+
- \`tm test-tool <name> key=value\` — Run a tool on the server
|
|
328
|
+
- \`tm test-chat "message"\` — Test a single chat message
|
|
329
|
+
- \`tm chat\` — Interactive chat REPL
|
|
330
|
+
- \`tm test-conversations\` — Run all conversation tests
|
|
331
|
+
- \`tm optimize-prompt\` — GPT-4 prompt optimization based on test failures
|
|
332
|
+
- \`tm logs\` — Stream server logs
|
|
333
|
+
|
|
334
|
+
## File Structure
|
|
335
|
+
|
|
336
|
+
- \`monkey_tasks/*.php\` — Task definitions (name, tools, prompt)
|
|
337
|
+
- \`prompts/*.php\` — System prompts and greetings
|
|
338
|
+
- \`tools/**/*.php\` — Tool configurations (API calls, handlers)
|
|
339
|
+
- \`docs/TenantConfig.md\` — Full config reference
|
|
340
|
+
|
|
341
|
+
## Config Format
|
|
342
|
+
|
|
343
|
+
Each .php file returns an array with dot-notation keys:
|
|
344
|
+
|
|
345
|
+
\`\`\`php
|
|
346
|
+
<?php
|
|
347
|
+
return [
|
|
348
|
+
'monkey_tasks.myTask' => [
|
|
349
|
+
'name' => 'My Task',
|
|
350
|
+
'tools' => ['searchItems', 'updateStock'],
|
|
351
|
+
],
|
|
352
|
+
'monkey_tasks.myTask.prompt' => <<<'PROMPT'
|
|
353
|
+
You are an assistant that...
|
|
354
|
+
PROMPT,
|
|
355
|
+
];
|
|
356
|
+
\`\`\`
|
|
357
|
+
|
|
358
|
+
## Tool Patterns
|
|
359
|
+
|
|
360
|
+
### API-only
|
|
361
|
+
\`\`\`php
|
|
362
|
+
'tools.getName' => ['api' => 'myapi', 'endpoint' => 'items/{id}', 'method' => 'GET']
|
|
363
|
+
\`\`\`
|
|
364
|
+
|
|
365
|
+
### Handler
|
|
366
|
+
\`\`\`php
|
|
367
|
+
'tools.myTool' => [
|
|
368
|
+
'handler' => function(array $results, array $args, array $ctx): array {
|
|
369
|
+
$item = $ctx['tool']('searchItems', ['searchSku' => $args['sku']]);
|
|
370
|
+
return ['success' => true, 'item' => $item];
|
|
371
|
+
},
|
|
372
|
+
]
|
|
373
|
+
\`\`\`
|
|
374
|
+
|
|
375
|
+
## Available Handler Classes
|
|
376
|
+
|
|
377
|
+
| Class | Key Methods |
|
|
378
|
+
|-------|------------|
|
|
379
|
+
| JtlTools | searchItems, findBySku, getStockBySku, updateStock, verifyOrder |
|
|
380
|
+
| GoogleSheetsTools | readFromGoogleSheet, writeToGoogleSheet |
|
|
381
|
+
| GoogleDriveTools | listFiles, readFile, uploadFile |
|
|
382
|
+
| BankingTools | getBalance, searchTransactions, matchInvoiceData |
|
|
383
|
+
| PdfTools | extractInvoiceFromPdf, extractTextFromPdf |
|
|
384
|
+
| DatabaseGatewayTools | deployGateway, executeQuery |
|
|
385
|
+
|
|
386
|
+
## Handler Context
|
|
387
|
+
|
|
388
|
+
\`\`\`php
|
|
389
|
+
$ctx['config'] // Tenant config (APIs, tools)
|
|
390
|
+
$ctx['tenant'] // Tenant code
|
|
391
|
+
$ctx['logger'] // Logger: ->info(), ->success(), ->error()
|
|
392
|
+
$ctx['tool'] // Call other tools: $ctx['tool']('name', $args)
|
|
393
|
+
\`\`\`
|
|
394
|
+
|
|
395
|
+
## Testing
|
|
396
|
+
|
|
397
|
+
Define conversation tests in config, run with \`tm test-conversations\`:
|
|
398
|
+
|
|
399
|
+
\`\`\`php
|
|
400
|
+
'conversation_tests' => [
|
|
401
|
+
['description' => 'Find product', 'user_message' => 'show me strawberries',
|
|
402
|
+
'expect_tool_calls' => ['getProducts'], 'expect_response_contains' => ['Strawberry']],
|
|
403
|
+
]
|
|
404
|
+
\`\`\`
|
|
405
|
+
`;
|
|
406
|
+
}
|