@cat-factory/app 0.168.0 → 0.170.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/README.md +13 -4
- package/app/components/observability/StepMetricsBar.vue +36 -20
- package/app/components/panels/ObservabilityPanel.vue +60 -23
- package/app/modular/nav-contributions.spec.ts +39 -10
- package/app/modular/nav-contributions.ts +18 -13
- package/app/utils/observability.spec.ts +18 -18
- package/app/utils/observability.ts +19 -22
- package/i18n/locales/de.json +18 -6
- package/i18n/locales/en.json +18 -6
- package/i18n/locales/es.json +18 -6
- package/i18n/locales/fr.json +18 -6
- package/i18n/locales/he.json +18 -6
- package/i18n/locales/it.json +18 -6
- package/i18n/locales/ja.json +18 -6
- package/i18n/locales/pl.json +18 -6
- package/i18n/locales/tr.json +18 -6
- package/i18n/locales/uk.json +18 -6
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -56,9 +56,10 @@ over the WebSocket. How that sync works is written up in
|
|
|
56
56
|
## Interface modes (basic / advanced)
|
|
57
57
|
|
|
58
58
|
The SPA renders at one of two **interface tiers**. `basic` (the default) is the everyday
|
|
59
|
-
surface: the
|
|
60
|
-
|
|
61
|
-
everything. The tier resolves in a fixed order, first
|
|
59
|
+
surface: the run/pipeline options that only exist to override a workspace-level default are
|
|
60
|
+
left at that default, and the nav is trimmed to the destinations that are the **only route**
|
|
61
|
+
to their capability. `advanced` shows everything. The tier resolves in a fixed order, first
|
|
62
|
+
match wins:
|
|
62
63
|
|
|
63
64
|
1. **`NUXT_PUBLIC_UI_MODE`** (`basic` | `advanced`) — the deployment pin. Like
|
|
64
65
|
`NUXT_PUBLIC_API_BASE` it is baked in at **build** time (`ssr: false`), and while it is
|
|
@@ -81,7 +82,15 @@ hoc where it can be avoided:
|
|
|
81
82
|
- **A nav destination** declares `advanced: true` in `app/modular/nav-contributions.ts`. The
|
|
82
83
|
shared `navSlotFilter` drops it in basic mode across all three shells (sidebar, command
|
|
83
84
|
palette, toolbar), independently of its RBAC `gate` — both must pass. A consumer module's
|
|
84
|
-
own contributions take the same flag.
|
|
85
|
+
own contributions take the same flag. The bar for setting it is **route count, not how
|
|
86
|
+
advanced the surface feels**: hiding the only way to reach a capability removes the
|
|
87
|
+
capability from the tier, while hiding a shortcut into a surface a basic destination also
|
|
88
|
+
opens removes nothing. So the flag belongs on a surface that sits beside the delivery path
|
|
89
|
+
(Sandbox, Kaizen), on a palette shortcut into a Workspace-settings tab, or on a knob the
|
|
90
|
+
Integrations hub already offers — and never on a sole route (the pipeline builder, the
|
|
91
|
+
fragment library, the infrastructure/PREnv windows, the operator + reports views).
|
|
92
|
+
`nav-contributions.spec.ts` pins the advanced set against a table of each item's
|
|
93
|
+
alternative route, so promoting one forces that claim to be written down.
|
|
85
94
|
- **A less-used option inside a surface** reads `useUiModeStore().isAdvanced`. Hide, never
|
|
86
95
|
disable, and only ever hide an OVERRIDE: what remains must be exactly the default the hidden
|
|
87
96
|
field would have shown, so a basic-mode user never gets different behaviour from an advanced
|
|
@@ -4,10 +4,10 @@ import type { StepMetrics } from '~/types/execution'
|
|
|
4
4
|
import {
|
|
5
5
|
formatMs,
|
|
6
6
|
formatTokens,
|
|
7
|
-
freshPromptTokens,
|
|
8
7
|
headroomColor,
|
|
9
8
|
headroomRatio,
|
|
10
9
|
pct,
|
|
10
|
+
totalInputTokens,
|
|
11
11
|
transportRatio,
|
|
12
12
|
} from '~/utils/observability'
|
|
13
13
|
|
|
@@ -23,12 +23,16 @@ defineEmits<{ inspect: [] }>()
|
|
|
23
23
|
const { t } = useI18n()
|
|
24
24
|
|
|
25
25
|
const m = computed(() => props.metrics)
|
|
26
|
-
// The headline "↑" is
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
// The headline "↑" is TOTAL input — fresh + both cache classes — the like-for-like measure of
|
|
27
|
+
// Claude Code's own context gauge, which counts the same buckets because a cached token still
|
|
28
|
+
// occupies the context window (see `totalInputTokens`). The three classes then render as the
|
|
29
|
+
// breakdown, because they are priced an order of magnitude apart in opposite directions: a read
|
|
30
|
+
// is ~0.1x base input, a write 1.25-2x. Volume in the headline, cost in the breakdown — leading
|
|
31
|
+
// with fresh made a 31M-token run read as a 685-token one.
|
|
32
|
+
const totalInput = computed(() => totalInputTokens(m.value))
|
|
33
|
+
const cacheRead = computed(() => m.value.cacheReadTokens ?? 0)
|
|
34
|
+
const cacheWrite = computed(() => m.value.cacheWriteTokens ?? 0)
|
|
35
|
+
const hasCache = computed(() => cacheRead.value > 0 || cacheWrite.value > 0)
|
|
32
36
|
const headroom = computed(() => headroomRatio(m.value))
|
|
33
37
|
const transport = computed(() => transportRatio(m.value))
|
|
34
38
|
const headroomTone = computed(() => headroomColor(headroom.value, m.value.truncatedCalls > 0))
|
|
@@ -53,20 +57,9 @@ const headroomTone = computed(() => headroomColor(headroom.value, m.value.trunca
|
|
|
53
57
|
<span class="text-slate-500">·</span>
|
|
54
58
|
<span
|
|
55
59
|
class="tabular-nums text-slate-400"
|
|
56
|
-
:title="t('observability.metricsBar.
|
|
60
|
+
:title="t('observability.metricsBar.inputCompletionTokens')"
|
|
57
61
|
>
|
|
58
|
-
{{ formatTokens(
|
|
59
|
-
</span>
|
|
60
|
-
<span
|
|
61
|
-
v-if="(m.cachedPromptTokens ?? 0) > 0"
|
|
62
|
-
class="tabular-nums text-emerald-400/80"
|
|
63
|
-
:title="t('observability.metricsBar.cachedTokensHint')"
|
|
64
|
-
>
|
|
65
|
-
{{
|
|
66
|
-
t('observability.metricsBar.cachedTokens', {
|
|
67
|
-
tokens: formatTokens(m.cachedPromptTokens ?? 0),
|
|
68
|
-
})
|
|
69
|
-
}}
|
|
62
|
+
{{ formatTokens(totalInput) }}↑ {{ formatTokens(m.completionTokens) }}↓
|
|
70
63
|
</span>
|
|
71
64
|
<div class="ms-auto flex items-center gap-1">
|
|
72
65
|
<UBadge v-if="m.errors > 0" color="error" variant="subtle" size="sm">
|
|
@@ -83,6 +76,29 @@ const headroomTone = computed(() => headroomColor(headroom.value, m.value.trunca
|
|
|
83
76
|
</div>
|
|
84
77
|
</div>
|
|
85
78
|
|
|
79
|
+
<!-- input breakdown: the headline's three classes, priced an order of magnitude apart -->
|
|
80
|
+
<div v-if="hasCache" class="mt-1.5 flex items-center gap-1.5 text-[11px] tabular-nums">
|
|
81
|
+
<span class="text-slate-400" :title="t('observability.metricsBar.freshHint')">
|
|
82
|
+
{{ t('observability.metricsBar.fresh', { tokens: formatTokens(m.promptTokens) }) }}
|
|
83
|
+
</span>
|
|
84
|
+
<span v-if="cacheRead > 0" class="text-slate-600">·</span>
|
|
85
|
+
<span
|
|
86
|
+
v-if="cacheRead > 0"
|
|
87
|
+
class="text-emerald-400/80"
|
|
88
|
+
:title="t('observability.metricsBar.cacheReadHint')"
|
|
89
|
+
>
|
|
90
|
+
{{ t('observability.metricsBar.cacheRead', { tokens: formatTokens(cacheRead) }) }}
|
|
91
|
+
</span>
|
|
92
|
+
<span v-if="cacheWrite > 0" class="text-slate-600">·</span>
|
|
93
|
+
<span
|
|
94
|
+
v-if="cacheWrite > 0"
|
|
95
|
+
class="text-amber-400/80"
|
|
96
|
+
:title="t('observability.metricsBar.cacheWriteHint')"
|
|
97
|
+
>
|
|
98
|
+
{{ t('observability.metricsBar.cacheWrite', { tokens: formatTokens(cacheWrite) }) }}
|
|
99
|
+
</span>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
86
102
|
<!-- output-limit headroom -->
|
|
87
103
|
<div v-if="headroom !== null" class="mt-2">
|
|
88
104
|
<div class="flex items-center justify-between text-[11px]">
|
|
@@ -8,7 +8,7 @@ import type {
|
|
|
8
8
|
WebSearchProvider,
|
|
9
9
|
} from '~/types/execution'
|
|
10
10
|
import { agentKindMeta } from '~/utils/catalog'
|
|
11
|
-
import { formatMs, formatTokens,
|
|
11
|
+
import { formatMs, formatTokens, pct, totalInputTokens } from '~/utils/observability'
|
|
12
12
|
|
|
13
13
|
// Drill-down overlay for a run's LLM activity. Opened via
|
|
14
14
|
// `ui.openObservability(instanceId)` from a step surface; loads the full per-call
|
|
@@ -126,15 +126,18 @@ const totals = computed(() => {
|
|
|
126
126
|
const upstreamMs = sum(c, (x) => x.upstreamMs)
|
|
127
127
|
const overheadMs = sum(c, (x) => x.overheadMs)
|
|
128
128
|
const total = upstreamMs + overheadMs
|
|
129
|
+
// The three input classes are orthogonal at the source, so they are simply summed —
|
|
130
|
+
// `promptTokens` IS the fresh figure and needs no heuristic to recover it; the headline is
|
|
131
|
+
// their TOTAL (see `totalInputTokens` — the like-for-like Claude Code context gauge).
|
|
129
132
|
const promptTokens = sum(c, (x) => x.promptTokens)
|
|
130
|
-
const
|
|
133
|
+
const cacheReadTokens = sum(c, (x) => x.cacheReadTokens)
|
|
134
|
+
const cacheWriteTokens = sum(c, (x) => x.cacheWriteTokens)
|
|
131
135
|
return {
|
|
132
136
|
calls: c.length,
|
|
133
137
|
promptTokens,
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
freshPromptTokens: freshPromptTokens(promptTokens, cachedPromptTokens),
|
|
138
|
+
cacheReadTokens,
|
|
139
|
+
cacheWriteTokens,
|
|
140
|
+
inputTokens: totalInputTokens({ promptTokens, cacheReadTokens, cacheWriteTokens }),
|
|
138
141
|
completionTokens: sum(c, (x) => x.completionTokens),
|
|
139
142
|
upstreamMs,
|
|
140
143
|
overheadMs,
|
|
@@ -290,18 +293,47 @@ function exportJson() {
|
|
|
290
293
|
{{ t('observability.summary.tokensInOut') }}
|
|
291
294
|
</dt>
|
|
292
295
|
<dd class="mt-0.5 tabular-nums text-slate-200">
|
|
293
|
-
|
|
294
|
-
|
|
296
|
+
<span :title="t('observability.summary.inputTokensHint')">
|
|
297
|
+
{{ formatTokens(totals.inputTokens) }} /
|
|
298
|
+
{{ formatTokens(totals.completionTokens) }}
|
|
299
|
+
</span>
|
|
295
300
|
<span
|
|
296
|
-
v-if="totals.
|
|
297
|
-
class="
|
|
301
|
+
v-if="totals.cacheReadTokens > 0 || totals.cacheWriteTokens > 0"
|
|
302
|
+
class="mt-0.5 block text-[11px]"
|
|
298
303
|
>
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
304
|
+
<span class="text-slate-400" :title="t('observability.summary.freshHint')">
|
|
305
|
+
{{
|
|
306
|
+
t('observability.summary.fresh', {
|
|
307
|
+
tokens: formatTokens(totals.promptTokens),
|
|
308
|
+
})
|
|
309
|
+
}}
|
|
310
|
+
</span>
|
|
311
|
+
<template v-if="totals.cacheReadTokens > 0">
|
|
312
|
+
<span class="text-slate-600"> · </span>
|
|
313
|
+
<span
|
|
314
|
+
class="text-emerald-400/80"
|
|
315
|
+
:title="t('observability.summary.cacheReadHint')"
|
|
316
|
+
>
|
|
317
|
+
{{
|
|
318
|
+
t('observability.summary.cacheRead', {
|
|
319
|
+
tokens: formatTokens(totals.cacheReadTokens),
|
|
320
|
+
})
|
|
321
|
+
}}
|
|
322
|
+
</span>
|
|
323
|
+
</template>
|
|
324
|
+
<template v-if="totals.cacheWriteTokens > 0">
|
|
325
|
+
<span class="text-slate-600"> · </span>
|
|
326
|
+
<span
|
|
327
|
+
class="text-amber-400/80"
|
|
328
|
+
:title="t('observability.summary.cacheWriteHint')"
|
|
329
|
+
>
|
|
330
|
+
{{
|
|
331
|
+
t('observability.summary.cacheWrite', {
|
|
332
|
+
tokens: formatTokens(totals.cacheWriteTokens),
|
|
333
|
+
})
|
|
334
|
+
}}
|
|
335
|
+
</span>
|
|
336
|
+
</template>
|
|
305
337
|
</span>
|
|
306
338
|
</dd>
|
|
307
339
|
</div>
|
|
@@ -418,12 +450,14 @@ function exportJson() {
|
|
|
418
450
|
<span
|
|
419
451
|
:title="
|
|
420
452
|
t('observability.call.tokensTitle', {
|
|
421
|
-
|
|
453
|
+
input: totalInputTokens(c),
|
|
454
|
+
fresh: c.promptTokens,
|
|
422
455
|
completion: c.completionTokens,
|
|
423
456
|
})
|
|
424
457
|
"
|
|
425
458
|
>
|
|
426
|
-
{{ formatTokens(c
|
|
459
|
+
{{ formatTokens(totalInputTokens(c)) }}↑
|
|
460
|
+
{{ formatTokens(c.completionTokens) }}↓
|
|
427
461
|
</span>
|
|
428
462
|
<span
|
|
429
463
|
v-if="headroomOf(c) !== null"
|
|
@@ -467,11 +501,14 @@ function exportJson() {
|
|
|
467
501
|
<span v-if="c.requestMaxTokens != null">{{
|
|
468
502
|
t('observability.call.maxTokens', { value: c.requestMaxTokens })
|
|
469
503
|
}}</span>
|
|
470
|
-
<span v-if="c.
|
|
471
|
-
t('observability.call.
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
})
|
|
504
|
+
<span v-if="c.cacheReadTokens > 0 || c.cacheWriteTokens > 0">{{
|
|
505
|
+
t('observability.call.fresh', { tokens: c.promptTokens })
|
|
506
|
+
}}</span>
|
|
507
|
+
<span v-if="c.cacheReadTokens > 0" class="text-emerald-400">{{
|
|
508
|
+
t('observability.call.cacheRead', { tokens: c.cacheReadTokens })
|
|
509
|
+
}}</span>
|
|
510
|
+
<span v-if="c.cacheWriteTokens > 0" class="text-amber-400">{{
|
|
511
|
+
t('observability.call.cacheWrite', { tokens: c.cacheWriteTokens })
|
|
475
512
|
}}</span>
|
|
476
513
|
<span>{{
|
|
477
514
|
t('observability.call.total', { duration: formatMs(c.totalMs) })
|
|
@@ -99,11 +99,36 @@ describe('navSlotFilter', () => {
|
|
|
99
99
|
expect(kept).toContain('integrations-hub')
|
|
100
100
|
expect(kept).toContain('workspace-settings')
|
|
101
101
|
expect(kept).toContain('model-config')
|
|
102
|
-
// ...and the
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
// ...and so does every destination that is the SOLE route to its capability, however deep
|
|
103
|
+
// it feels: authoring a flow, the standards library, the PREnv/runner plumbing, and the
|
|
104
|
+
// aggregate run-health / spend views.
|
|
105
|
+
expect(kept).toContain('build-pipeline')
|
|
106
|
+
expect(kept).toContain('fragments')
|
|
107
|
+
expect(kept).toContain('infrastructure')
|
|
108
|
+
expect(kept).toContain('environment-setup')
|
|
109
|
+
expect(kept).toContain('operator-dashboard')
|
|
110
|
+
expect(kept).toContain('reports')
|
|
111
|
+
// What drops is beside the delivery path (experimentation) or a shortcut into a surface
|
|
112
|
+
// basic mode already reaches another way.
|
|
105
113
|
expect(kept).not.toContain('sandbox')
|
|
106
|
-
expect(kept).not.toContain('
|
|
114
|
+
expect(kept).not.toContain('kaizen')
|
|
115
|
+
expect(kept).not.toContain('merge-thresholds')
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('never makes an advanced item the only route to its capability', () => {
|
|
119
|
+
// The tier's governing rule (see the catalog comment): every advanced destination either
|
|
120
|
+
// sits beside the delivery path, or is a shortcut into a surface a basic destination also
|
|
121
|
+
// opens. Spelled out here as a table so promoting an item to `advanced` forces an explicit
|
|
122
|
+
// claim about how basic mode still reaches it, rather than a silent capability loss.
|
|
123
|
+
const ALTERNATIVE_ROUTE: Record<string, string> = {
|
|
124
|
+
sandbox: 'none needed - experimentation surface, not on the delivery path',
|
|
125
|
+
kaizen: 'none needed - self-grading history, not on the delivery path',
|
|
126
|
+
'merge-thresholds': 'workspace-settings -> Merge tab',
|
|
127
|
+
'service-fragment-defaults': 'workspace-settings -> Service best practices tab',
|
|
128
|
+
'local-models': 'integrations-hub -> Local runners',
|
|
129
|
+
}
|
|
130
|
+
const advanced = NAV_CONTRIBUTIONS.filter((i) => i.advanced).map((i) => i.id)
|
|
131
|
+
expect(advanced.sort()).toEqual(Object.keys(ALTERNATIVE_ROUTE).sort())
|
|
107
132
|
})
|
|
108
133
|
|
|
109
134
|
it('keeps the tier switch itself reachable in basic mode', () => {
|
|
@@ -119,15 +144,19 @@ describe('navSlotFilter', () => {
|
|
|
119
144
|
})
|
|
120
145
|
|
|
121
146
|
it('keeps the tier and the permission axes independent — both must pass', () => {
|
|
122
|
-
// `
|
|
147
|
+
// `sandbox` is advanced AND needs integrations.manage: neither axis alone reveals it.
|
|
123
148
|
const advancedOnly: NavGates = { ...NO_GATES, advancedMode: true }
|
|
124
|
-
expect(ids(navSlotFilter(slots(), { gates: advancedOnly }))).not.toContain('
|
|
149
|
+
expect(ids(navSlotFilter(slots(), { gates: advancedOnly }))).not.toContain('sandbox')
|
|
125
150
|
|
|
126
|
-
const permissionOnly: NavGates = {
|
|
127
|
-
|
|
151
|
+
const permissionOnly: NavGates = {
|
|
152
|
+
...NO_GATES,
|
|
153
|
+
canManageIntegrations: true,
|
|
154
|
+
advancedMode: false,
|
|
155
|
+
}
|
|
156
|
+
expect(ids(navSlotFilter(slots(), { gates: permissionOnly }))).not.toContain('sandbox')
|
|
128
157
|
|
|
129
|
-
const both: NavGates = { ...NO_GATES,
|
|
130
|
-
expect(ids(navSlotFilter(slots(), { gates: both }))).toContain('
|
|
158
|
+
const both: NavGates = { ...NO_GATES, canManageIntegrations: true, advancedMode: true }
|
|
159
|
+
expect(ids(navSlotFilter(slots(), { gates: both }))).toContain('sandbox')
|
|
131
160
|
})
|
|
132
161
|
|
|
133
162
|
it('leaves at least one sidebar destination in every basic-mode section it keeps', () => {
|
|
@@ -153,13 +153,24 @@ const S = (...s: NavSurface[]) => s as readonly NavSurface[]
|
|
|
153
153
|
* with accounts enabled).
|
|
154
154
|
* - one icon per destination across shells.
|
|
155
155
|
*
|
|
156
|
-
* `advanced: true` marks the power-user half, hidden in basic interface mode. The line
|
|
157
|
-
* drawn
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
156
|
+
* `advanced: true` marks the power-user half, hidden in basic interface mode. The line is
|
|
157
|
+
* drawn by ROUTE COUNT, not by how advanced a surface feels: hiding the only way to reach a
|
|
158
|
+
* capability removes the capability from the tier, while hiding a shortcut to a surface basic
|
|
159
|
+
* mode already reaches removes nothing. So an item is advanced only when both of these hold —
|
|
160
|
+
* it is not the sole route to its capability, and nothing on the delivery path needs it:
|
|
161
|
+
*
|
|
162
|
+
* - `sandbox` / `kaizen` — experimentation and self-grading surfaces, beside the delivery
|
|
163
|
+
* path rather than on it.
|
|
164
|
+
* - `merge-thresholds` / `service-fragment-defaults` — palette shortcuts into Workspace
|
|
165
|
+
* settings tabs (Merge, Service best practices), which basic mode reaches via
|
|
166
|
+
* `workspace-settings`.
|
|
167
|
+
* - `local-models` — a per-user endpoint knob the Integrations hub already offers.
|
|
168
|
+
*
|
|
169
|
+
* Everything else stays in basic BECAUSE it is a sole route: authoring a flow
|
|
170
|
+
* (`build-pipeline`), the standards/skills library (`fragments`, whose only other route is a
|
|
171
|
+
* button two levels into Workspace settings), the PREnv + runner plumbing (`infrastructure`,
|
|
172
|
+
* `environment-setup`), and the operator/cost views that are the only aggregate read of run
|
|
173
|
+
* health and spend (`operator-dashboard`, `reports`).
|
|
163
174
|
*/
|
|
164
175
|
export const NAV_CONTRIBUTIONS: readonly NavContribution[] = [
|
|
165
176
|
{
|
|
@@ -167,7 +178,6 @@ export const NAV_CONTRIBUTIONS: readonly NavContribution[] = [
|
|
|
167
178
|
labelKey: 'nav.buildPipeline',
|
|
168
179
|
icon: 'i-lucide-workflow',
|
|
169
180
|
surfaces: S('sidebar', 'command'),
|
|
170
|
-
advanced: true,
|
|
171
181
|
gate: (g) => g.canWriteBoard,
|
|
172
182
|
action: 'buildPipeline',
|
|
173
183
|
testId: 'nav-build-pipeline',
|
|
@@ -253,7 +263,6 @@ export const NAV_CONTRIBUTIONS: readonly NavContribution[] = [
|
|
|
253
263
|
labelKey: 'nav.infrastructure',
|
|
254
264
|
icon: 'i-lucide-server-cog',
|
|
255
265
|
surfaces: S('sidebar'),
|
|
256
|
-
advanced: true,
|
|
257
266
|
gate: (g) => g.infrastructureAvailable,
|
|
258
267
|
action: 'infrastructure',
|
|
259
268
|
testId: 'nav-infrastructure',
|
|
@@ -264,7 +273,6 @@ export const NAV_CONTRIBUTIONS: readonly NavContribution[] = [
|
|
|
264
273
|
labelKey: 'nav.environmentSetup',
|
|
265
274
|
icon: 'i-lucide-flask-conical',
|
|
266
275
|
surfaces: S('sidebar'),
|
|
267
|
-
advanced: true,
|
|
268
276
|
gate: (g) => g.infrastructureAvailable,
|
|
269
277
|
action: 'environmentSetup',
|
|
270
278
|
testId: 'nav-environment-setup',
|
|
@@ -275,7 +283,6 @@ export const NAV_CONTRIBUTIONS: readonly NavContribution[] = [
|
|
|
275
283
|
labelKey: 'nav.contextFragments',
|
|
276
284
|
icon: 'i-lucide-book-marked',
|
|
277
285
|
surfaces: S('sidebar', 'command'),
|
|
278
|
-
advanced: true,
|
|
279
286
|
gate: (g) => g.libraryAvailable && g.canManageSettings,
|
|
280
287
|
action: 'fragmentLibrary',
|
|
281
288
|
testId: 'nav-fragments',
|
|
@@ -381,7 +388,6 @@ export const NAV_CONTRIBUTIONS: readonly NavContribution[] = [
|
|
|
381
388
|
labelKey: 'nav.operatorDashboard',
|
|
382
389
|
icon: 'i-lucide-gauge',
|
|
383
390
|
surfaces: S('sidebar'),
|
|
384
|
-
advanced: true,
|
|
385
391
|
gate: (g) => g.accountsEnabled && g.isAccountAdmin,
|
|
386
392
|
action: 'operatorDashboard',
|
|
387
393
|
testId: 'nav-operator-dashboard',
|
|
@@ -392,7 +398,6 @@ export const NAV_CONTRIBUTIONS: readonly NavContribution[] = [
|
|
|
392
398
|
labelKey: 'nav.reports',
|
|
393
399
|
icon: 'i-lucide-chart-column',
|
|
394
400
|
surfaces: S('sidebar'),
|
|
395
|
-
advanced: true,
|
|
396
401
|
gate: (g) => g.accountsEnabled && g.isAccountAdmin,
|
|
397
402
|
action: 'reports',
|
|
398
403
|
testId: 'nav-reports',
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest'
|
|
2
|
-
import {
|
|
2
|
+
import { totalInputTokens } from './observability'
|
|
3
3
|
|
|
4
|
-
describe('
|
|
5
|
-
it('
|
|
6
|
-
expect(
|
|
4
|
+
describe('totalInputTokens', () => {
|
|
5
|
+
it('sums all three input classes, so the headline matches Claude Code’s context gauge', () => {
|
|
6
|
+
expect(
|
|
7
|
+
totalInputTokens({ promptTokens: 685, cacheReadTokens: 31_099_813, cacheWriteTokens: 0 }),
|
|
8
|
+
).toBe(31_100_498)
|
|
7
9
|
})
|
|
8
10
|
|
|
9
|
-
it('
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
expect(freshPromptTokens(31_100_498, 31_099_813)).toBe(685)
|
|
11
|
+
it('counts cache WRITES too — they occupy the window like any other input token', () => {
|
|
12
|
+
expect(
|
|
13
|
+
totalInputTokens({ promptTokens: 100, cacheReadTokens: 900, cacheWriteTokens: 40 }),
|
|
14
|
+
).toBe(1040)
|
|
14
15
|
})
|
|
15
16
|
|
|
16
|
-
it('
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
|
|
17
|
+
it('does NOT lead with the fresh figure on a cache-dominated run', () => {
|
|
18
|
+
// The regression this pins: leading with fresh made a ~31M-token run render as 685 tokens,
|
|
19
|
+
// discounting cache reads because their dollar cost is low. Volume is the thing being
|
|
20
|
+
// measured here, and a cached token costs the same context window as a fresh one.
|
|
21
|
+
const m = { promptTokens: 685, cacheReadTokens: 31_099_813, cacheWriteTokens: 0 }
|
|
22
|
+
expect(totalInputTokens(m)).toBeGreaterThan(m.promptTokens * 1000)
|
|
21
23
|
})
|
|
22
24
|
|
|
23
|
-
it('
|
|
24
|
-
expect(
|
|
25
|
-
// cached > prompt ⇒ separate shape ⇒ fresh = prompt (never a negative number).
|
|
26
|
-
expect(freshPromptTokens(500, 600)).toBe(500)
|
|
25
|
+
it('degrades to the fresh count when an older snapshot carries no cache fields', () => {
|
|
26
|
+
expect(totalInputTokens({ promptTokens: 500 })).toBe(500)
|
|
27
27
|
})
|
|
28
28
|
})
|
|
@@ -12,31 +12,28 @@ export function formatTokens(n: number): string {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* growing transcript every turn, so on the "inclusive" shape the raw `promptTokens` sum is
|
|
18
|
-
* dominated by cache reads (often >99%) — showing THAT as "tokens burned" reads as a blow-up
|
|
19
|
-
* when almost nothing fresh was processed. This surfaces the fresh figure alongside cached.
|
|
15
|
+
* TOTAL input tokens: fresh + cache read + cache write. This is the headline "↑" figure on
|
|
16
|
+
* every LLM surface, and it deliberately COUNTS THE CACHED CLASSES.
|
|
20
17
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* the fresh figure.
|
|
18
|
+
* That is the like-for-like measure of Claude Code's own context gauge, which sums exactly these
|
|
19
|
+
* buckets because a cached token still physically occupies the context window. Leading with the
|
|
20
|
+
* fresh figure instead (what this surface used to do, on the grounds that the raw sum "reads as a
|
|
21
|
+
* blow-up") discounts cache reads because their DOLLAR cost is low — but the quota, latency and
|
|
22
|
+
* context-window cost is the whole thing an autonomous run burns, and hiding it is what let a
|
|
23
|
+
* ~31M-token run look like a 685-token one. See
|
|
24
|
+
* `docs/initiatives/token-burn-instrumentation.md`.
|
|
29
25
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
26
|
+
* The three classes are still rendered as the breakdown beneath it, because they are priced an
|
|
27
|
+
* order of magnitude apart in opposite directions — this makes the volume honest WITHOUT making
|
|
28
|
+
* the cost unreadable. The two fields are optional on an older snapshot, where absent reads as 0
|
|
29
|
+
* and the total degrades to the fresh count.
|
|
34
30
|
*/
|
|
35
|
-
export function
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
export function totalInputTokens(m: {
|
|
32
|
+
promptTokens: number
|
|
33
|
+
cacheReadTokens?: number
|
|
34
|
+
cacheWriteTokens?: number
|
|
35
|
+
}): number {
|
|
36
|
+
return m.promptTokens + (m.cacheReadTokens ?? 0) + (m.cacheWriteTokens ?? 0)
|
|
40
37
|
}
|
|
41
38
|
|
|
42
39
|
/** Compact duration: 850 → "850ms", 1500 → "1.5s", 90_000 → "1m 30s". */
|
package/i18n/locales/de.json
CHANGED
|
@@ -2906,13 +2906,23 @@
|
|
|
2906
2906
|
"transportOverhead": "Transport-Overhead",
|
|
2907
2907
|
"modelExecution": "Modellausführung",
|
|
2908
2908
|
"truncated": "{count} abgeschnitten | {count} abgeschnitten",
|
|
2909
|
-
"
|
|
2909
|
+
"inputTokensHint": "Eingabe- / Ausgabe-Tokens insgesamt. Die Eingabe zählt auch gecachte Tokens mit: Sie belegen weiterhin das Kontextfenster, genau wie es die Kontextanzeige von Claude Code zählt.",
|
|
2910
|
+
"fresh": "{tokens} frisch",
|
|
2911
|
+
"freshHint": "Eingabe, die von Grund auf verarbeitet wurde, ohne Anteil aus dem Cache",
|
|
2912
|
+
"cacheRead": "{tokens} aus dem Cache gelesen",
|
|
2913
|
+
"cacheReadHint": "Eingabe-Tokens, die aus dem Cache des Providers bedient wurden (etwa 0,1x der Preis frischer Eingabe-Tokens)",
|
|
2914
|
+
"cacheWrite": "{tokens} in den Cache geschrieben",
|
|
2915
|
+
"cacheWriteHint": "Eingabe-Tokens, die in den Cache des Providers geschrieben wurden (1,25x bis 2x der Preis frischer Eingabe-Tokens)"
|
|
2910
2916
|
},
|
|
2911
2917
|
"metricsBar": {
|
|
2912
2918
|
"calls": "{count} Aufruf | {count} Aufrufe",
|
|
2913
|
-
"
|
|
2914
|
-
"
|
|
2915
|
-
"
|
|
2919
|
+
"inputCompletionTokens": "Eingabe- / Ausgabe-Tokens insgesamt. Die Eingabe zählt auch gecachte Tokens mit: Sie belegen weiterhin das Kontextfenster, genau wie es die Kontextanzeige von Claude Code zählt.",
|
|
2920
|
+
"fresh": "{tokens} frisch",
|
|
2921
|
+
"freshHint": "Eingabe, die von Grund auf verarbeitet wurde, ohne Anteil aus dem Cache",
|
|
2922
|
+
"cacheRead": "{tokens} aus dem Cache gelesen",
|
|
2923
|
+
"cacheReadHint": "Eingabe-Tokens, die aus dem Cache des Providers bedient wurden (etwa 0,1x der Preis frischer Eingabe-Tokens)",
|
|
2924
|
+
"cacheWrite": "{tokens} in den Cache geschrieben",
|
|
2925
|
+
"cacheWriteHint": "Eingabe-Tokens, die in den Cache des Providers geschrieben wurden (1,25x bis 2x der Preis frischer Eingabe-Tokens)",
|
|
2916
2926
|
"errors": "{count} Fehler | {count} Fehler",
|
|
2917
2927
|
"warnings": "{count} Warnung | {count} Warnungen",
|
|
2918
2928
|
"outputLimit": "Ausgabelimit",
|
|
@@ -2922,7 +2932,7 @@
|
|
|
2922
2932
|
"modelExecution": "Modellausführung"
|
|
2923
2933
|
},
|
|
2924
2934
|
"call": {
|
|
2925
|
-
"tokensTitle": "{
|
|
2935
|
+
"tokensTitle": "{input} Eingabe-Tokens (davon {fresh} frisch) / {completion} Ausgabe-Tokens",
|
|
2926
2936
|
"outputUsedVsLimit": "Ausgabe genutzt vs. Limit",
|
|
2927
2937
|
"transportVsExecution": "Transport-Overhead / Modellausführung",
|
|
2928
2938
|
"error": "Fehler",
|
|
@@ -2932,7 +2942,9 @@
|
|
|
2932
2942
|
"streamed": "gestreamt",
|
|
2933
2943
|
"buffered": "gepuffert",
|
|
2934
2944
|
"maxTokens": "max_tokens {value}",
|
|
2935
|
-
"
|
|
2945
|
+
"fresh": "{tokens} frisch",
|
|
2946
|
+
"cacheRead": "{tokens} aus dem Cache gelesen",
|
|
2947
|
+
"cacheWrite": "{tokens} in den Cache geschrieben",
|
|
2936
2948
|
"total": "gesamt {duration}",
|
|
2937
2949
|
"prompt": "Prompt",
|
|
2938
2950
|
"promptPrefixOmitted": "(nur neue Nachrichten: {count} frühere ausgelassen)",
|
package/i18n/locales/en.json
CHANGED
|
@@ -1434,13 +1434,23 @@
|
|
|
1434
1434
|
"transportOverhead": "Transport overhead",
|
|
1435
1435
|
"modelExecution": "Model execution",
|
|
1436
1436
|
"truncated": "{count} truncated | {count} truncated",
|
|
1437
|
-
"
|
|
1437
|
+
"inputTokensHint": "Total input / completion tokens. Input counts cached tokens too: they still occupy the context window, exactly as Claude Code's own context gauge counts them.",
|
|
1438
|
+
"fresh": "{tokens} fresh",
|
|
1439
|
+
"freshHint": "Input processed from scratch, with nothing served from the cache",
|
|
1440
|
+
"cacheRead": "{tokens} cache read",
|
|
1441
|
+
"cacheReadHint": "Input tokens served from the provider's cache (about 0.1x the price of fresh input)",
|
|
1442
|
+
"cacheWrite": "{tokens} cache write",
|
|
1443
|
+
"cacheWriteHint": "Input tokens written into the provider's cache (1.25x to 2x the price of fresh input)"
|
|
1438
1444
|
},
|
|
1439
1445
|
"metricsBar": {
|
|
1440
1446
|
"calls": "{count} call | {count} calls",
|
|
1441
|
-
"
|
|
1442
|
-
"
|
|
1443
|
-
"
|
|
1447
|
+
"inputCompletionTokens": "Total input / completion tokens. Input counts cached tokens too: they still occupy the context window, exactly as Claude Code's own context gauge counts them.",
|
|
1448
|
+
"fresh": "{tokens} fresh",
|
|
1449
|
+
"freshHint": "Input processed from scratch, with nothing served from the cache",
|
|
1450
|
+
"cacheRead": "{tokens} cache read",
|
|
1451
|
+
"cacheReadHint": "Input tokens served from the provider's cache (about 0.1x the price of fresh input)",
|
|
1452
|
+
"cacheWrite": "{tokens} cache write",
|
|
1453
|
+
"cacheWriteHint": "Input tokens written into the provider's cache (1.25x to 2x the price of fresh input)",
|
|
1444
1454
|
"errors": "{count} error | {count} errors",
|
|
1445
1455
|
"warnings": "{count} warning | {count} warnings",
|
|
1446
1456
|
"outputLimit": "Output limit",
|
|
@@ -1450,7 +1460,7 @@
|
|
|
1450
1460
|
"modelExecution": "Model execution"
|
|
1451
1461
|
},
|
|
1452
1462
|
"call": {
|
|
1453
|
-
"tokensTitle": "{
|
|
1463
|
+
"tokensTitle": "{input} input tokens ({fresh} of them fresh) / {completion} completion tokens",
|
|
1454
1464
|
"outputUsedVsLimit": "Output used vs limit",
|
|
1455
1465
|
"transportVsExecution": "Transport overhead / model execution",
|
|
1456
1466
|
"error": "error",
|
|
@@ -1460,7 +1470,9 @@
|
|
|
1460
1470
|
"streamed": "streamed",
|
|
1461
1471
|
"buffered": "buffered",
|
|
1462
1472
|
"maxTokens": "max_tokens {value}",
|
|
1463
|
-
"
|
|
1473
|
+
"fresh": "{tokens} fresh",
|
|
1474
|
+
"cacheRead": "{tokens} cache read",
|
|
1475
|
+
"cacheWrite": "{tokens} cache write",
|
|
1464
1476
|
"total": "total {duration}",
|
|
1465
1477
|
"prompt": "Prompt",
|
|
1466
1478
|
"promptPrefixOmitted": "(new messages only: {count} earlier omitted)",
|
package/i18n/locales/es.json
CHANGED
|
@@ -1368,13 +1368,23 @@
|
|
|
1368
1368
|
"transportOverhead": "Sobrecarga de transporte",
|
|
1369
1369
|
"modelExecution": "Ejecución del modelo",
|
|
1370
1370
|
"truncated": "{count} truncada | {count} truncadas",
|
|
1371
|
-
"
|
|
1371
|
+
"inputTokensHint": "Tokens totales de entrada / salida. La entrada tambien cuenta los tokens en caché: siguen ocupando la ventana de contexto, igual que los cuenta el medidor de contexto de Claude Code.",
|
|
1372
|
+
"fresh": "{tokens} frescos",
|
|
1373
|
+
"freshHint": "Entrada procesada desde cero, sin nada servido desde la caché",
|
|
1374
|
+
"cacheRead": "{tokens} leídos de caché",
|
|
1375
|
+
"cacheReadHint": "Tokens de entrada servidos desde la caché del proveedor (unas 0,1 veces el precio de la entrada fresca)",
|
|
1376
|
+
"cacheWrite": "{tokens} escritos en caché",
|
|
1377
|
+
"cacheWriteHint": "Tokens de entrada escritos en la caché del proveedor (de 1,25 a 2 veces el precio de la entrada fresca)"
|
|
1372
1378
|
},
|
|
1373
1379
|
"metricsBar": {
|
|
1374
1380
|
"calls": "{count} llamada | {count} llamadas",
|
|
1375
|
-
"
|
|
1376
|
-
"
|
|
1377
|
-
"
|
|
1381
|
+
"inputCompletionTokens": "Tokens totales de entrada / salida. La entrada tambien cuenta los tokens en caché: siguen ocupando la ventana de contexto, igual que los cuenta el medidor de contexto de Claude Code.",
|
|
1382
|
+
"fresh": "{tokens} frescos",
|
|
1383
|
+
"freshHint": "Entrada procesada desde cero, sin nada servido desde la caché",
|
|
1384
|
+
"cacheRead": "{tokens} leídos de caché",
|
|
1385
|
+
"cacheReadHint": "Tokens de entrada servidos desde la caché del proveedor (unas 0,1 veces el precio de la entrada fresca)",
|
|
1386
|
+
"cacheWrite": "{tokens} escritos en caché",
|
|
1387
|
+
"cacheWriteHint": "Tokens de entrada escritos en la caché del proveedor (de 1,25 a 2 veces el precio de la entrada fresca)",
|
|
1378
1388
|
"errors": "{count} error | {count} errores",
|
|
1379
1389
|
"warnings": "{count} advertencia | {count} advertencias",
|
|
1380
1390
|
"outputLimit": "Límite de salida",
|
|
@@ -1384,7 +1394,7 @@
|
|
|
1384
1394
|
"modelExecution": "Ejecución del modelo"
|
|
1385
1395
|
},
|
|
1386
1396
|
"call": {
|
|
1387
|
-
"tokensTitle": "{
|
|
1397
|
+
"tokensTitle": "{input} tokens de entrada ({fresh} de ellos frescos) / {completion} tokens de salida",
|
|
1388
1398
|
"outputUsedVsLimit": "Salida usada frente al límite",
|
|
1389
1399
|
"transportVsExecution": "Sobrecarga de transporte / ejecución del modelo",
|
|
1390
1400
|
"error": "error",
|
|
@@ -1394,7 +1404,9 @@
|
|
|
1394
1404
|
"streamed": "en streaming",
|
|
1395
1405
|
"buffered": "en búfer",
|
|
1396
1406
|
"maxTokens": "max_tokens {value}",
|
|
1397
|
-
"
|
|
1407
|
+
"fresh": "{tokens} frescos",
|
|
1408
|
+
"cacheRead": "{tokens} leídos de caché",
|
|
1409
|
+
"cacheWrite": "{tokens} escritos en caché",
|
|
1398
1410
|
"total": "total {duration}",
|
|
1399
1411
|
"prompt": "Prompt",
|
|
1400
1412
|
"promptPrefixOmitted": "(solo mensajes nuevos: {count} anteriores omitidos)",
|
package/i18n/locales/fr.json
CHANGED
|
@@ -1368,13 +1368,23 @@
|
|
|
1368
1368
|
"transportOverhead": "Surcoût de transport",
|
|
1369
1369
|
"modelExecution": "Exécution du modèle",
|
|
1370
1370
|
"truncated": "{count} tronqué | {count} tronqués",
|
|
1371
|
-
"
|
|
1371
|
+
"inputTokensHint": "Total des tokens d'entrée / de sortie. L'entree compte aussi les tokens en cache : ils occupent toujours la fenêtre de contexte, exactement comme les compte la jauge de contexte de Claude Code.",
|
|
1372
|
+
"fresh": "{tokens} frais",
|
|
1373
|
+
"freshHint": "Entrée traitée de zero, sans rien servi depuis le cache",
|
|
1374
|
+
"cacheRead": "{tokens} lus depuis le cache",
|
|
1375
|
+
"cacheReadHint": "Tokens d'entrée servis depuis le cache du fournisseur (environ 0,1 fois le prix d'une entrée fraîche)",
|
|
1376
|
+
"cacheWrite": "{tokens} écrits dans le cache",
|
|
1377
|
+
"cacheWriteHint": "Tokens d'entrée écrits dans le cache du fournisseur (1,25 à 2 fois le prix d'une entrée fraîche)"
|
|
1372
1378
|
},
|
|
1373
1379
|
"metricsBar": {
|
|
1374
1380
|
"calls": "{count} appel | {count} appels",
|
|
1375
|
-
"
|
|
1376
|
-
"
|
|
1377
|
-
"
|
|
1381
|
+
"inputCompletionTokens": "Total des tokens d'entrée / de sortie. L'entree compte aussi les tokens en cache : ils occupent toujours la fenêtre de contexte, exactement comme les compte la jauge de contexte de Claude Code.",
|
|
1382
|
+
"fresh": "{tokens} frais",
|
|
1383
|
+
"freshHint": "Entrée traitée de zero, sans rien servi depuis le cache",
|
|
1384
|
+
"cacheRead": "{tokens} lus depuis le cache",
|
|
1385
|
+
"cacheReadHint": "Tokens d'entrée servis depuis le cache du fournisseur (environ 0,1 fois le prix d'une entrée fraîche)",
|
|
1386
|
+
"cacheWrite": "{tokens} écrits dans le cache",
|
|
1387
|
+
"cacheWriteHint": "Tokens d'entrée écrits dans le cache du fournisseur (1,25 à 2 fois le prix d'une entrée fraîche)",
|
|
1378
1388
|
"errors": "{count} erreur | {count} erreurs",
|
|
1379
1389
|
"warnings": "{count} avertissement | {count} avertissements",
|
|
1380
1390
|
"outputLimit": "Limite de sortie",
|
|
@@ -1384,7 +1394,7 @@
|
|
|
1384
1394
|
"modelExecution": "Exécution du modèle"
|
|
1385
1395
|
},
|
|
1386
1396
|
"call": {
|
|
1387
|
-
"tokensTitle": "{
|
|
1397
|
+
"tokensTitle": "{input} tokens d'entrée (dont {fresh} frais) / {completion} tokens de sortie",
|
|
1388
1398
|
"outputUsedVsLimit": "Sortie utilisée vs limite",
|
|
1389
1399
|
"transportVsExecution": "Surcoût de transport / exécution du modèle",
|
|
1390
1400
|
"error": "erreur",
|
|
@@ -1394,7 +1404,9 @@
|
|
|
1394
1404
|
"streamed": "en streaming",
|
|
1395
1405
|
"buffered": "en mémoire tampon",
|
|
1396
1406
|
"maxTokens": "max_tokens {value}",
|
|
1397
|
-
"
|
|
1407
|
+
"fresh": "{tokens} frais",
|
|
1408
|
+
"cacheRead": "{tokens} lus depuis le cache",
|
|
1409
|
+
"cacheWrite": "{tokens} écrits dans le cache",
|
|
1398
1410
|
"total": "total {duration}",
|
|
1399
1411
|
"prompt": "Prompt",
|
|
1400
1412
|
"promptPrefixOmitted": "(nouveaux messages uniquement : {count} antérieurs omis)",
|
package/i18n/locales/he.json
CHANGED
|
@@ -1368,13 +1368,23 @@
|
|
|
1368
1368
|
"transportOverhead": "תקורת תעבורה",
|
|
1369
1369
|
"modelExecution": "הרצת מודל",
|
|
1370
1370
|
"truncated": "{count} נקטע | {count} נקטעו",
|
|
1371
|
-
"
|
|
1371
|
+
"inputTokensHint": "סך טוקני הקלט / הפלט. הקלט סופר גם טוקנים מהמטמון: הם עדיין תופסים את חלון ההקשר, בדיוק כפי שמד ההקשר של Claude Code סופר אותם.",
|
|
1372
|
+
"fresh": "{tokens} חדשים",
|
|
1373
|
+
"freshHint": "קלט שעובד מאפס, ללא שום חלק שהוגש מהמטמון",
|
|
1374
|
+
"cacheRead": "{tokens} נקראו מהמטמון",
|
|
1375
|
+
"cacheReadHint": "טוקני קלט שהוגשו ממטמון הספק (כ-0.1 ממחיר קלט חדש)",
|
|
1376
|
+
"cacheWrite": "{tokens} נכתבו למטמון",
|
|
1377
|
+
"cacheWriteHint": "טוקני קלט שנכתבו למטמון הספק (פי 1.25 עד 2 ממחיר קלט חדש)"
|
|
1372
1378
|
},
|
|
1373
1379
|
"metricsBar": {
|
|
1374
1380
|
"calls": "{count} קריאה | {count} קריאות",
|
|
1375
|
-
"
|
|
1376
|
-
"
|
|
1377
|
-
"
|
|
1381
|
+
"inputCompletionTokens": "סך טוקני הקלט / הפלט. הקלט סופר גם טוקנים מהמטמון: הם עדיין תופסים את חלון ההקשר, בדיוק כפי שמד ההקשר של Claude Code סופר אותם.",
|
|
1382
|
+
"fresh": "{tokens} חדשים",
|
|
1383
|
+
"freshHint": "קלט שעובד מאפס, ללא שום חלק שהוגש מהמטמון",
|
|
1384
|
+
"cacheRead": "{tokens} נקראו מהמטמון",
|
|
1385
|
+
"cacheReadHint": "טוקני קלט שהוגשו ממטמון הספק (כ-0.1 ממחיר קלט חדש)",
|
|
1386
|
+
"cacheWrite": "{tokens} נכתבו למטמון",
|
|
1387
|
+
"cacheWriteHint": "טוקני קלט שנכתבו למטמון הספק (פי 1.25 עד 2 ממחיר קלט חדש)",
|
|
1378
1388
|
"errors": "{count} שגיאה | {count} שגיאות",
|
|
1379
1389
|
"warnings": "{count} אזהרה | {count} אזהרות",
|
|
1380
1390
|
"outputLimit": "מגבלת פלט",
|
|
@@ -1384,7 +1394,7 @@
|
|
|
1384
1394
|
"modelExecution": "הרצת מודל"
|
|
1385
1395
|
},
|
|
1386
1396
|
"call": {
|
|
1387
|
-
"tokensTitle": "{
|
|
1397
|
+
"tokensTitle": "{input} טוקני קלט ({fresh} מהם חדשים) / {completion} טוקני פלט",
|
|
1388
1398
|
"outputUsedVsLimit": "פלט בשימוש לעומת המגבלה",
|
|
1389
1399
|
"transportVsExecution": "תקורת תעבורה / הרצת מודל",
|
|
1390
1400
|
"error": "שגיאה",
|
|
@@ -1394,7 +1404,9 @@
|
|
|
1394
1404
|
"streamed": "הוזרם",
|
|
1395
1405
|
"buffered": "באגירה",
|
|
1396
1406
|
"maxTokens": "max_tokens {value}",
|
|
1397
|
-
"
|
|
1407
|
+
"fresh": "{tokens} חדשים",
|
|
1408
|
+
"cacheRead": "{tokens} נקראו מהמטמון",
|
|
1409
|
+
"cacheWrite": "{tokens} נכתבו למטמון",
|
|
1398
1410
|
"total": "סך הכל {duration}",
|
|
1399
1411
|
"prompt": "פרומפט",
|
|
1400
1412
|
"promptPrefixOmitted": "(הודעות חדשות בלבד: {count} מוקדמות יותר הושמטו)",
|
package/i18n/locales/it.json
CHANGED
|
@@ -2906,13 +2906,23 @@
|
|
|
2906
2906
|
"transportOverhead": "Overhead di trasporto",
|
|
2907
2907
|
"modelExecution": "Esecuzione del modello",
|
|
2908
2908
|
"truncated": "{count} troncata | {count} troncate",
|
|
2909
|
-
"
|
|
2909
|
+
"inputTokensHint": "Token totali di input / output. L'input conta anche i token in cache: occupano comunque la finestra di contesto, esattamente come li conta l'indicatore di contesto di Claude Code.",
|
|
2910
|
+
"fresh": "{tokens} freschi",
|
|
2911
|
+
"freshHint": "Input elaborato da zero, senza nulla servito dalla cache",
|
|
2912
|
+
"cacheRead": "{tokens} letti dalla cache",
|
|
2913
|
+
"cacheReadHint": "Token di input serviti dalla cache del provider (circa 0,1 volte il prezzo dell'input fresco)",
|
|
2914
|
+
"cacheWrite": "{tokens} scritti nella cache",
|
|
2915
|
+
"cacheWriteHint": "Token di input scritti nella cache del provider (da 1,25 a 2 volte il prezzo dell'input fresco)"
|
|
2910
2916
|
},
|
|
2911
2917
|
"metricsBar": {
|
|
2912
2918
|
"calls": "{count} chiamata | {count} chiamate",
|
|
2913
|
-
"
|
|
2914
|
-
"
|
|
2915
|
-
"
|
|
2919
|
+
"inputCompletionTokens": "Token totali di input / output. L'input conta anche i token in cache: occupano comunque la finestra di contesto, esattamente come li conta l'indicatore di contesto di Claude Code.",
|
|
2920
|
+
"fresh": "{tokens} freschi",
|
|
2921
|
+
"freshHint": "Input elaborato da zero, senza nulla servito dalla cache",
|
|
2922
|
+
"cacheRead": "{tokens} letti dalla cache",
|
|
2923
|
+
"cacheReadHint": "Token di input serviti dalla cache del provider (circa 0,1 volte il prezzo dell'input fresco)",
|
|
2924
|
+
"cacheWrite": "{tokens} scritti nella cache",
|
|
2925
|
+
"cacheWriteHint": "Token di input scritti nella cache del provider (da 1,25 a 2 volte il prezzo dell'input fresco)",
|
|
2916
2926
|
"errors": "{count} errore | {count} errori",
|
|
2917
2927
|
"warnings": "{count} avviso | {count} avvisi",
|
|
2918
2928
|
"outputLimit": "Limite di output",
|
|
@@ -2922,7 +2932,7 @@
|
|
|
2922
2932
|
"modelExecution": "Esecuzione del modello"
|
|
2923
2933
|
},
|
|
2924
2934
|
"call": {
|
|
2925
|
-
"tokensTitle": "{
|
|
2935
|
+
"tokensTitle": "{input} token di input (di cui {fresh} freschi) / {completion} token di output",
|
|
2926
2936
|
"outputUsedVsLimit": "Output usato vs limite",
|
|
2927
2937
|
"transportVsExecution": "Overhead di trasporto / esecuzione del modello",
|
|
2928
2938
|
"error": "errore",
|
|
@@ -2932,7 +2942,9 @@
|
|
|
2932
2942
|
"streamed": "in streaming",
|
|
2933
2943
|
"buffered": "bufferizzato",
|
|
2934
2944
|
"maxTokens": "max_tokens {value}",
|
|
2935
|
-
"
|
|
2945
|
+
"fresh": "{tokens} freschi",
|
|
2946
|
+
"cacheRead": "{tokens} letti dalla cache",
|
|
2947
|
+
"cacheWrite": "{tokens} scritti nella cache",
|
|
2936
2948
|
"total": "totale {duration}",
|
|
2937
2949
|
"prompt": "Prompt",
|
|
2938
2950
|
"promptPrefixOmitted": "(solo nuovi messaggi: {count} precedenti omessi)",
|
package/i18n/locales/ja.json
CHANGED
|
@@ -1368,13 +1368,23 @@
|
|
|
1368
1368
|
"transportOverhead": "転送オーバーヘッド",
|
|
1369
1369
|
"modelExecution": "モデル実行",
|
|
1370
1370
|
"truncated": "{count} 件が切り詰め | {count} 件が切り詰め",
|
|
1371
|
-
"
|
|
1371
|
+
"inputTokensHint": "入力 / 出力トークンの合計。入力にはキャッシュされたトークンも含まれます。それらも依然としてコンテキストウィンドウを占有するため、Claude Code のコンテキスト表示と同じ数え方です。",
|
|
1372
|
+
"fresh": "{tokens} 新規",
|
|
1373
|
+
"freshHint": "キャッシュから提供された分を含まない、ゼロから処理された入力",
|
|
1374
|
+
"cacheRead": "{tokens} キャッシュ読み取り",
|
|
1375
|
+
"cacheReadHint": "プロバイダーのキャッシュから提供された入力トークン (新規入力の約 0.1 倍の価格)",
|
|
1376
|
+
"cacheWrite": "{tokens} キャッシュ書き込み",
|
|
1377
|
+
"cacheWriteHint": "プロバイダーのキャッシュに書き込まれた入力トークン (新規入力の 1.25 倍から 2 倍の価格)"
|
|
1372
1378
|
},
|
|
1373
1379
|
"metricsBar": {
|
|
1374
1380
|
"calls": "{count} 件の呼び出し | {count} 件の呼び出し",
|
|
1375
|
-
"
|
|
1376
|
-
"
|
|
1377
|
-
"
|
|
1381
|
+
"inputCompletionTokens": "入力 / 出力トークンの合計。入力にはキャッシュされたトークンも含まれます。それらも依然としてコンテキストウィンドウを占有するため、Claude Code のコンテキスト表示と同じ数え方です。",
|
|
1382
|
+
"fresh": "{tokens} 新規",
|
|
1383
|
+
"freshHint": "キャッシュから提供された分を含まない、ゼロから処理された入力",
|
|
1384
|
+
"cacheRead": "{tokens} キャッシュ読み取り",
|
|
1385
|
+
"cacheReadHint": "プロバイダーのキャッシュから提供された入力トークン (新規入力の約 0.1 倍の価格)",
|
|
1386
|
+
"cacheWrite": "{tokens} キャッシュ書き込み",
|
|
1387
|
+
"cacheWriteHint": "プロバイダーのキャッシュに書き込まれた入力トークン (新規入力の 1.25 倍から 2 倍の価格)",
|
|
1378
1388
|
"errors": "{count} 件のエラー | {count} 件のエラー",
|
|
1379
1389
|
"warnings": "{count} 件の警告 | {count} 件の警告",
|
|
1380
1390
|
"outputLimit": "出力上限",
|
|
@@ -1384,7 +1394,7 @@
|
|
|
1384
1394
|
"modelExecution": "モデル実行"
|
|
1385
1395
|
},
|
|
1386
1396
|
"call": {
|
|
1387
|
-
"tokensTitle": "{
|
|
1397
|
+
"tokensTitle": "入力トークン {input} 件 (うち新規 {fresh} 件) / 出力トークン {completion} 件",
|
|
1388
1398
|
"outputUsedVsLimit": "使用済み出力 vs 上限",
|
|
1389
1399
|
"transportVsExecution": "転送オーバーヘッド / モデル実行",
|
|
1390
1400
|
"error": "エラー",
|
|
@@ -1394,7 +1404,9 @@
|
|
|
1394
1404
|
"streamed": "ストリーミング",
|
|
1395
1405
|
"buffered": "バッファ済み",
|
|
1396
1406
|
"maxTokens": "max_tokens {value}",
|
|
1397
|
-
"
|
|
1407
|
+
"fresh": "{tokens} 新規",
|
|
1408
|
+
"cacheRead": "{tokens} キャッシュ読み取り",
|
|
1409
|
+
"cacheWrite": "{tokens} キャッシュ書き込み",
|
|
1398
1410
|
"total": "合計 {duration}",
|
|
1399
1411
|
"prompt": "プロンプト",
|
|
1400
1412
|
"promptPrefixOmitted": "(新規メッセージのみ: 以前の {count} 件を省略)",
|
package/i18n/locales/pl.json
CHANGED
|
@@ -1368,13 +1368,23 @@
|
|
|
1368
1368
|
"transportOverhead": "Narzut transportu",
|
|
1369
1369
|
"modelExecution": "Wykonanie modelu",
|
|
1370
1370
|
"truncated": "{count} obcięte | {count} obcięte | {count} obciętych",
|
|
1371
|
-
"
|
|
1371
|
+
"inputTokensHint": "Łączna liczba tokenów wejścia / wyjscia. Wejście liczy takze tokeny z pamięci podręcznej: nadal zajmują okno kontekstu, dokładnie tak, jak liczy je wskaźnik kontekstu w Claude Code.",
|
|
1372
|
+
"fresh": "{tokens} świeżych",
|
|
1373
|
+
"freshHint": "Wejście przetworzone od zera, bez żadnej części obsłużonej z pamięci podręcznej",
|
|
1374
|
+
"cacheRead": "{tokens} odczytane z pamięci podręcznej",
|
|
1375
|
+
"cacheReadHint": "Tokeny wejściowe obsłużone z pamięci podręcznej dostawcy (około 0,1 ceny świeżego wejścia)",
|
|
1376
|
+
"cacheWrite": "{tokens} zapisane do pamięci podręcznej",
|
|
1377
|
+
"cacheWriteHint": "Tokeny wejściowe zapisane do pamięci podręcznej dostawcy (od 1,25 do 2 razy cena świeżego wejścia)"
|
|
1372
1378
|
},
|
|
1373
1379
|
"metricsBar": {
|
|
1374
1380
|
"calls": "{count} wywołanie | {count} wywołania | {count} wywołań",
|
|
1375
|
-
"
|
|
1376
|
-
"
|
|
1377
|
-
"
|
|
1381
|
+
"inputCompletionTokens": "Łączna liczba tokenów wejścia / wyjscia. Wejście liczy takze tokeny z pamięci podręcznej: nadal zajmują okno kontekstu, dokładnie tak, jak liczy je wskaźnik kontekstu w Claude Code.",
|
|
1382
|
+
"fresh": "{tokens} świeżych",
|
|
1383
|
+
"freshHint": "Wejście przetworzone od zera, bez żadnej części obsłużonej z pamięci podręcznej",
|
|
1384
|
+
"cacheRead": "{tokens} odczytane z pamięci podręcznej",
|
|
1385
|
+
"cacheReadHint": "Tokeny wejściowe obsłużone z pamięci podręcznej dostawcy (około 0,1 ceny świeżego wejścia)",
|
|
1386
|
+
"cacheWrite": "{tokens} zapisane do pamięci podręcznej",
|
|
1387
|
+
"cacheWriteHint": "Tokeny wejściowe zapisane do pamięci podręcznej dostawcy (od 1,25 do 2 razy cena świeżego wejścia)",
|
|
1378
1388
|
"errors": "{count} błąd | {count} błędy | {count} błędów",
|
|
1379
1389
|
"warnings": "{count} ostrzeżenie | {count} ostrzeżenia | {count} ostrzeżeń",
|
|
1380
1390
|
"outputLimit": "Limit wyjścia",
|
|
@@ -1384,7 +1394,7 @@
|
|
|
1384
1394
|
"modelExecution": "Wykonanie modelu"
|
|
1385
1395
|
},
|
|
1386
1396
|
"call": {
|
|
1387
|
-
"tokensTitle": "{
|
|
1397
|
+
"tokensTitle": "{input} tokenów wejścia (w tym {fresh} świeżych) / {completion} tokenów wyjścia",
|
|
1388
1398
|
"outputUsedVsLimit": "Użyte wyjście a limit",
|
|
1389
1399
|
"transportVsExecution": "Narzut transportu / wykonanie modelu",
|
|
1390
1400
|
"error": "błąd",
|
|
@@ -1394,7 +1404,9 @@
|
|
|
1394
1404
|
"streamed": "strumieniowane",
|
|
1395
1405
|
"buffered": "buforowane",
|
|
1396
1406
|
"maxTokens": "max_tokens {value}",
|
|
1397
|
-
"
|
|
1407
|
+
"fresh": "{tokens} świeżych",
|
|
1408
|
+
"cacheRead": "{tokens} odczytane z pamięci podręcznej",
|
|
1409
|
+
"cacheWrite": "{tokens} zapisane do pamięci podręcznej",
|
|
1398
1410
|
"total": "łącznie {duration}",
|
|
1399
1411
|
"prompt": "Prompt",
|
|
1400
1412
|
"promptPrefixOmitted": "(tylko nowe wiadomości: {count} wcześniejszych pominięto)",
|
package/i18n/locales/tr.json
CHANGED
|
@@ -1368,13 +1368,23 @@
|
|
|
1368
1368
|
"transportOverhead": "Taşıma yükü",
|
|
1369
1369
|
"modelExecution": "Model yürütme",
|
|
1370
1370
|
"truncated": "{count} kesildi | {count} kesildi",
|
|
1371
|
-
"
|
|
1371
|
+
"inputTokensHint": "Toplam giriş / çıkış token'i. Giriş, önbelleğe alınmış token'ları da sayar: bunlar hâlâ bağlam penceresini kaplar, tıpkı Claude Code'un kendi bağlam göstergesinin saydığı gibi.",
|
|
1372
|
+
"fresh": "{tokens} yeni",
|
|
1373
|
+
"freshHint": "Önbellekten hiçbir şey sunulmadan sıfırdan işlenen giriş",
|
|
1374
|
+
"cacheRead": "{tokens} önbellekten okundu",
|
|
1375
|
+
"cacheReadHint": "Sağlayıcının önbelleğinden sunulan giriş token'ları (yeni girişin yaklaşık 0,1 katı fiyat)",
|
|
1376
|
+
"cacheWrite": "{tokens} önbelleğe yazıldı",
|
|
1377
|
+
"cacheWriteHint": "Sağlayıcının önbelleğine yazılan giriş token'ları (yeni girişin 1,25 ila 2 katı fiyat)"
|
|
1372
1378
|
},
|
|
1373
1379
|
"metricsBar": {
|
|
1374
1380
|
"calls": "{count} çağrı | {count} çağrı",
|
|
1375
|
-
"
|
|
1376
|
-
"
|
|
1377
|
-
"
|
|
1381
|
+
"inputCompletionTokens": "Toplam giriş / çıkış token'i. Giriş, önbelleğe alınmış token'ları da sayar: bunlar hâlâ bağlam penceresini kaplar, tıpkı Claude Code'un kendi bağlam göstergesinin saydığı gibi.",
|
|
1382
|
+
"fresh": "{tokens} yeni",
|
|
1383
|
+
"freshHint": "Önbellekten hiçbir şey sunulmadan sıfırdan işlenen giriş",
|
|
1384
|
+
"cacheRead": "{tokens} önbellekten okundu",
|
|
1385
|
+
"cacheReadHint": "Sağlayıcının önbelleğinden sunulan giriş token'ları (yeni girişin yaklaşık 0,1 katı fiyat)",
|
|
1386
|
+
"cacheWrite": "{tokens} önbelleğe yazıldı",
|
|
1387
|
+
"cacheWriteHint": "Sağlayıcının önbelleğine yazılan giriş token'ları (yeni girişin 1,25 ila 2 katı fiyat)",
|
|
1378
1388
|
"errors": "{count} hata | {count} hata",
|
|
1379
1389
|
"warnings": "{count} uyarı | {count} uyarı",
|
|
1380
1390
|
"outputLimit": "Çıkış sınırı",
|
|
@@ -1384,7 +1394,7 @@
|
|
|
1384
1394
|
"modelExecution": "Model yürütme"
|
|
1385
1395
|
},
|
|
1386
1396
|
"call": {
|
|
1387
|
-
"tokensTitle": "{
|
|
1397
|
+
"tokensTitle": "{input} giriş token'i ({fresh} tanesi yeni) / {completion} çıkış token'i",
|
|
1388
1398
|
"outputUsedVsLimit": "Kullanılan çıkış ile sınır",
|
|
1389
1399
|
"transportVsExecution": "Taşıma yükü / model yürütme",
|
|
1390
1400
|
"error": "hata",
|
|
@@ -1394,7 +1404,9 @@
|
|
|
1394
1404
|
"streamed": "akışlı",
|
|
1395
1405
|
"buffered": "ara belleğe alınmış",
|
|
1396
1406
|
"maxTokens": "max_tokens {value}",
|
|
1397
|
-
"
|
|
1407
|
+
"fresh": "{tokens} yeni",
|
|
1408
|
+
"cacheRead": "{tokens} önbellekten okundu",
|
|
1409
|
+
"cacheWrite": "{tokens} önbelleğe yazıldı",
|
|
1398
1410
|
"total": "toplam {duration}",
|
|
1399
1411
|
"prompt": "İstem",
|
|
1400
1412
|
"promptPrefixOmitted": "(yalnızca yeni mesajlar: {count} öncekisi atlandı)",
|
package/i18n/locales/uk.json
CHANGED
|
@@ -1368,13 +1368,23 @@
|
|
|
1368
1368
|
"transportOverhead": "Накладні витрати транспорту",
|
|
1369
1369
|
"modelExecution": "Виконання моделі",
|
|
1370
1370
|
"truncated": "{count} обрізаний | {count} обрізані | {count} обрізаних",
|
|
1371
|
-
"
|
|
1371
|
+
"inputTokensHint": "Загальна кількість токенів входу / виходу. Вхід враховує й токени з кешу: вони так само займають вікно контексту, точно як їх рахує індикатор контексту в Claude Code.",
|
|
1372
|
+
"fresh": "{tokens} нових",
|
|
1373
|
+
"freshHint": "Вхід, оброблений з нуля, без жодної частини з кешу",
|
|
1374
|
+
"cacheRead": "{tokens} прочитано з кешу",
|
|
1375
|
+
"cacheReadHint": "Вхідні токени, надані з кешу провайдера (приблизно 0,1 ціни нових вхідних токенів)",
|
|
1376
|
+
"cacheWrite": "{tokens} записано в кеш",
|
|
1377
|
+
"cacheWriteHint": "Вхідні токени, записані в кеш провайдера (від 1,25 до 2 разів ціна нових вхідних токенів)"
|
|
1372
1378
|
},
|
|
1373
1379
|
"metricsBar": {
|
|
1374
1380
|
"calls": "{count} виклик | {count} виклики | {count} викликів",
|
|
1375
|
-
"
|
|
1376
|
-
"
|
|
1377
|
-
"
|
|
1381
|
+
"inputCompletionTokens": "Загальна кількість токенів входу / виходу. Вхід враховує й токени з кешу: вони так само займають вікно контексту, точно як їх рахує індикатор контексту в Claude Code.",
|
|
1382
|
+
"fresh": "{tokens} нових",
|
|
1383
|
+
"freshHint": "Вхід, оброблений з нуля, без жодної частини з кешу",
|
|
1384
|
+
"cacheRead": "{tokens} прочитано з кешу",
|
|
1385
|
+
"cacheReadHint": "Вхідні токени, надані з кешу провайдера (приблизно 0,1 ціни нових вхідних токенів)",
|
|
1386
|
+
"cacheWrite": "{tokens} записано в кеш",
|
|
1387
|
+
"cacheWriteHint": "Вхідні токени, записані в кеш провайдера (від 1,25 до 2 разів ціна нових вхідних токенів)",
|
|
1378
1388
|
"errors": "{count} помилка | {count} помилки | {count} помилок",
|
|
1379
1389
|
"warnings": "{count} попередження | {count} попередження | {count} попереджень",
|
|
1380
1390
|
"outputLimit": "Ліміт виводу",
|
|
@@ -1384,7 +1394,7 @@
|
|
|
1384
1394
|
"modelExecution": "Виконання моделі"
|
|
1385
1395
|
},
|
|
1386
1396
|
"call": {
|
|
1387
|
-
"tokensTitle": "{
|
|
1397
|
+
"tokensTitle": "{input} токенів входу (з них {fresh} нових) / {completion} токенів виходу",
|
|
1388
1398
|
"outputUsedVsLimit": "Використано виводу проти ліміту",
|
|
1389
1399
|
"transportVsExecution": "Накладні витрати транспорту / виконання моделі",
|
|
1390
1400
|
"error": "помилка",
|
|
@@ -1394,7 +1404,9 @@
|
|
|
1394
1404
|
"streamed": "потоково",
|
|
1395
1405
|
"buffered": "буферизовано",
|
|
1396
1406
|
"maxTokens": "max_tokens {value}",
|
|
1397
|
-
"
|
|
1407
|
+
"fresh": "{tokens} нових",
|
|
1408
|
+
"cacheRead": "{tokens} прочитано з кешу",
|
|
1409
|
+
"cacheWrite": "{tokens} записано в кеш",
|
|
1398
1410
|
"total": "усього {duration}",
|
|
1399
1411
|
"prompt": "Запит",
|
|
1400
1412
|
"promptPrefixOmitted": "(лише нові повідомлення: {count} раніших пропущено)",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.170.0",
|
|
4
4
|
"description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"valibot": "^1.4.2",
|
|
41
41
|
"vue": "3.5.40",
|
|
42
42
|
"wretch": "^3.0.9",
|
|
43
|
-
"@cat-factory/contracts": "0.
|
|
43
|
+
"@cat-factory/contracts": "0.182.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@toad-contracts/testing": "0.3.2",
|