trucontext 0.8.1 → 0.8.3
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/cli.js +4 -2
- package/package.json +1 -1
- package/src/commands/billing.js +53 -21
- package/src/commands/docs.js +1 -1
- package/src/commands/entities.js +2 -2
- package/src/commands/roots.js +1 -1
package/bin/cli.js
CHANGED
|
@@ -183,12 +183,14 @@ docs.command('show <slug>').description('Show a specific doc section').action(do
|
|
|
183
183
|
// Billing & Usage
|
|
184
184
|
const billing = program.command('billing').description('View usage and billing').action(function() { this.help(); });
|
|
185
185
|
billing.command('usage')
|
|
186
|
-
.description('View
|
|
187
|
-
.option('-p, --period <period>', 'Period:
|
|
186
|
+
.description('View usage metrics with optional source filter')
|
|
187
|
+
.option('-p, --period <period>', 'Period: ytd, today, week, month, 6months, year, current', 'ytd')
|
|
188
|
+
.option('-s, --source <sources>', 'Filter by source: ingest, dream:decay, dream:concepts (comma-separated)')
|
|
188
189
|
.action(usageCommand);
|
|
189
190
|
billing.command('history')
|
|
190
191
|
.description('View usage history with time series data')
|
|
191
192
|
.option('-p, --period <period>', 'Period: today, week, month, 6months, year, ytd', 'month')
|
|
193
|
+
.option('-s, --source <sources>', 'Filter by source: ingest, dream:decay, dream:concepts (comma-separated)')
|
|
192
194
|
.action(usageHistoryCommand);
|
|
193
195
|
billing.command('plans')
|
|
194
196
|
.description('View available plans')
|
package/package.json
CHANGED
package/src/commands/billing.js
CHANGED
|
@@ -40,28 +40,43 @@ function formatMs(ms) {
|
|
|
40
40
|
export async function usageCommand(options) {
|
|
41
41
|
try {
|
|
42
42
|
const appId = requireApp();
|
|
43
|
-
const period = options.period || '
|
|
44
|
-
const
|
|
45
|
-
const
|
|
43
|
+
const period = options.period || 'ytd';
|
|
44
|
+
const source = options.source || '';
|
|
45
|
+
const params = [`period=${period}`];
|
|
46
|
+
if (source) params.push(`source=${source}`);
|
|
47
|
+
const res = await controlPlane('GET', `/billing/usage/${appId}?${params.join('&')}`);
|
|
48
|
+
const usage = res.data || {};
|
|
46
49
|
|
|
47
50
|
if (!usage || (!usage.apiCalls && !usage.llmInputTokens && !usage.processingMs)) {
|
|
48
51
|
console.log(chalk.yellow('No usage data available.'));
|
|
49
52
|
return;
|
|
50
53
|
}
|
|
51
54
|
|
|
52
|
-
|
|
55
|
+
const header = source ? `${period} — source: ${source}` : period;
|
|
56
|
+
console.log(chalk.bold('Usage Summary') + chalk.dim(` — ${header}`));
|
|
53
57
|
console.log();
|
|
54
|
-
console.log(` API Calls:
|
|
55
|
-
console.log(` Tokens:
|
|
56
|
-
console.log(` Input:
|
|
57
|
-
console.log(` Output:
|
|
58
|
+
console.log(` API Calls: ${chalk.bold(formatNumber(usage.apiCalls || 0))}${usage.limits?.apiCalls ? chalk.dim(` of ${formatNumber(usage.limits.apiCalls)}`) : ''}`);
|
|
59
|
+
console.log(` Tokens: ${chalk.bold(formatNumber((usage.llmInputTokens || 0) + (usage.llmOutputTokens || 0)))}${usage.limits?.llmTokens ? chalk.dim(` of ${formatNumber(usage.limits.llmTokens)}`) : ''}`);
|
|
60
|
+
console.log(` Input: ${chalk.dim(formatNumber(usage.llmInputTokens || 0))}`);
|
|
61
|
+
console.log(` Output: ${chalk.dim(formatNumber(usage.llmOutputTokens || 0))}`);
|
|
58
62
|
console.log(` Compute Units: ${chalk.bold(formatNumber(usage.computeUnits || 0))}`);
|
|
59
|
-
console.log(` Storage:
|
|
60
|
-
console.log(` Processing:
|
|
63
|
+
console.log(` Storage: ${chalk.bold(formatBytes(usage.storageBytes || 0))}${usage.limits?.storageGb ? chalk.dim(` of ${usage.limits.storageGb} GB`) : ''}`);
|
|
64
|
+
console.log(` Processing: ${chalk.bold(formatMs(usage.processingMs || 0))}${usage.limits?.processingMinutes ? chalk.dim(` of ${usage.limits.processingMinutes} min`) : ''}`);
|
|
61
65
|
|
|
62
66
|
if (usage.planTier) {
|
|
63
67
|
console.log();
|
|
64
|
-
console.log(` Plan:
|
|
68
|
+
console.log(` Plan: ${chalk.cyan(usage.planTier)}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Per-source breakdown
|
|
72
|
+
if (usage.sources && usage.sources.length > 0 && !source) {
|
|
73
|
+
console.log();
|
|
74
|
+
console.log(chalk.bold(' By Source:'));
|
|
75
|
+
for (const s of usage.sources) {
|
|
76
|
+
const tokens = formatNumber((s.llmInputTokens || 0) + (s.llmOutputTokens || 0));
|
|
77
|
+
const cu = formatNumber(s.computeUnits || 0);
|
|
78
|
+
console.log(` ${chalk.dim(s.source.padEnd(20))} ${tokens.padEnd(10)} tokens ${cu.padEnd(8)} CU ${formatNumber(s.apiCalls || 0)} calls`);
|
|
79
|
+
}
|
|
65
80
|
}
|
|
66
81
|
} catch (err) {
|
|
67
82
|
console.error(chalk.red(`Failed: ${err.message}`));
|
|
@@ -73,8 +88,11 @@ export async function usageHistoryCommand(options) {
|
|
|
73
88
|
try {
|
|
74
89
|
const appId = requireApp();
|
|
75
90
|
const period = options.period || 'month';
|
|
76
|
-
const
|
|
77
|
-
const
|
|
91
|
+
const source = options.source || '';
|
|
92
|
+
const params = [`period=${period}`];
|
|
93
|
+
if (source) params.push(`source=${source}`);
|
|
94
|
+
const res = await controlPlane('GET', `/billing/usage/${appId}/history?${params.join('&')}`);
|
|
95
|
+
const historyData = res.data || {};
|
|
78
96
|
const history = historyData.history || [];
|
|
79
97
|
|
|
80
98
|
if (history.length === 0) {
|
|
@@ -82,17 +100,31 @@ export async function usageHistoryCommand(options) {
|
|
|
82
100
|
return;
|
|
83
101
|
}
|
|
84
102
|
|
|
85
|
-
|
|
103
|
+
const header = source ? `${period} — source: ${source}` : period;
|
|
104
|
+
console.log(chalk.bold(`Usage History`) + chalk.dim(` — ${header} (${history.length} entries)`));
|
|
86
105
|
console.log();
|
|
87
|
-
console.log(chalk.dim(' Date API Calls Tokens
|
|
88
|
-
console.log(chalk.dim(' ──── ───────── ──────
|
|
106
|
+
console.log(chalk.dim(' Date API Calls Tokens CU Processing'));
|
|
107
|
+
console.log(chalk.dim(' ──── ───────── ────── ── ──────────'));
|
|
89
108
|
|
|
90
109
|
for (const entry of history) {
|
|
91
|
-
const date = entry.date ||
|
|
110
|
+
const date = entry.date || '—';
|
|
92
111
|
const calls = formatNumber(entry.apiCalls || 0);
|
|
93
|
-
const tokens = formatNumber((entry.
|
|
94
|
-
const
|
|
95
|
-
|
|
112
|
+
const tokens = formatNumber((entry.llmInputTokens || 0) + (entry.llmOutputTokens || 0));
|
|
113
|
+
const cu = formatNumber(entry.computeUnits || 0);
|
|
114
|
+
const proc = formatMs(entry.processingMs || 0);
|
|
115
|
+
console.log(` ${date.padEnd(18)} ${calls.padEnd(12)} ${tokens.padEnd(12)} ${cu.padEnd(12)} ${proc}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Source breakdown
|
|
119
|
+
const sources = historyData.sources || [];
|
|
120
|
+
if (sources.length > 0 && !source) {
|
|
121
|
+
console.log();
|
|
122
|
+
console.log(chalk.bold(' By Source:'));
|
|
123
|
+
for (const s of sources) {
|
|
124
|
+
const tokens = formatNumber(s.llmTokens || 0);
|
|
125
|
+
const cu = formatNumber(s.computeUnits || 0);
|
|
126
|
+
console.log(` ${chalk.dim(s.source.padEnd(20))} ${tokens.padEnd(10)} tokens ${cu.padEnd(8)} CU ${formatNumber(s.apiCalls || 0)} calls`);
|
|
127
|
+
}
|
|
96
128
|
}
|
|
97
129
|
} catch (err) {
|
|
98
130
|
console.error(chalk.red(`Failed: ${err.message}`));
|
|
@@ -103,7 +135,7 @@ export async function usageHistoryCommand(options) {
|
|
|
103
135
|
export async function plansCommand() {
|
|
104
136
|
try {
|
|
105
137
|
const res = await controlPlane('GET', '/billing/plans');
|
|
106
|
-
const plansData = res.data
|
|
138
|
+
const plansData = res.data || {};
|
|
107
139
|
const plans = plansData.plans || [];
|
|
108
140
|
|
|
109
141
|
if (plans.length === 0) {
|
package/src/commands/docs.js
CHANGED
|
@@ -4,7 +4,7 @@ import { publicApi } from '../client.js';
|
|
|
4
4
|
export async function docsListCommand() {
|
|
5
5
|
try {
|
|
6
6
|
const res = await publicApi('GET', '/public/docs');
|
|
7
|
-
const sections = res.data
|
|
7
|
+
const sections = Array.isArray(res.data) ? res.data : [];
|
|
8
8
|
|
|
9
9
|
if (sections.length === 0) {
|
|
10
10
|
console.log(chalk.yellow('No documentation available.'));
|
package/src/commands/entities.js
CHANGED
|
@@ -49,7 +49,7 @@ export async function entitiesListCommand(options) {
|
|
|
49
49
|
const path = `/apps/${appId}/entities${qs ? `?${qs}` : ''}`;
|
|
50
50
|
|
|
51
51
|
const res = await controlPlane('GET', path);
|
|
52
|
-
const entities = Array.isArray(res.data) ? res.data :
|
|
52
|
+
const entities = Array.isArray(res.data) ? res.data : [];
|
|
53
53
|
|
|
54
54
|
if (entities.length === 0) {
|
|
55
55
|
console.log(chalk.yellow('No entities found.'));
|
|
@@ -201,7 +201,7 @@ export async function entitiesEdgesCommand(entityId) {
|
|
|
201
201
|
try {
|
|
202
202
|
const appId = getActiveApp();
|
|
203
203
|
const res = await controlPlane('GET', `/apps/${appId}/entities/${entityId}/edges`);
|
|
204
|
-
const edges = res.data
|
|
204
|
+
const edges = Array.isArray(res.data) ? res.data : [];
|
|
205
205
|
|
|
206
206
|
if (edges.length === 0) {
|
|
207
207
|
console.log(chalk.yellow('No edges found.'));
|
package/src/commands/roots.js
CHANGED
|
@@ -76,7 +76,7 @@ export function registerRootsCommand(program) {
|
|
|
76
76
|
try {
|
|
77
77
|
const appId = getActiveApp();
|
|
78
78
|
const res = await controlPlane('GET', `/apps/${appId}/roots`);
|
|
79
|
-
const rootNodes = res.data
|
|
79
|
+
const rootNodes = Array.isArray(res.data) ? res.data : [];
|
|
80
80
|
if (rootNodes.length === 0) {
|
|
81
81
|
console.log('No root nodes. Create one with: trucontext roots create');
|
|
82
82
|
return;
|