claude-cli-advanced-starter-pack 1.0.16 → 1.8.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/OVERVIEW.md +5 -1
- package/README.md +241 -132
- package/bin/gtask.js +53 -0
- package/package.json +1 -1
- package/src/cli/menu.js +27 -0
- package/src/commands/explore-mcp/mcp-registry.js +99 -0
- package/src/commands/init.js +309 -80
- package/src/commands/install-panel-hook.js +108 -0
- package/src/commands/install-scripts.js +232 -0
- package/src/commands/install-skill.js +220 -0
- package/src/commands/panel.js +297 -0
- package/src/commands/setup-wizard.js +4 -3
- package/src/commands/test-setup.js +4 -5
- package/src/data/releases.json +209 -0
- package/src/panel/queue.js +188 -0
- package/templates/commands/ask-claude.template.md +118 -0
- package/templates/commands/ccasp-panel.template.md +72 -0
- package/templates/commands/ccasp-setup.template.md +470 -79
- package/templates/commands/create-smoke-test.template.md +186 -0
- package/templates/commands/project-impl.template.md +9 -113
- package/templates/commands/refactor-check.template.md +112 -0
- package/templates/commands/refactor-cleanup.template.md +144 -0
- package/templates/commands/refactor-prep.template.md +192 -0
- package/templates/docs/AI_ARCHITECTURE_CONSTITUTION.template.md +198 -0
- package/templates/docs/DETAILED_GOTCHAS.template.md +347 -0
- package/templates/docs/PHASE-DEV-CHECKLIST.template.md +241 -0
- package/templates/docs/PROGRESS_JSON_TEMPLATE.json +117 -0
- package/templates/docs/background-agent.template.md +264 -0
- package/templates/hooks/autonomous-decision-logger.template.js +207 -0
- package/templates/hooks/branch-merge-checker.template.js +272 -0
- package/templates/hooks/context-injector.template.js +261 -0
- package/templates/hooks/git-commit-tracker.template.js +267 -0
- package/templates/hooks/happy-mode-detector.template.js +214 -0
- package/templates/hooks/happy-title-generator.template.js +260 -0
- package/templates/hooks/issue-completion-detector.template.js +205 -0
- package/templates/hooks/panel-queue-reader.template.js +83 -0
- package/templates/hooks/phase-validation-gates.template.js +307 -0
- package/templates/hooks/session-id-generator.template.js +236 -0
- package/templates/hooks/token-budget-loader.template.js +234 -0
- package/templates/hooks/token-usage-monitor.template.js +193 -0
- package/templates/hooks/tool-output-cacher.template.js +219 -0
- package/templates/patterns/README.md +129 -0
- package/templates/patterns/l1-l2-orchestration.md +189 -0
- package/templates/patterns/multi-phase-orchestration.md +258 -0
- package/templates/patterns/two-tier-query-pipeline.md +192 -0
- package/templates/scripts/README.md +109 -0
- package/templates/scripts/analyze-delegation-log.js +299 -0
- package/templates/scripts/autonomous-decision-logger.js +277 -0
- package/templates/scripts/git-history-analyzer.py +269 -0
- package/templates/scripts/phase-validation-gates.js +307 -0
- package/templates/scripts/poll-deployment-status.js +260 -0
- package/templates/scripts/roadmap-scanner.js +263 -0
- package/templates/scripts/validate-deployment.js +293 -0
- package/templates/skills/agent-creator/skill.json +18 -0
- package/templates/skills/agent-creator/skill.md +335 -0
- package/templates/skills/hook-creator/skill.json +18 -0
- package/templates/skills/hook-creator/skill.md +318 -0
- package/templates/skills/panel/skill.json +18 -0
- package/templates/skills/panel/skill.md +90 -0
- package/templates/skills/rag-agent-creator/skill.json +18 -0
- package/templates/skills/rag-agent-creator/skill.md +307 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Two-Tier Query Pipeline Pattern
|
|
2
|
+
|
|
3
|
+
Intent classification followed by specialized execution.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
A two-tier architecture that separates:
|
|
8
|
+
1. **Tier 1**: Intent classification (what kind of request is this?)
|
|
9
|
+
2. **Tier 2**: Specialized execution (handle based on intent)
|
|
10
|
+
|
|
11
|
+
## When to Use
|
|
12
|
+
|
|
13
|
+
- Multiple types of requests need different handling
|
|
14
|
+
- Request routing is complex
|
|
15
|
+
- You want to add new handlers without changing core logic
|
|
16
|
+
|
|
17
|
+
## Architecture
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
User Request
|
|
21
|
+
↓
|
|
22
|
+
┌──────────────────────┐
|
|
23
|
+
│ Tier 1: Classifier │ (Fast, lightweight)
|
|
24
|
+
│ - Parse intent │
|
|
25
|
+
│ - Extract entities │
|
|
26
|
+
│ - Route to handler │
|
|
27
|
+
└──────────────────────┘
|
|
28
|
+
↓
|
|
29
|
+
┌──────────────────────┐
|
|
30
|
+
│ Tier 2: Handler │ (Specialized, thorough)
|
|
31
|
+
│ - Execute task │
|
|
32
|
+
│ - Return result │
|
|
33
|
+
└──────────────────────┘
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Implementation
|
|
37
|
+
|
|
38
|
+
### Tier 1: Classifier
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
interface ClassificationResult {
|
|
42
|
+
intent: string;
|
|
43
|
+
confidence: number;
|
|
44
|
+
entities: Record<string, string>;
|
|
45
|
+
handler: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function classifyIntent(request: string): Promise<ClassificationResult> {
|
|
49
|
+
// Pattern matching for common intents
|
|
50
|
+
const patterns = {
|
|
51
|
+
'create': /create|add|new|make/i,
|
|
52
|
+
'read': /get|show|list|find|search/i,
|
|
53
|
+
'update': /update|edit|modify|change/i,
|
|
54
|
+
'delete': /delete|remove|destroy/i,
|
|
55
|
+
'analyze': /analyze|check|review|audit/i
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
for (const [intent, pattern] of Object.entries(patterns)) {
|
|
59
|
+
if (pattern.test(request)) {
|
|
60
|
+
return {
|
|
61
|
+
intent,
|
|
62
|
+
confidence: 0.8,
|
|
63
|
+
entities: extractEntities(request),
|
|
64
|
+
handler: `${intent}Handler`
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return { intent: 'unknown', confidence: 0.5, entities: {}, handler: 'fallbackHandler' };
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Tier 2: Handlers
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
const handlers = {
|
|
77
|
+
createHandler: async (entities) => {
|
|
78
|
+
// Launch specialized creation agent
|
|
79
|
+
return Task({
|
|
80
|
+
description: `Create ${entities.type}`,
|
|
81
|
+
prompt: `Create a new ${entities.type} with: ${JSON.stringify(entities)}`,
|
|
82
|
+
subagent_type: 'general-purpose'
|
|
83
|
+
});
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
readHandler: async (entities) => {
|
|
87
|
+
// Launch exploration agent
|
|
88
|
+
return Task({
|
|
89
|
+
description: `Find ${entities.target}`,
|
|
90
|
+
prompt: `Search for ${entities.target} in the codebase`,
|
|
91
|
+
subagent_type: 'Explore'
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
analyzeHandler: async (entities) => {
|
|
96
|
+
// Launch analysis agent
|
|
97
|
+
return Task({
|
|
98
|
+
description: `Analyze ${entities.scope}`,
|
|
99
|
+
prompt: `Perform analysis on ${entities.scope}`,
|
|
100
|
+
subagent_type: 'Plan'
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
fallbackHandler: async (entities) => {
|
|
105
|
+
// Ask for clarification
|
|
106
|
+
return { needsClarification: true, entities };
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Pipeline Execution
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
async function executeQuery(request: string) {
|
|
115
|
+
// Tier 1: Classify
|
|
116
|
+
const classification = await classifyIntent(request);
|
|
117
|
+
|
|
118
|
+
if (classification.confidence < 0.7) {
|
|
119
|
+
// Low confidence - ask for clarification
|
|
120
|
+
return askForClarification(classification);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Tier 2: Execute
|
|
124
|
+
const handler = handlers[classification.handler];
|
|
125
|
+
if (!handler) {
|
|
126
|
+
throw new Error(`Unknown handler: ${classification.handler}`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return handler(classification.entities);
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Example: Command Router
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
// User asks: "Create a new hook for validating file writes"
|
|
137
|
+
|
|
138
|
+
// Tier 1 Classification:
|
|
139
|
+
{
|
|
140
|
+
intent: 'create',
|
|
141
|
+
confidence: 0.9,
|
|
142
|
+
entities: {
|
|
143
|
+
type: 'hook',
|
|
144
|
+
target: 'file writes',
|
|
145
|
+
purpose: 'validation'
|
|
146
|
+
},
|
|
147
|
+
handler: 'createHandler'
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Tier 2 Execution:
|
|
151
|
+
// Launches create-hook skill with extracted parameters
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Benefits
|
|
155
|
+
|
|
156
|
+
1. **Separation of Concerns**: Classification logic is separate from execution
|
|
157
|
+
2. **Extensibility**: Add new handlers without changing classifier
|
|
158
|
+
3. **Testability**: Each tier can be tested independently
|
|
159
|
+
4. **Confidence Handling**: Low-confidence routes can be handled specially
|
|
160
|
+
|
|
161
|
+
## Variations
|
|
162
|
+
|
|
163
|
+
### Multi-Intent
|
|
164
|
+
|
|
165
|
+
Handle requests with multiple intents:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
// "Create a user and send them a welcome email"
|
|
169
|
+
// Intent 1: create user
|
|
170
|
+
// Intent 2: send email
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Fallback Chain
|
|
174
|
+
|
|
175
|
+
Multiple classifiers with fallback:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const classifiers = [patternClassifier, mlClassifier, heuristicClassifier];
|
|
179
|
+
|
|
180
|
+
async function classifyWithFallback(request) {
|
|
181
|
+
for (const classifier of classifiers) {
|
|
182
|
+
const result = await classifier(request);
|
|
183
|
+
if (result.confidence > 0.7) return result;
|
|
184
|
+
}
|
|
185
|
+
return { intent: 'unknown', confidence: 0 };
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Related Patterns
|
|
190
|
+
|
|
191
|
+
- L1→L2 Orchestration
|
|
192
|
+
- Multi-Phase Orchestration
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Utility Scripts Library
|
|
2
|
+
|
|
3
|
+
Standalone scripts for deployment validation, logging analysis, and project health monitoring.
|
|
4
|
+
|
|
5
|
+
## Available Scripts
|
|
6
|
+
|
|
7
|
+
| Script | Purpose | Language |
|
|
8
|
+
|--------|---------|----------|
|
|
9
|
+
| [validate-deployment.js](validate-deployment.js) | Pre-deployment environment validation | Node.js |
|
|
10
|
+
| [poll-deployment-status.js](poll-deployment-status.js) | Poll deployment until complete | Node.js |
|
|
11
|
+
| [roadmap-scanner.js](roadmap-scanner.js) | Multi-roadmap progress dashboard | Node.js |
|
|
12
|
+
| [analyze-delegation-log.js](analyze-delegation-log.js) | Model usage analysis from JSONL logs | Node.js |
|
|
13
|
+
| [autonomous-decision-logger.js](autonomous-decision-logger.js) | JSONL audit trail for agent decisions | Node.js |
|
|
14
|
+
| [phase-validation-gates.js](phase-validation-gates.js) | 5-gate validation before phase transitions | Node.js |
|
|
15
|
+
| [git-history-analyzer.py](git-history-analyzer.py) | Security audit for sensitive data in git | Python |
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
Copy scripts to your project:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Copy all scripts
|
|
23
|
+
cp -r templates/scripts/ .claude/scripts/
|
|
24
|
+
|
|
25
|
+
# Or install via ccasp
|
|
26
|
+
ccasp install-scripts
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
### Pre-Deployment Validation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Validate Railway environment
|
|
35
|
+
node .claude/scripts/validate-deployment.js --platform railway
|
|
36
|
+
|
|
37
|
+
# Validate Cloudflare Pages
|
|
38
|
+
node .claude/scripts/validate-deployment.js --platform cloudflare
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Deployment Polling
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Poll Railway deployment until complete
|
|
45
|
+
node .claude/scripts/poll-deployment-status.js \
|
|
46
|
+
--platform railway \
|
|
47
|
+
--project-id YOUR_PROJECT_ID \
|
|
48
|
+
--timeout 300
|
|
49
|
+
|
|
50
|
+
# Poll Cloudflare Pages deployment
|
|
51
|
+
node .claude/scripts/poll-deployment-status.js \
|
|
52
|
+
--platform cloudflare \
|
|
53
|
+
--project-name your-project
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Roadmap Scanning
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Scan all roadmaps in current directory
|
|
60
|
+
node .claude/scripts/roadmap-scanner.js
|
|
61
|
+
|
|
62
|
+
# Generate JSON report
|
|
63
|
+
node .claude/scripts/roadmap-scanner.js --output json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Log Analysis
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Analyze delegation log for model usage
|
|
70
|
+
node .claude/scripts/analyze-delegation-log.js \
|
|
71
|
+
~/.claude/logs/delegation.jsonl
|
|
72
|
+
|
|
73
|
+
# Generate cost estimate
|
|
74
|
+
node .claude/scripts/analyze-delegation-log.js \
|
|
75
|
+
~/.claude/logs/delegation.jsonl --cost-estimate
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Git History Audit
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Check for sensitive data in git history
|
|
82
|
+
python .claude/scripts/git-history-analyzer.py
|
|
83
|
+
|
|
84
|
+
# Check specific patterns
|
|
85
|
+
python .claude/scripts/git-history-analyzer.py \
|
|
86
|
+
--patterns "password|secret|api.key"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Integration with Claude Code
|
|
90
|
+
|
|
91
|
+
These scripts can be invoked via Claude Code commands:
|
|
92
|
+
|
|
93
|
+
```markdown
|
|
94
|
+
<!-- .claude/commands/validate-deploy.md -->
|
|
95
|
+
Run the deployment validation script:
|
|
96
|
+
\`\`\`bash
|
|
97
|
+
node .claude/scripts/validate-deployment.js --platform {{platform}}
|
|
98
|
+
\`\`\`
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Environment Variables
|
|
102
|
+
|
|
103
|
+
Some scripts require environment variables:
|
|
104
|
+
|
|
105
|
+
| Variable | Used By | Description |
|
|
106
|
+
|----------|---------|-------------|
|
|
107
|
+
| `RAILWAY_API_TOKEN` | validate-deployment.js | Railway API access |
|
|
108
|
+
| `CLOUDFLARE_API_TOKEN` | validate-deployment.js | Cloudflare API access |
|
|
109
|
+
| `GITHUB_TOKEN` | git-history-analyzer.py | GitHub API (optional) |
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Analyze Delegation Log
|
|
4
|
+
*
|
|
5
|
+
* Analyzes Claude Code delegation logs to understand model usage,
|
|
6
|
+
* token consumption, and agent patterns.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* node analyze-delegation-log.js ~/.claude/logs/delegation.jsonl
|
|
10
|
+
* node analyze-delegation-log.js log.jsonl --cost-estimate
|
|
11
|
+
* node analyze-delegation-log.js log.jsonl --output json
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { readFileSync, existsSync } from 'fs';
|
|
15
|
+
|
|
16
|
+
// Approximate costs per 1M tokens (as of 2025)
|
|
17
|
+
const MODEL_COSTS = {
|
|
18
|
+
'claude-opus-4-5': { input: 15.00, output: 75.00 },
|
|
19
|
+
'claude-sonnet-4': { input: 3.00, output: 15.00 },
|
|
20
|
+
'claude-haiku': { input: 0.25, output: 1.25 },
|
|
21
|
+
'default': { input: 3.00, output: 15.00 },
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
class DelegationAnalyzer {
|
|
25
|
+
constructor(logPath, options = {}) {
|
|
26
|
+
this.logPath = logPath;
|
|
27
|
+
this.options = options;
|
|
28
|
+
this.entries = [];
|
|
29
|
+
this.analysis = {
|
|
30
|
+
models: {},
|
|
31
|
+
agents: {},
|
|
32
|
+
tools: {},
|
|
33
|
+
sessions: {},
|
|
34
|
+
timeline: [],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async analyze() {
|
|
39
|
+
console.log(`\n📊 Analyzing delegation log: ${this.logPath}\n`);
|
|
40
|
+
|
|
41
|
+
if (!existsSync(this.logPath)) {
|
|
42
|
+
console.error(`Error: File not found: ${this.logPath}`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
await this.parseLog();
|
|
47
|
+
await this.computeMetrics();
|
|
48
|
+
|
|
49
|
+
if (this.options.output === 'json') {
|
|
50
|
+
this.outputJson();
|
|
51
|
+
} else {
|
|
52
|
+
this.outputText();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async parseLog() {
|
|
57
|
+
const content = readFileSync(this.logPath, 'utf8');
|
|
58
|
+
const lines = content.split('\n').filter(line => line.trim());
|
|
59
|
+
|
|
60
|
+
for (const line of lines) {
|
|
61
|
+
try {
|
|
62
|
+
const entry = JSON.parse(line);
|
|
63
|
+
this.entries.push(entry);
|
|
64
|
+
} catch (e) {
|
|
65
|
+
// Skip invalid lines
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log(`Parsed ${this.entries.length} log entries\n`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async computeMetrics() {
|
|
73
|
+
for (const entry of this.entries) {
|
|
74
|
+
// Track by model
|
|
75
|
+
const model = entry.model || 'unknown';
|
|
76
|
+
if (!this.analysis.models[model]) {
|
|
77
|
+
this.analysis.models[model] = {
|
|
78
|
+
calls: 0,
|
|
79
|
+
inputTokens: 0,
|
|
80
|
+
outputTokens: 0,
|
|
81
|
+
errors: 0,
|
|
82
|
+
avgLatency: 0,
|
|
83
|
+
latencies: [],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const modelStats = this.analysis.models[model];
|
|
88
|
+
modelStats.calls++;
|
|
89
|
+
modelStats.inputTokens += entry.inputTokens || 0;
|
|
90
|
+
modelStats.outputTokens += entry.outputTokens || 0;
|
|
91
|
+
if (entry.error) modelStats.errors++;
|
|
92
|
+
if (entry.latencyMs) modelStats.latencies.push(entry.latencyMs);
|
|
93
|
+
|
|
94
|
+
// Track by agent type
|
|
95
|
+
const agentType = entry.agentType || entry.subagentType || 'main';
|
|
96
|
+
if (!this.analysis.agents[agentType]) {
|
|
97
|
+
this.analysis.agents[agentType] = {
|
|
98
|
+
invocations: 0,
|
|
99
|
+
totalTokens: 0,
|
|
100
|
+
avgTokensPerCall: 0,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const agentStats = this.analysis.agents[agentType];
|
|
105
|
+
agentStats.invocations++;
|
|
106
|
+
agentStats.totalTokens += (entry.inputTokens || 0) + (entry.outputTokens || 0);
|
|
107
|
+
|
|
108
|
+
// Track by tool
|
|
109
|
+
if (entry.tool) {
|
|
110
|
+
if (!this.analysis.tools[entry.tool]) {
|
|
111
|
+
this.analysis.tools[entry.tool] = { calls: 0, errors: 0 };
|
|
112
|
+
}
|
|
113
|
+
this.analysis.tools[entry.tool].calls++;
|
|
114
|
+
if (entry.error) this.analysis.tools[entry.tool].errors++;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Track by session
|
|
118
|
+
const sessionId = entry.sessionId || 'default';
|
|
119
|
+
if (!this.analysis.sessions[sessionId]) {
|
|
120
|
+
this.analysis.sessions[sessionId] = {
|
|
121
|
+
calls: 0,
|
|
122
|
+
tokens: 0,
|
|
123
|
+
start: entry.timestamp,
|
|
124
|
+
end: entry.timestamp,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const session = this.analysis.sessions[sessionId];
|
|
129
|
+
session.calls++;
|
|
130
|
+
session.tokens += (entry.inputTokens || 0) + (entry.outputTokens || 0);
|
|
131
|
+
if (entry.timestamp > session.end) session.end = entry.timestamp;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Compute averages
|
|
135
|
+
for (const model of Object.keys(this.analysis.models)) {
|
|
136
|
+
const stats = this.analysis.models[model];
|
|
137
|
+
if (stats.latencies.length > 0) {
|
|
138
|
+
stats.avgLatency = Math.round(
|
|
139
|
+
stats.latencies.reduce((a, b) => a + b, 0) / stats.latencies.length
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
delete stats.latencies;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
for (const agent of Object.keys(this.analysis.agents)) {
|
|
146
|
+
const stats = this.analysis.agents[agent];
|
|
147
|
+
stats.avgTokensPerCall = Math.round(stats.totalTokens / stats.invocations);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
estimateCost() {
|
|
152
|
+
let totalCost = 0;
|
|
153
|
+
const breakdown = {};
|
|
154
|
+
|
|
155
|
+
for (const [model, stats] of Object.entries(this.analysis.models)) {
|
|
156
|
+
const costs = MODEL_COSTS[model] || MODEL_COSTS['default'];
|
|
157
|
+
const inputCost = (stats.inputTokens / 1_000_000) * costs.input;
|
|
158
|
+
const outputCost = (stats.outputTokens / 1_000_000) * costs.output;
|
|
159
|
+
const modelCost = inputCost + outputCost;
|
|
160
|
+
|
|
161
|
+
breakdown[model] = {
|
|
162
|
+
inputCost: inputCost.toFixed(4),
|
|
163
|
+
outputCost: outputCost.toFixed(4),
|
|
164
|
+
totalCost: modelCost.toFixed(4),
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
totalCost += modelCost;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return { breakdown, totalCost: totalCost.toFixed(4) };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
outputText() {
|
|
174
|
+
console.log('='.repeat(70));
|
|
175
|
+
console.log(' DELEGATION LOG ANALYSIS');
|
|
176
|
+
console.log('='.repeat(70));
|
|
177
|
+
|
|
178
|
+
// Model usage
|
|
179
|
+
console.log('\n📊 Model Usage\n');
|
|
180
|
+
console.log('Model Calls Input Tokens Output Tokens Errors');
|
|
181
|
+
console.log('-'.repeat(70));
|
|
182
|
+
|
|
183
|
+
for (const [model, stats] of Object.entries(this.analysis.models)) {
|
|
184
|
+
const modelName = model.padEnd(24);
|
|
185
|
+
const calls = stats.calls.toString().padStart(6);
|
|
186
|
+
const input = stats.inputTokens.toLocaleString().padStart(15);
|
|
187
|
+
const output = stats.outputTokens.toLocaleString().padStart(16);
|
|
188
|
+
const errors = stats.errors.toString().padStart(8);
|
|
189
|
+
console.log(`${modelName}${calls}${input}${output}${errors}`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Agent usage
|
|
193
|
+
console.log('\n🤖 Agent Types\n');
|
|
194
|
+
console.log('Agent Type Invocations Total Tokens Avg Tokens/Call');
|
|
195
|
+
console.log('-'.repeat(70));
|
|
196
|
+
|
|
197
|
+
for (const [agent, stats] of Object.entries(this.analysis.agents)) {
|
|
198
|
+
const agentName = agent.padEnd(22);
|
|
199
|
+
const invocations = stats.invocations.toString().padStart(12);
|
|
200
|
+
const tokens = stats.totalTokens.toLocaleString().padStart(15);
|
|
201
|
+
const avg = stats.avgTokensPerCall.toLocaleString().padStart(17);
|
|
202
|
+
console.log(`${agentName}${invocations}${tokens}${avg}`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Tool usage (top 10)
|
|
206
|
+
const toolEntries = Object.entries(this.analysis.tools)
|
|
207
|
+
.sort((a, b) => b[1].calls - a[1].calls)
|
|
208
|
+
.slice(0, 10);
|
|
209
|
+
|
|
210
|
+
if (toolEntries.length > 0) {
|
|
211
|
+
console.log('\n🔧 Top 10 Tools\n');
|
|
212
|
+
console.log('Tool Calls Errors');
|
|
213
|
+
console.log('-'.repeat(50));
|
|
214
|
+
|
|
215
|
+
for (const [tool, stats] of toolEntries) {
|
|
216
|
+
const toolName = tool.padEnd(30);
|
|
217
|
+
const calls = stats.calls.toString().padStart(6);
|
|
218
|
+
const errors = stats.errors.toString().padStart(9);
|
|
219
|
+
console.log(`${toolName}${calls}${errors}`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Cost estimate
|
|
224
|
+
if (this.options.costEstimate) {
|
|
225
|
+
const cost = this.estimateCost();
|
|
226
|
+
|
|
227
|
+
console.log('\n💰 Cost Estimate\n');
|
|
228
|
+
console.log('Model Input Cost Output Cost Total Cost');
|
|
229
|
+
console.log('-'.repeat(70));
|
|
230
|
+
|
|
231
|
+
for (const [model, costs] of Object.entries(cost.breakdown)) {
|
|
232
|
+
const modelName = model.padEnd(26);
|
|
233
|
+
const input = `$${costs.inputCost}`.padStart(12);
|
|
234
|
+
const output = `$${costs.outputCost}`.padStart(14);
|
|
235
|
+
const total = `$${costs.totalCost}`.padStart(13);
|
|
236
|
+
console.log(`${modelName}${input}${output}${total}`);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
console.log('-'.repeat(70));
|
|
240
|
+
console.log(`${'TOTAL'.padEnd(26)}${''.padStart(26)}$${cost.totalCost}`.padStart(13));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Summary
|
|
244
|
+
const totalCalls = Object.values(this.analysis.models)
|
|
245
|
+
.reduce((acc, m) => acc + m.calls, 0);
|
|
246
|
+
const totalTokens = Object.values(this.analysis.models)
|
|
247
|
+
.reduce((acc, m) => acc + m.inputTokens + m.outputTokens, 0);
|
|
248
|
+
const totalErrors = Object.values(this.analysis.models)
|
|
249
|
+
.reduce((acc, m) => acc + m.errors, 0);
|
|
250
|
+
|
|
251
|
+
console.log('\n' + '='.repeat(70));
|
|
252
|
+
console.log('SUMMARY');
|
|
253
|
+
console.log('='.repeat(70));
|
|
254
|
+
console.log(`\n Total API Calls: ${totalCalls.toLocaleString()}`);
|
|
255
|
+
console.log(` Total Tokens: ${totalTokens.toLocaleString()}`);
|
|
256
|
+
console.log(` Error Rate: ${((totalErrors / totalCalls) * 100).toFixed(2)}%`);
|
|
257
|
+
console.log(` Sessions: ${Object.keys(this.analysis.sessions).length}`);
|
|
258
|
+
console.log('\n' + '='.repeat(70) + '\n');
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
outputJson() {
|
|
262
|
+
const output = {
|
|
263
|
+
analyzedAt: new Date().toISOString(),
|
|
264
|
+
logPath: this.logPath,
|
|
265
|
+
totalEntries: this.entries.length,
|
|
266
|
+
analysis: this.analysis,
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
if (this.options.costEstimate) {
|
|
270
|
+
output.costEstimate = this.estimateCost();
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
console.log(JSON.stringify(output, null, 2));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// CLI entry point
|
|
278
|
+
async function main() {
|
|
279
|
+
const args = process.argv.slice(2);
|
|
280
|
+
|
|
281
|
+
if (args.length === 0 || args[0].startsWith('--')) {
|
|
282
|
+
console.error('Usage: node analyze-delegation-log.js <log-file> [options]');
|
|
283
|
+
console.error('Options:');
|
|
284
|
+
console.error(' --cost-estimate Include cost estimate');
|
|
285
|
+
console.error(' --output json Output as JSON');
|
|
286
|
+
process.exit(1);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const logPath = args[0];
|
|
290
|
+
const options = {
|
|
291
|
+
costEstimate: args.includes('--cost-estimate'),
|
|
292
|
+
output: args.includes('--output') ? args[args.indexOf('--output') + 1] : 'text',
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const analyzer = new DelegationAnalyzer(logPath, options);
|
|
296
|
+
await analyzer.analyze();
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
main().catch(console.error);
|