trickle-cli 0.1.202 → 0.1.204
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.
|
@@ -156,6 +156,8 @@ function costReportCommand(opts) {
|
|
|
156
156
|
['claude-opus', 'frontier'], ['claude-sonnet', 'standard'], ['claude-haiku', 'mini'],
|
|
157
157
|
['gemini-2.5-flash-lite', 'mini'], ['gemini-2.5-flash', 'standard'], ['gemini-2.5-pro', 'frontier'],
|
|
158
158
|
['gemini-2.0-flash', 'mini'], ['gemini-1.5-pro', 'frontier'], ['gemini-1.5-flash', 'mini'],
|
|
159
|
+
['mistral-large', 'frontier'], ['mistral-medium', 'standard'], ['mistral-small', 'mini'], ['codestral', 'standard'],
|
|
160
|
+
['command-r-plus', 'frontier'], ['command-r', 'standard'], ['command-light', 'mini'],
|
|
159
161
|
];
|
|
160
162
|
function classifyTier(model) {
|
|
161
163
|
for (const [pattern, tier] of TIER_RULES) {
|
package/dist/commands/monitor.js
CHANGED
|
@@ -456,6 +456,39 @@ function analyzeLlmCalls(trickleDir) {
|
|
|
456
456
|
suggestion: `Large prompts increase cost and latency. Consider chunking input, using summarization, or reducing context window.`,
|
|
457
457
|
});
|
|
458
458
|
}
|
|
459
|
+
// 4. Structured output validation — detect malformed JSON in LLM outputs
|
|
460
|
+
let malformedCount = 0;
|
|
461
|
+
const malformedExamples = [];
|
|
462
|
+
for (const c of calls) {
|
|
463
|
+
const output = c.outputPreview || '';
|
|
464
|
+
if (!output || c.error)
|
|
465
|
+
continue;
|
|
466
|
+
// Detect if output looks like it was supposed to be JSON but isn't valid
|
|
467
|
+
const trimmed = output.trim();
|
|
468
|
+
if (trimmed.startsWith('{') || trimmed.startsWith('[') || trimmed.startsWith('```json')) {
|
|
469
|
+
let jsonStr = trimmed;
|
|
470
|
+
if (jsonStr.startsWith('```json'))
|
|
471
|
+
jsonStr = jsonStr.replace(/^```json\s*/, '').replace(/```$/, '').trim();
|
|
472
|
+
try {
|
|
473
|
+
JSON.parse(jsonStr);
|
|
474
|
+
}
|
|
475
|
+
catch {
|
|
476
|
+
malformedCount++;
|
|
477
|
+
if (malformedExamples.length < 3) {
|
|
478
|
+
malformedExamples.push(`${c.model}: "${trimmed.substring(0, 60)}..."`);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (malformedCount > 0) {
|
|
484
|
+
alerts.push({
|
|
485
|
+
kind: 'alert', severity: 'warning', category: 'llm_malformed_json',
|
|
486
|
+
message: `${malformedCount} LLM response(s) contain malformed JSON`,
|
|
487
|
+
details: { count: malformedCount, examples: malformedExamples },
|
|
488
|
+
timestamp: Date.now(),
|
|
489
|
+
suggestion: `LLM returned JSON-like output that doesn't parse. Use structured output mode (response_format: {type: "json_object"}) or add output validation.`,
|
|
490
|
+
});
|
|
491
|
+
}
|
|
459
492
|
return alerts;
|
|
460
493
|
}
|
|
461
494
|
function analyzeAgentEvents(trickleDir) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trickle-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.204",
|
|
4
4
|
"description": "Zero-code runtime observability for JS/Python + AI agent debugging. Traces LangChain, CrewAI, OpenAI, Anthropic, Gemini. Eval, security, compliance, cost tracking. Free, local-first.",
|
|
5
5
|
"keywords": ["observability", "tracing", "llm", "openai", "anthropic", "langchain", "crewai", "agent", "mcp", "debugging", "typescript", "python", "security", "eval", "compliance"],
|
|
6
6
|
"bin": {
|
|
@@ -131,6 +131,8 @@ export function costReportCommand(opts: { json?: boolean; budget?: string }): vo
|
|
|
131
131
|
['claude-opus', 'frontier'], ['claude-sonnet', 'standard'], ['claude-haiku', 'mini'],
|
|
132
132
|
['gemini-2.5-flash-lite', 'mini'], ['gemini-2.5-flash', 'standard'], ['gemini-2.5-pro', 'frontier'],
|
|
133
133
|
['gemini-2.0-flash', 'mini'], ['gemini-1.5-pro', 'frontier'], ['gemini-1.5-flash', 'mini'],
|
|
134
|
+
['mistral-large', 'frontier'], ['mistral-medium', 'standard'], ['mistral-small', 'mini'], ['codestral', 'standard'],
|
|
135
|
+
['command-r-plus', 'frontier'], ['command-r', 'standard'], ['command-light', 'mini'],
|
|
134
136
|
];
|
|
135
137
|
|
|
136
138
|
function classifyTier(model: string): string {
|
package/src/commands/monitor.ts
CHANGED
|
@@ -481,6 +481,37 @@ function analyzeLlmCalls(trickleDir: string): Alert[] {
|
|
|
481
481
|
});
|
|
482
482
|
}
|
|
483
483
|
|
|
484
|
+
// 4. Structured output validation — detect malformed JSON in LLM outputs
|
|
485
|
+
let malformedCount = 0;
|
|
486
|
+
const malformedExamples: string[] = [];
|
|
487
|
+
for (const c of calls) {
|
|
488
|
+
const output = c.outputPreview || '';
|
|
489
|
+
if (!output || c.error) continue;
|
|
490
|
+
// Detect if output looks like it was supposed to be JSON but isn't valid
|
|
491
|
+
const trimmed = output.trim();
|
|
492
|
+
if (trimmed.startsWith('{') || trimmed.startsWith('[') || trimmed.startsWith('```json')) {
|
|
493
|
+
let jsonStr = trimmed;
|
|
494
|
+
if (jsonStr.startsWith('```json')) jsonStr = jsonStr.replace(/^```json\s*/, '').replace(/```$/, '').trim();
|
|
495
|
+
try {
|
|
496
|
+
JSON.parse(jsonStr);
|
|
497
|
+
} catch {
|
|
498
|
+
malformedCount++;
|
|
499
|
+
if (malformedExamples.length < 3) {
|
|
500
|
+
malformedExamples.push(`${c.model}: "${trimmed.substring(0, 60)}..."`);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (malformedCount > 0) {
|
|
506
|
+
alerts.push({
|
|
507
|
+
kind: 'alert', severity: 'warning', category: 'llm_malformed_json',
|
|
508
|
+
message: `${malformedCount} LLM response(s) contain malformed JSON`,
|
|
509
|
+
details: { count: malformedCount, examples: malformedExamples },
|
|
510
|
+
timestamp: Date.now(),
|
|
511
|
+
suggestion: `LLM returned JSON-like output that doesn't parse. Use structured output mode (response_format: {type: "json_object"}) or add output validation.`,
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
|
|
484
515
|
return alerts;
|
|
485
516
|
}
|
|
486
517
|
|