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 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 current usage metrics')
187
- .option('-p, --period <period>', 'Period: current, today, week, month, year', 'current')
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trucontext",
3
- "version": "0.8.1",
3
+ "version": "0.8.3",
4
4
  "description": "TruContext CLI — contextual memory for AI applications",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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 || 'current';
44
- const res = await controlPlane('GET', `/billing/usage/${appId}?period=${period}`);
45
- const usage = res.data?.data || res.data || {};
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
- console.log(chalk.bold('Usage Summary') + chalk.dim(` — ${period}`));
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: ${chalk.bold(formatNumber(usage.apiCalls || 0))}${usage.limits?.apiCalls ? chalk.dim(` of ${formatNumber(usage.limits.apiCalls)}`) : ''}`);
55
- console.log(` Tokens: ${chalk.bold(formatNumber((usage.llmInputTokens || 0) + (usage.llmOutputTokens || 0)))}${usage.limits?.llmTokens ? chalk.dim(` of ${formatNumber(usage.limits.llmTokens)}`) : ''}`);
56
- console.log(` Input: ${chalk.dim(formatNumber(usage.llmInputTokens || 0))}`);
57
- console.log(` Output: ${chalk.dim(formatNumber(usage.llmOutputTokens || 0))}`);
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: ${chalk.bold(formatBytes(usage.storageBytes || 0))}${usage.limits?.storageGb ? chalk.dim(` of ${usage.limits.storageGb} GB`) : ''}`);
60
- console.log(` Processing: ${chalk.bold(formatMs(usage.processingMs || 0))}${usage.limits?.processingMinutes ? chalk.dim(` of ${usage.limits.processingMinutes} min`) : ''}`);
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: ${chalk.cyan(usage.planTier)}`);
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 res = await controlPlane('GET', `/billing/usage/${appId}/history?period=${period}&sources=true`);
77
- const historyData = res.data?.data || res.data || {};
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
- console.log(chalk.bold(`Usage History`) + chalk.dim(` ${period} (${history.length} entries)`));
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 Source'));
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 || entry.period || '—';
110
+ const date = entry.date || '—';
92
111
  const calls = formatNumber(entry.apiCalls || 0);
93
- const tokens = formatNumber((entry.inputTokens || 0) + (entry.outputTokens || 0));
94
- const source = entry.source || '—';
95
- console.log(` ${date.padEnd(18)} ${calls.padEnd(12)} ${tokens.padEnd(12)} ${chalk.dim(source)}`);
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?.data || res.data || {};
138
+ const plansData = res.data || {};
107
139
  const plans = plansData.plans || [];
108
140
 
109
141
  if (plans.length === 0) {
@@ -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?.sections || res.sections || [];
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.'));
@@ -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 : (res.data?.entities || []);
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?.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.'));
@@ -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?.roots || [];
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;