promptmetrics-sample 1.0.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/.env.example +12 -0
- package/README.md +235 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/tests/logs.test.d.ts +7 -0
- package/dist/tests/logs.test.d.ts.map +1 -0
- package/dist/tests/logs.test.js +163 -0
- package/dist/tests/logs.test.js.map +1 -0
- package/dist/tests/providers.test.d.ts +7 -0
- package/dist/tests/providers.test.d.ts.map +1 -0
- package/dist/tests/providers.test.js +99 -0
- package/dist/tests/providers.test.js.map +1 -0
- package/dist/tests/tags.test.d.ts +7 -0
- package/dist/tests/tags.test.d.ts.map +1 -0
- package/dist/tests/tags.test.js +220 -0
- package/dist/tests/tags.test.js.map +1 -0
- package/dist/tests/template-run-load.test.d.ts +11 -0
- package/dist/tests/template-run-load.test.d.ts.map +1 -0
- package/dist/tests/template-run-load.test.js +245 -0
- package/dist/tests/template-run-load.test.js.map +1 -0
- package/dist/tests/templates.test.d.ts +7 -0
- package/dist/tests/templates.test.d.ts.map +1 -0
- package/dist/tests/templates.test.js +152 -0
- package/dist/tests/templates.test.js.map +1 -0
- package/dist/tests/traceable.test.d.ts +7 -0
- package/dist/tests/traceable.test.d.ts.map +1 -0
- package/dist/tests/traceable.test.js +300 -0
- package/dist/tests/traceable.test.js.map +1 -0
- package/dist/tests/traces.test.d.ts +7 -0
- package/dist/tests/traces.test.d.ts.map +1 -0
- package/dist/tests/traces.test.js +264 -0
- package/dist/tests/traces.test.js.map +1 -0
- package/dist/tests/versions.test.d.ts +7 -0
- package/dist/tests/versions.test.d.ts.map +1 -0
- package/dist/tests/versions.test.js +145 -0
- package/dist/tests/versions.test.js.map +1 -0
- package/dist/utils/logger.d.ts +26 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +79 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +36 -0
- package/sample-project-plan.md +316 -0
- package/src/index.ts +36 -0
- package/src/tests/logs.test.ts +180 -0
- package/src/tests/providers.test.ts +99 -0
- package/src/tests/tags.test.ts +237 -0
- package/src/tests/template-run-load.test.ts +332 -0
- package/src/tests/templates.test.ts +154 -0
- package/src/tests/traceable.test.ts +290 -0
- package/src/tests/traces.test.ts +298 -0
- package/src/tests/versions.test.ts +155 -0
- package/src/utils/logger.ts +91 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
/**
|
|
3
|
+
* Template Run Load Test
|
|
4
|
+
* Configurable load testing for canary deployments
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npm run test:load -- --requests=1000 --concurrency=50
|
|
8
|
+
* npm run test:load -- --template=my-template --requests=500
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import "dotenv/config";
|
|
12
|
+
import { PromptMetrics } from "@promptmetrics/sdk";
|
|
13
|
+
import { logger } from "../utils/logger";
|
|
14
|
+
|
|
15
|
+
// Configuration interface
|
|
16
|
+
interface LoadTestConfig {
|
|
17
|
+
templateIdentifier: string;
|
|
18
|
+
requestCount: number;
|
|
19
|
+
concurrency: number;
|
|
20
|
+
errorRate: number; // 0-1, percentage of requests that should fail
|
|
21
|
+
delayMs?: number; // Delay between batches
|
|
22
|
+
variables?: Record<string, any>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Parse command line arguments
|
|
26
|
+
function parseArgs(): Partial<LoadTestConfig> {
|
|
27
|
+
const args = process.argv.slice(2);
|
|
28
|
+
const config: Partial<LoadTestConfig> = {};
|
|
29
|
+
|
|
30
|
+
args.forEach((arg) => {
|
|
31
|
+
const [key, value] = arg.replace("--", "").split("=");
|
|
32
|
+
switch (key) {
|
|
33
|
+
case "template":
|
|
34
|
+
config.templateIdentifier = value;
|
|
35
|
+
break;
|
|
36
|
+
case "requests":
|
|
37
|
+
config.requestCount = parseInt(value);
|
|
38
|
+
break;
|
|
39
|
+
case "concurrency":
|
|
40
|
+
config.concurrency = parseInt(value);
|
|
41
|
+
break;
|
|
42
|
+
case "error-rate":
|
|
43
|
+
config.errorRate = parseFloat(value);
|
|
44
|
+
break;
|
|
45
|
+
case "delay":
|
|
46
|
+
config.delayMs = parseInt(value);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return config;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Default configuration
|
|
55
|
+
const defaultConfig: LoadTestConfig = {
|
|
56
|
+
templateIdentifier: process.env.TEST_TEMPLATE_NAME || "test-template",
|
|
57
|
+
requestCount: 100,
|
|
58
|
+
concurrency: 10,
|
|
59
|
+
errorRate: 0,
|
|
60
|
+
delayMs: 0,
|
|
61
|
+
variables: {},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Merge with CLI args
|
|
65
|
+
const cliConfig = parseArgs();
|
|
66
|
+
const config: LoadTestConfig = { ...defaultConfig, ...cliConfig };
|
|
67
|
+
|
|
68
|
+
// Initialize SDK
|
|
69
|
+
const pm = new PromptMetrics({
|
|
70
|
+
apiKey: process.env.PROMPTMETRICS_API_KEY!,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Metrics tracking
|
|
74
|
+
interface TestMetrics {
|
|
75
|
+
totalRequests: number;
|
|
76
|
+
successfulRequests: number;
|
|
77
|
+
failedRequests: number;
|
|
78
|
+
canaryRequests: number;
|
|
79
|
+
legacyRequests: number;
|
|
80
|
+
errors: Array<{ message: string; timestamp: Date }>;
|
|
81
|
+
responseTimes: number[];
|
|
82
|
+
startTime: Date;
|
|
83
|
+
endTime?: Date;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const metrics: TestMetrics = {
|
|
87
|
+
totalRequests: 0,
|
|
88
|
+
successfulRequests: 0,
|
|
89
|
+
failedRequests: 0,
|
|
90
|
+
canaryRequests: 0,
|
|
91
|
+
legacyRequests: 0,
|
|
92
|
+
errors: [],
|
|
93
|
+
responseTimes: [],
|
|
94
|
+
startTime: new Date(),
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Progress bar
|
|
98
|
+
function renderProgressBar(current: number, total: number): string {
|
|
99
|
+
const percentage = Math.floor((current / total) * 100);
|
|
100
|
+
const barLength = 20;
|
|
101
|
+
const filledLength = Math.floor((current / total) * barLength);
|
|
102
|
+
const bar = "█".repeat(filledLength) + "░".repeat(barLength - filledLength);
|
|
103
|
+
return `[${bar}] ${percentage}% (${current}/${total})`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Single request execution
|
|
107
|
+
async function executeRequest(
|
|
108
|
+
requestId: number
|
|
109
|
+
): Promise<{ success: boolean; responseTime: number; isCanary?: boolean }> {
|
|
110
|
+
const startTime = Date.now();
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
// Simulate error based on error rate
|
|
114
|
+
const shouldFail = Math.random() < config.errorRate;
|
|
115
|
+
|
|
116
|
+
if (shouldFail) {
|
|
117
|
+
throw new Error(`Simulated error for request ${requestId}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Execute template run
|
|
121
|
+
const result = await pm.templates.run(config.templateIdentifier, {
|
|
122
|
+
variables: config.variables,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const responseTime = Date.now() - startTime;
|
|
126
|
+
|
|
127
|
+
// Try to detect if this was a canary request
|
|
128
|
+
// This would need to be exposed by the API or inferred from metadata
|
|
129
|
+
const isCanary = (result as any).metadata?.is_canary;
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
success: true,
|
|
133
|
+
responseTime,
|
|
134
|
+
isCanary,
|
|
135
|
+
};
|
|
136
|
+
} catch (error: any) {
|
|
137
|
+
const responseTime = Date.now() - startTime;
|
|
138
|
+
metrics.errors.push({
|
|
139
|
+
message: error.message || "Unknown error",
|
|
140
|
+
timestamp: new Date(),
|
|
141
|
+
});
|
|
142
|
+
return {
|
|
143
|
+
success: false,
|
|
144
|
+
responseTime,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Execute batch of requests concurrently
|
|
150
|
+
async function executeBatch(
|
|
151
|
+
batchSize: number,
|
|
152
|
+
startIndex: number
|
|
153
|
+
): Promise<void> {
|
|
154
|
+
const promises = [];
|
|
155
|
+
|
|
156
|
+
for (let i = 0; i < batchSize; i++) {
|
|
157
|
+
const requestId = startIndex + i;
|
|
158
|
+
promises.push(executeRequest(requestId));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const results = await Promise.all(promises);
|
|
162
|
+
|
|
163
|
+
// Update metrics
|
|
164
|
+
results.forEach((result) => {
|
|
165
|
+
metrics.totalRequests++;
|
|
166
|
+
metrics.responseTimes.push(result.responseTime);
|
|
167
|
+
|
|
168
|
+
if (result.success) {
|
|
169
|
+
metrics.successfulRequests++;
|
|
170
|
+
if (result.isCanary === true) {
|
|
171
|
+
metrics.canaryRequests++;
|
|
172
|
+
} else if (result.isCanary === false) {
|
|
173
|
+
metrics.legacyRequests++;
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
metrics.failedRequests++;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Main load test execution
|
|
182
|
+
async function runLoadTest(): Promise<void> {
|
|
183
|
+
console.log("\n" + "=".repeat(60));
|
|
184
|
+
console.log("🚀 Template Run Load Test");
|
|
185
|
+
console.log("=".repeat(60));
|
|
186
|
+
console.log(`Template: ${config.templateIdentifier}`);
|
|
187
|
+
console.log(`Requests: ${config.requestCount}`);
|
|
188
|
+
console.log(`Concurrency: ${config.concurrency}`);
|
|
189
|
+
console.log(`Error Rate: ${(config.errorRate * 100).toFixed(1)}%`);
|
|
190
|
+
console.log(`Delay: ${config.delayMs}ms`);
|
|
191
|
+
console.log("=".repeat(60) + "\n");
|
|
192
|
+
|
|
193
|
+
const batches = Math.ceil(config.requestCount / config.concurrency);
|
|
194
|
+
|
|
195
|
+
for (let i = 0; i < batches; i++) {
|
|
196
|
+
const startIndex = i * config.concurrency;
|
|
197
|
+
const remainingRequests = config.requestCount - startIndex;
|
|
198
|
+
const batchSize = Math.min(config.concurrency, remainingRequests);
|
|
199
|
+
|
|
200
|
+
// Execute batch
|
|
201
|
+
await executeBatch(batchSize, startIndex);
|
|
202
|
+
|
|
203
|
+
// Update progress
|
|
204
|
+
process.stdout.write(
|
|
205
|
+
`\rProgress: ${renderProgressBar(
|
|
206
|
+
metrics.totalRequests,
|
|
207
|
+
config.requestCount
|
|
208
|
+
)}`
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
// Delay between batches if configured
|
|
212
|
+
if (config.delayMs && i < batches - 1) {
|
|
213
|
+
await new Promise((resolve) => setTimeout(resolve, config.delayMs));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
metrics.endTime = new Date();
|
|
218
|
+
console.log("\n");
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Calculate and display results
|
|
222
|
+
function displayResults(): void {
|
|
223
|
+
const duration =
|
|
224
|
+
(metrics.endTime!.getTime() - metrics.startTime.getTime()) / 1000;
|
|
225
|
+
const avgResponseTime =
|
|
226
|
+
metrics.responseTimes.reduce((a, b) => a + b, 0) /
|
|
227
|
+
metrics.responseTimes.length || 0;
|
|
228
|
+
const minResponseTime = Math.min(...metrics.responseTimes) || 0;
|
|
229
|
+
const maxResponseTime = Math.max(...metrics.responseTimes) || 0;
|
|
230
|
+
const requestsPerSecond = metrics.totalRequests / duration;
|
|
231
|
+
|
|
232
|
+
console.log("=".repeat(60));
|
|
233
|
+
console.log("📊 Test Results");
|
|
234
|
+
console.log("=".repeat(60));
|
|
235
|
+
|
|
236
|
+
// Request stats
|
|
237
|
+
console.log("\n📈 Request Statistics:");
|
|
238
|
+
console.log(` ✓ Total Requests: ${metrics.totalRequests}`);
|
|
239
|
+
console.log(
|
|
240
|
+
` ✓ Successful: ${metrics.successfulRequests} (${(
|
|
241
|
+
(metrics.successfulRequests / metrics.totalRequests) *
|
|
242
|
+
100
|
|
243
|
+
).toFixed(1)}%)`
|
|
244
|
+
);
|
|
245
|
+
console.log(
|
|
246
|
+
` ✗ Failed: ${metrics.failedRequests} (${(
|
|
247
|
+
(metrics.failedRequests / metrics.totalRequests) *
|
|
248
|
+
100
|
|
249
|
+
).toFixed(1)}%)`
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
// Canary distribution (if available)
|
|
253
|
+
if (metrics.canaryRequests > 0 || metrics.legacyRequests > 0) {
|
|
254
|
+
const totalVersioned = metrics.canaryRequests + metrics.legacyRequests;
|
|
255
|
+
console.log("\n🔀 Traffic Distribution:");
|
|
256
|
+
console.log(
|
|
257
|
+
` 🐤 Canary Requests: ${metrics.canaryRequests} (${(
|
|
258
|
+
(metrics.canaryRequests / totalVersioned) *
|
|
259
|
+
100
|
|
260
|
+
).toFixed(1)}%)`
|
|
261
|
+
);
|
|
262
|
+
console.log(
|
|
263
|
+
` 🏛️ Legacy Requests: ${metrics.legacyRequests} (${(
|
|
264
|
+
(metrics.legacyRequests / totalVersioned) *
|
|
265
|
+
100
|
|
266
|
+
).toFixed(1)}%)`
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Performance stats
|
|
271
|
+
console.log("\n⚡ Performance:");
|
|
272
|
+
console.log(` ⏱️ Duration: ${duration.toFixed(2)}s`);
|
|
273
|
+
console.log(` 📊 Requests/sec: ${requestsPerSecond.toFixed(2)}`);
|
|
274
|
+
console.log(` 📉 Avg Response Time: ${avgResponseTime.toFixed(0)}ms`);
|
|
275
|
+
console.log(` 📊 Min Response Time: ${minResponseTime.toFixed(0)}ms`);
|
|
276
|
+
console.log(` 📊 Max Response Time: ${maxResponseTime.toFixed(0)}ms`);
|
|
277
|
+
|
|
278
|
+
// Error details
|
|
279
|
+
if (metrics.errors.length > 0) {
|
|
280
|
+
console.log("\n❌ Errors:");
|
|
281
|
+
const errorCounts = new Map<string, number>();
|
|
282
|
+
metrics.errors.forEach((error) => {
|
|
283
|
+
const count = errorCounts.get(error.message) || 0;
|
|
284
|
+
errorCounts.set(error.message, count + 1);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
errorCounts.forEach((count, message) => {
|
|
288
|
+
console.log(` • ${message}: ${count} occurrences`);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// Show last 3 errors with timestamps
|
|
292
|
+
console.log("\n Recent Errors:");
|
|
293
|
+
metrics.errors.slice(-3).forEach((error) => {
|
|
294
|
+
console.log(` ${error.timestamp.toISOString()}: ${error.message}`);
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
console.log("\n" + "=".repeat(60));
|
|
299
|
+
|
|
300
|
+
// Validation checks
|
|
301
|
+
console.log("\n✅ Validation:");
|
|
302
|
+
|
|
303
|
+
// Check counter accuracy (if we can query the backend)
|
|
304
|
+
console.log(` ℹ️ Note: Verify backend counters match these numbers`);
|
|
305
|
+
console.log(` Expected total_requests: ${metrics.totalRequests}`);
|
|
306
|
+
console.log(` Expected canary_requests: ${metrics.canaryRequests}`);
|
|
307
|
+
console.log(` Expected legacy_requests: ${metrics.legacyRequests}`);
|
|
308
|
+
|
|
309
|
+
console.log("\n" + "=".repeat(60) + "\n");
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Main execution
|
|
313
|
+
async function main() {
|
|
314
|
+
try {
|
|
315
|
+
await runLoadTest();
|
|
316
|
+
displayResults();
|
|
317
|
+
|
|
318
|
+
// Exit with appropriate code
|
|
319
|
+
if (metrics.failedRequests > 0 && config.errorRate === 0) {
|
|
320
|
+
console.log("⚠️ Test completed with unexpected errors");
|
|
321
|
+
process.exit(1);
|
|
322
|
+
} else {
|
|
323
|
+
console.log("✅ Test completed successfully");
|
|
324
|
+
process.exit(0);
|
|
325
|
+
}
|
|
326
|
+
} catch (error: any) {
|
|
327
|
+
console.error("❌ Load test failed:", error.message);
|
|
328
|
+
process.exit(1);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
main();
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
/**
|
|
3
|
+
* Templates Test Suite
|
|
4
|
+
* Tests all template-related SDK operations
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import "dotenv/config";
|
|
8
|
+
import { PromptMetrics } from "@promptmetrics/sdk";
|
|
9
|
+
import { runTestSuite, logger } from "../utils/logger";
|
|
10
|
+
|
|
11
|
+
const pm = new PromptMetrics({
|
|
12
|
+
apiKey: process.env.PROMPTMETRICS_API_KEY!,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const TEST_TEMPLATE_NAME = process.env.TEST_TEMPLATE_NAME || "test-template";
|
|
16
|
+
const TEST_TEMPLATE_ID = process.env.TEST_TEMPLATE_ID;
|
|
17
|
+
|
|
18
|
+
const tests = [
|
|
19
|
+
{
|
|
20
|
+
name: "Get template by name",
|
|
21
|
+
fn: async () => {
|
|
22
|
+
const template = await pm.templates.get(TEST_TEMPLATE_NAME);
|
|
23
|
+
if (!template) throw new Error("Template not found");
|
|
24
|
+
logger.data("Template ID", template._id);
|
|
25
|
+
logger.data("Template Name", template.name);
|
|
26
|
+
logger.data("Versions Count", template.versions?.length || 0);
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
{
|
|
31
|
+
name: "Get template by ID",
|
|
32
|
+
fn: async () => {
|
|
33
|
+
if (!TEST_TEMPLATE_ID) {
|
|
34
|
+
logger.info("Skipped - TEST_TEMPLATE_ID not set");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const template = await pm.templates.get(TEST_TEMPLATE_ID);
|
|
38
|
+
if (!template) throw new Error("Template not found");
|
|
39
|
+
logger.data("Template ID", template._id);
|
|
40
|
+
logger.data("Template Name", template.name);
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
{
|
|
45
|
+
name: "Get template with specific version number",
|
|
46
|
+
fn: async () => {
|
|
47
|
+
const template = await pm.templates.get(TEST_TEMPLATE_NAME, {
|
|
48
|
+
version: 1,
|
|
49
|
+
});
|
|
50
|
+
if (!template) throw new Error("Template not found");
|
|
51
|
+
logger.data("Template Name", template.name);
|
|
52
|
+
logger.data("Version", template.versions?.[0]?.version || "N/A");
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
{
|
|
57
|
+
name: "Get template with env_label (production)",
|
|
58
|
+
fn: async () => {
|
|
59
|
+
try {
|
|
60
|
+
const template = await pm.templates.get(TEST_TEMPLATE_NAME, {
|
|
61
|
+
env_label: "production",
|
|
62
|
+
});
|
|
63
|
+
if (!template) throw new Error("Template not found");
|
|
64
|
+
logger.data("Template Name", template.name);
|
|
65
|
+
logger.data("Env Label", template.versions?.[0]?.env_label || "N/A");
|
|
66
|
+
} catch (error: unknown) {
|
|
67
|
+
const err = error as { message?: string };
|
|
68
|
+
if (err.message?.includes("not found")) {
|
|
69
|
+
logger.info("No production version found - this is OK");
|
|
70
|
+
} else {
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
{
|
|
78
|
+
name: "List templates with pagination",
|
|
79
|
+
fn: async () => {
|
|
80
|
+
const result = await pm.templates.list({
|
|
81
|
+
page: 1,
|
|
82
|
+
per_page: 10,
|
|
83
|
+
});
|
|
84
|
+
if (!result) throw new Error("Failed to list templates");
|
|
85
|
+
logger.data("Templates Count", result.prompts?.length || 0);
|
|
86
|
+
logger.data("Total", result.total || 0);
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
{
|
|
91
|
+
name: "List templates with search filter",
|
|
92
|
+
fn: async () => {
|
|
93
|
+
const result = await pm.templates.list({
|
|
94
|
+
search: TEST_TEMPLATE_NAME.substring(0, 4), // Search with partial name
|
|
95
|
+
page: 1,
|
|
96
|
+
per_page: 10,
|
|
97
|
+
});
|
|
98
|
+
if (!result) throw new Error("Failed to list templates");
|
|
99
|
+
logger.data("Search Results", result.prompts?.length || 0);
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
{
|
|
104
|
+
name: "Run template (canary-aware)",
|
|
105
|
+
fn: async () => {
|
|
106
|
+
const result = await pm.templates.run(TEST_TEMPLATE_NAME, {
|
|
107
|
+
variables: {
|
|
108
|
+
topic: "SDK Template Run Test",
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
if (!result) throw new Error("Run failed");
|
|
113
|
+
logger.data("Request ID", result.request_id);
|
|
114
|
+
logger.data("Status", result.status);
|
|
115
|
+
logger.data("Latency", `${result.latency}s`);
|
|
116
|
+
logger.data("Total Tokens", result.llm_total_tokens);
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
{
|
|
121
|
+
name: "Run template with pm_tags",
|
|
122
|
+
fn: async () => {
|
|
123
|
+
const result = await pm.templates.run(TEST_TEMPLATE_NAME, {
|
|
124
|
+
variables: {
|
|
125
|
+
topic: "Template Tags Test",
|
|
126
|
+
},
|
|
127
|
+
pm_tags: ["template-run-test", "sdk-sample"],
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
if (!result) throw new Error("Run failed");
|
|
131
|
+
logger.data("Request ID", result.request_id);
|
|
132
|
+
logger.data("Status", result.status);
|
|
133
|
+
logger.data("Tags", result.tags || "Not returned");
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
{
|
|
138
|
+
name: "Run template with specific version",
|
|
139
|
+
fn: async () => {
|
|
140
|
+
const result = await pm.templates.run(TEST_TEMPLATE_NAME, {
|
|
141
|
+
version: 1,
|
|
142
|
+
variables: {
|
|
143
|
+
topic: "Specific Version Test",
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
if (!result) throw new Error("Run failed");
|
|
148
|
+
logger.data("Request ID", result.request_id);
|
|
149
|
+
logger.data("Status", result.status);
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
|
|
154
|
+
runTestSuite("Templates Test Suite", tests);
|