arkaos 3.37.0 → 3.38.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/VERSION CHANGED
@@ -1 +1 @@
1
- 3.37.0
1
+ 3.38.0
@@ -53,7 +53,8 @@ interface TrendResponse {
53
53
 
54
54
  type Period = 'today' | 'week' | 'month' | 'all'
55
55
 
56
- const { fetchApi } = useApi()
56
+ const { fetchApi, apiBase } = useApi()
57
+ const toast = useToast()
57
58
  const period = ref<Period>('today')
58
59
 
59
60
  const periodOptions: { label: string; value: Period }[] = [
@@ -73,6 +74,36 @@ const {
73
74
  { query: computed(() => ({ period: period.value })) },
74
75
  )
75
76
 
77
+ // PR91d v3.38.0 — CSV export of the telemetry rows for the current period.
78
+ async function exportCsv() {
79
+ try {
80
+ const blob = await $fetch<Blob>(
81
+ `${apiBase}/api/llm-costs/export.csv`,
82
+ { query: { period: period.value }, responseType: 'blob' },
83
+ )
84
+ const url = URL.createObjectURL(blob)
85
+ const a = document.createElement('a')
86
+ a.href = url
87
+ a.download = `arkaos-costs-${period.value}.csv`
88
+ document.body.appendChild(a)
89
+ a.click()
90
+ a.remove()
91
+ URL.revokeObjectURL(url)
92
+ toast.add({
93
+ title: 'CSV downloaded',
94
+ description: `arkaos-costs-${period.value}.csv`,
95
+ color: 'success',
96
+ icon: 'i-lucide-download',
97
+ })
98
+ } catch (err) {
99
+ toast.add({
100
+ title: 'Export failed',
101
+ description: err instanceof Error ? err.message : 'unknown error',
102
+ color: 'error',
103
+ })
104
+ }
105
+ }
106
+
76
107
  // PR90c v3.33.0 — let the operator pick 7d / 14d / 30d.
77
108
  const trendDays = ref<7 | 14 | 30>(7)
78
109
  const trendDaysOptions = [
@@ -204,6 +235,14 @@ async function refreshAll() {
204
235
  size="sm"
205
236
  class="w-32"
206
237
  />
238
+ <UButton
239
+ label="Export CSV"
240
+ icon="i-lucide-download"
241
+ variant="soft"
242
+ size="sm"
243
+ class="ml-2"
244
+ @click="exportCsv"
245
+ />
207
246
  <UButton
208
247
  label="Refresh"
209
248
  variant="ghost"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkaos",
3
- "version": "3.37.0",
3
+ "version": "3.38.0",
4
4
  "description": "The Operating System for AI Agent Teams",
5
5
  "type": "module",
6
6
  "bin": {
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "arkaos-core"
3
- version = "3.37.0"
3
+ version = "3.38.0"
4
4
  description = "Core engine for ArkaOS — The Operating System for AI Agent Teams"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}
@@ -2510,6 +2510,56 @@ def llm_costs(period: str = "today"):
2510
2510
  }
2511
2511
 
2512
2512
 
2513
+ @app.get("/api/llm-costs/export.csv")
2514
+ def llm_costs_export(period: str = "month"):
2515
+ """PR91d v3.38.0 — stream the telemetry rows for the period as CSV.
2516
+
2517
+ Returns ``text/csv`` with a header row + every row in the selected
2518
+ period. Period values match `summarise()`: today / week / month / all.
2519
+ """
2520
+ try:
2521
+ from core.runtime.llm_cost_telemetry import (
2522
+ VALID_PERIODS,
2523
+ _load_slice,
2524
+ _period_cutoff,
2525
+ )
2526
+ except Exception:
2527
+ return {"error": "telemetry unavailable"}
2528
+ if period not in VALID_PERIODS:
2529
+ period = "month"
2530
+
2531
+ entries, _ = _load_slice(None, _period_cutoff(period, now=None))
2532
+ import csv
2533
+ import io
2534
+ buffer = io.StringIO()
2535
+ writer = csv.writer(buffer)
2536
+ writer.writerow([
2537
+ "ts", "session_id", "provider", "model", "category",
2538
+ "tokens_in", "tokens_out", "cached_tokens", "estimated_cost_usd",
2539
+ ])
2540
+ for entry in entries:
2541
+ writer.writerow([
2542
+ entry.get("ts", ""),
2543
+ entry.get("session_id", ""),
2544
+ entry.get("provider", ""),
2545
+ entry.get("model", ""),
2546
+ entry.get("category", ""),
2547
+ entry.get("tokens_in", ""),
2548
+ entry.get("tokens_out", ""),
2549
+ entry.get("cached_tokens", ""),
2550
+ entry.get("estimated_cost_usd", ""),
2551
+ ])
2552
+ filename = f"arkaos-costs-{period}.csv"
2553
+ from fastapi import Response
2554
+ return Response(
2555
+ content=buffer.getvalue(),
2556
+ media_type="text/csv",
2557
+ headers={
2558
+ "Content-Disposition": f'attachment; filename="{filename}"',
2559
+ },
2560
+ )
2561
+
2562
+
2513
2563
  @app.get("/api/llm-costs/trend")
2514
2564
  def llm_costs_trend(days: int = 7):
2515
2565
  """Day-by-day rolling totals from the cost telemetry.