@cat-factory/app 0.144.0 → 0.145.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/app/components/observability/StepMetricsBar.vue +8 -1
- package/app/components/panels/ObservabilityPanel.vue +20 -3
- package/app/components/panels/inspector/TaskExecution.vue +23 -0
- package/app/components/pipeline/PipelineProgress.vue +33 -1
- package/app/components/prReview/PrReviewWindow.vue +87 -5
- package/app/stores/ui/resultViews.ts +8 -3
- package/app/stores/ui.dispatch.spec.ts +99 -0
- package/app/utils/catalog.spec.ts +1 -0
- package/app/utils/catalog.ts +18 -0
- package/app/utils/observability.spec.ts +28 -0
- package/app/utils/observability.ts +28 -0
- package/i18n/locales/de.json +12 -5
- package/i18n/locales/en.json +12 -5
- package/i18n/locales/es.json +12 -5
- package/i18n/locales/fr.json +12 -5
- package/i18n/locales/he.json +12 -5
- package/i18n/locales/it.json +12 -5
- package/i18n/locales/ja.json +12 -5
- package/i18n/locales/pl.json +12 -5
- package/i18n/locales/tr.json +12 -5
- package/i18n/locales/uk.json +12 -5
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ import type { StepMetrics } from '~/types/execution'
|
|
|
4
4
|
import {
|
|
5
5
|
formatMs,
|
|
6
6
|
formatTokens,
|
|
7
|
+
freshPromptTokens,
|
|
7
8
|
headroomColor,
|
|
8
9
|
headroomRatio,
|
|
9
10
|
pct,
|
|
@@ -22,6 +23,12 @@ defineEmits<{ inspect: [] }>()
|
|
|
22
23
|
const { t } = useI18n()
|
|
23
24
|
|
|
24
25
|
const m = computed(() => props.metrics)
|
|
26
|
+
// The headline "↑" is FRESH (uncached) input, not the raw prompt-token sum: a long agentic
|
|
27
|
+
// run re-sends its whole transcript every turn, so the raw sum is ~all cache reads and reads
|
|
28
|
+
// as a blow-up. The cached prefix is shown separately (the green chip) so the two are distinct.
|
|
29
|
+
const freshPrompt = computed(() =>
|
|
30
|
+
freshPromptTokens(m.value.promptTokens, m.value.cachedPromptTokens ?? 0),
|
|
31
|
+
)
|
|
25
32
|
const headroom = computed(() => headroomRatio(m.value))
|
|
26
33
|
const transport = computed(() => transportRatio(m.value))
|
|
27
34
|
const headroomTone = computed(() => headroomColor(headroom.value, m.value.truncatedCalls > 0))
|
|
@@ -48,7 +55,7 @@ const headroomTone = computed(() => headroomColor(headroom.value, m.value.trunca
|
|
|
48
55
|
class="tabular-nums text-slate-400"
|
|
49
56
|
:title="t('observability.metricsBar.promptCompletionTokens')"
|
|
50
57
|
>
|
|
51
|
-
{{ formatTokens(
|
|
58
|
+
{{ formatTokens(freshPrompt) }}↑ {{ formatTokens(m.completionTokens) }}↓
|
|
52
59
|
</span>
|
|
53
60
|
<span
|
|
54
61
|
v-if="(m.cachedPromptTokens ?? 0) > 0"
|
|
@@ -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, pct } from '~/utils/observability'
|
|
11
|
+
import { formatMs, formatTokens, freshPromptTokens, pct } 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,9 +126,15 @@ 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
|
+
const promptTokens = sum(c, (x) => x.promptTokens)
|
|
130
|
+
const cachedPromptTokens = sum(c, (x) => x.cachedPromptTokens)
|
|
129
131
|
return {
|
|
130
132
|
calls: c.length,
|
|
131
|
-
promptTokens
|
|
133
|
+
promptTokens,
|
|
134
|
+
cachedPromptTokens,
|
|
135
|
+
// Fresh (uncached) input — the raw prompt-token sum is dominated by per-turn cache reads
|
|
136
|
+
// on a long agentic run, so surface fresh vs cached rather than the misleading raw total.
|
|
137
|
+
freshPromptTokens: freshPromptTokens(promptTokens, cachedPromptTokens),
|
|
132
138
|
completionTokens: sum(c, (x) => x.completionTokens),
|
|
133
139
|
upstreamMs,
|
|
134
140
|
overheadMs,
|
|
@@ -284,8 +290,19 @@ function exportJson() {
|
|
|
284
290
|
{{ t('observability.summary.tokensInOut') }}
|
|
285
291
|
</dt>
|
|
286
292
|
<dd class="mt-0.5 tabular-nums text-slate-200">
|
|
287
|
-
{{ formatTokens(totals.
|
|
293
|
+
{{ formatTokens(totals.freshPromptTokens) }} /
|
|
288
294
|
{{ formatTokens(totals.completionTokens) }}
|
|
295
|
+
<span
|
|
296
|
+
v-if="totals.cachedPromptTokens > 0"
|
|
297
|
+
class="ms-1 text-[11px] text-emerald-400/80"
|
|
298
|
+
>
|
|
299
|
+
·
|
|
300
|
+
{{
|
|
301
|
+
t('observability.summary.cached', {
|
|
302
|
+
tokens: formatTokens(totals.cachedPromptTokens),
|
|
303
|
+
})
|
|
304
|
+
}}
|
|
305
|
+
</span>
|
|
289
306
|
</dd>
|
|
290
307
|
</div>
|
|
291
308
|
<div>
|
|
@@ -151,6 +151,12 @@ function openForkFor(i: number) {
|
|
|
151
151
|
if (instance.value) ui.openForkDecision(instance.value.id, i)
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
// Open the PR deep-review findings-selection window for a pr-reviewer step parked awaiting
|
|
155
|
+
// a selection (its dedicated chip, mirroring the fork-decision one above).
|
|
156
|
+
function openPrReviewFor(i: number) {
|
|
157
|
+
if (instance.value) ui.openPrReview(instance.value.id, i)
|
|
158
|
+
}
|
|
159
|
+
|
|
154
160
|
// Stop the run WITHOUT deleting it: halts the container + driver and records a
|
|
155
161
|
// `cancelled` failure, leaving the run readable + retryable (the block goes
|
|
156
162
|
// `blocked`). The destructive reset (delete the run, return the task to `planned`)
|
|
@@ -393,6 +399,23 @@ async function mergePr() {
|
|
|
393
399
|
>
|
|
394
400
|
{{ t('inspector.execution.chooseApproach') }}
|
|
395
401
|
</UButton>
|
|
402
|
+
<!-- A pr-reviewer step parked awaiting a finding selection: open the dedicated
|
|
403
|
+
findings-selection window, not the generic approval gate. -->
|
|
404
|
+
<UButton
|
|
405
|
+
v-else-if="
|
|
406
|
+
s.approval &&
|
|
407
|
+
s.approval.status === 'pending' &&
|
|
408
|
+
s.prReview?.status === 'awaiting_selection'
|
|
409
|
+
"
|
|
410
|
+
color="primary"
|
|
411
|
+
variant="soft"
|
|
412
|
+
size="xs"
|
|
413
|
+
icon="i-lucide-clipboard-check"
|
|
414
|
+
data-testid="pr-review-open"
|
|
415
|
+
@click="openPrReviewFor(i)"
|
|
416
|
+
>
|
|
417
|
+
{{ t('inspector.execution.reviewFindings') }}
|
|
418
|
+
</UButton>
|
|
396
419
|
<UButton
|
|
397
420
|
v-else-if="s.approval && s.approval.status === 'pending'"
|
|
398
421
|
color="warning"
|
|
@@ -75,6 +75,15 @@ function forkPhase(step: PipelineStep): 'proposing' | 'awaiting_choice' | null {
|
|
|
75
75
|
return status === 'proposing' || status === 'awaiting_choice' ? status : null
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Whether a `pr-reviewer` step is parked awaiting a human finding-selection — it carries a
|
|
80
|
+
* pending approval too, so we render a purpose-built "Review findings" chip (opening the
|
|
81
|
+
* PR-review window) ahead of the generic approval gate, mirroring the fork-decision chip.
|
|
82
|
+
*/
|
|
83
|
+
function prReviewAwaiting(step: PipelineStep): boolean {
|
|
84
|
+
return step.prReview?.status === 'awaiting_selection'
|
|
85
|
+
}
|
|
86
|
+
|
|
78
87
|
// --- restart from a step -----------------------------------------------------
|
|
79
88
|
// Re-run the pipeline from a chosen step onward: the server resets that step +
|
|
80
89
|
// every later step's iteration counters and re-drives a fresh run, keeping the
|
|
@@ -607,6 +616,26 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
607
616
|
</span>
|
|
608
617
|
</button>
|
|
609
618
|
|
|
619
|
+
<!-- PR deep-review parked for a human to select which findings matter: a
|
|
620
|
+
purpose-built chip opening the findings-selection window, ahead of the
|
|
621
|
+
generic approval gate (mirrors the fork-decision chip above). -->
|
|
622
|
+
<button
|
|
623
|
+
v-if="prReviewAwaiting(s)"
|
|
624
|
+
type="button"
|
|
625
|
+
data-testid="pr-review-open"
|
|
626
|
+
class="mt-3 flex w-full items-center gap-2 rounded-lg border border-dashed border-indigo-500/50 bg-indigo-500/10 px-2.5 py-1.5 text-start transition followup-blink hover:border-indigo-400/60"
|
|
627
|
+
@click="ui.openPrReview(instance.id, i)"
|
|
628
|
+
>
|
|
629
|
+
<span
|
|
630
|
+
class="flex h-6 w-6 shrink-0 items-center justify-center rounded-md border border-indigo-500/40 bg-indigo-500/15"
|
|
631
|
+
>
|
|
632
|
+
<UIcon name="i-lucide-clipboard-check" class="h-3 w-3 text-indigo-300" />
|
|
633
|
+
</span>
|
|
634
|
+
<span class="min-w-0 flex-1 truncate text-[12px] text-slate-300">
|
|
635
|
+
{{ t('pipeline.progress.prReview.review') }}
|
|
636
|
+
</span>
|
|
637
|
+
</button>
|
|
638
|
+
|
|
610
639
|
<!-- reviewer gate folding/re-reviewing in the background: a working indicator,
|
|
611
640
|
NOT a "Review & approve" gate (the human is summoned only if needed) -->
|
|
612
641
|
<div
|
|
@@ -618,7 +647,10 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
618
647
|
</div>
|
|
619
648
|
|
|
620
649
|
<!-- approval gate: review (and edit) the proposal before continuing -->
|
|
621
|
-
<div
|
|
650
|
+
<div
|
|
651
|
+
v-else-if="s.approval && s.approval.status === 'pending' && !prReviewAwaiting(s)"
|
|
652
|
+
class="mt-3"
|
|
653
|
+
>
|
|
622
654
|
<UButton
|
|
623
655
|
color="warning"
|
|
624
656
|
variant="soft"
|
|
@@ -17,7 +17,9 @@ import type {
|
|
|
17
17
|
PrReviewResolution,
|
|
18
18
|
PrReviewSeverity,
|
|
19
19
|
PrReviewStepState,
|
|
20
|
+
StepSubtasks,
|
|
20
21
|
} from '~/types/execution'
|
|
22
|
+
import { subtaskIconClass } from '~/utils/pipelineRender'
|
|
21
23
|
import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
|
|
22
24
|
|
|
23
25
|
const execution = useExecutionStore()
|
|
@@ -44,6 +46,18 @@ const step = computed(() => {
|
|
|
44
46
|
const state = computed<PrReviewStepState | null>(() => step.value?.prReview ?? null)
|
|
45
47
|
const status = computed(() => state.value?.status ?? null)
|
|
46
48
|
const awaiting = computed(() => status.value === 'awaiting_selection')
|
|
49
|
+
// The reviewer's live todo list while it works, streamed onto the step. Its entries are the
|
|
50
|
+
// cohesive slices/chunks the agent grouped the diff into (plus a final "aggregate" step), so it
|
|
51
|
+
// surfaces slices-reviewed-so-far progress during the `reviewing` phase — richer than a spinner.
|
|
52
|
+
const subtasks = computed<StepSubtasks | null>(() => step.value?.subtasks ?? null)
|
|
53
|
+
const hasProgress = computed(() => (subtasks.value?.total ?? 0) > 0)
|
|
54
|
+
|
|
55
|
+
/** Icon per todo-item status (matches the pipeline timeline's live subtask breakdown). */
|
|
56
|
+
const ITEM_ICON: Record<string, string> = {
|
|
57
|
+
completed: 'i-lucide-check-circle-2',
|
|
58
|
+
in_progress: 'i-lucide-loader-circle',
|
|
59
|
+
pending: 'i-lucide-circle',
|
|
60
|
+
}
|
|
47
61
|
// A resolution is executing (the Fixer is committing, or comments are being posted) — show a
|
|
48
62
|
// working state between the human's choice and the run advancing/the stream echoing `done`.
|
|
49
63
|
const working = computed(() => status.value === 'fixing' || status.value === 'posting')
|
|
@@ -145,14 +159,82 @@ async function onResolve(action: PrReviewResolution): Promise<void> {
|
|
|
145
159
|
</template>
|
|
146
160
|
|
|
147
161
|
<div class="min-h-0 flex-1 overflow-y-auto px-5 py-4">
|
|
148
|
-
<!-- Reviewing: the read-only reviewer is still working.
|
|
162
|
+
<!-- Reviewing: the read-only reviewer is still working. Once it starts maintaining its
|
|
163
|
+
per-slice todo list, surface the live chunk progress (slices reviewed / total + the
|
|
164
|
+
breakdown) instead of a bare spinner. -->
|
|
149
165
|
<div
|
|
150
166
|
v-if="status === 'reviewing'"
|
|
151
|
-
|
|
167
|
+
data-testid="pr-review-reviewing"
|
|
168
|
+
class="flex h-full flex-col"
|
|
152
169
|
>
|
|
153
|
-
|
|
154
|
-
<
|
|
155
|
-
|
|
170
|
+
<!-- Live chunk progress once the reviewer has planned its slices. -->
|
|
171
|
+
<div v-if="hasProgress" class="py-2">
|
|
172
|
+
<div class="mb-1 flex items-center gap-2 text-sm text-slate-200">
|
|
173
|
+
<UIcon
|
|
174
|
+
name="i-lucide-loader-circle"
|
|
175
|
+
class="h-4 w-4 shrink-0 animate-spin text-indigo-300"
|
|
176
|
+
/>
|
|
177
|
+
<span>{{ t('prReview.reviewing.title') }}</span>
|
|
178
|
+
</div>
|
|
179
|
+
<p class="mb-3 text-[11px] text-slate-500">{{ t('prReview.reviewing.hint') }}</p>
|
|
180
|
+
|
|
181
|
+
<div class="flex items-center justify-between text-[11px] text-slate-400">
|
|
182
|
+
<span data-testid="pr-review-chunk-count">
|
|
183
|
+
{{
|
|
184
|
+
t('prReview.reviewing.chunks', {
|
|
185
|
+
completed: subtasks!.completed,
|
|
186
|
+
total: subtasks!.total,
|
|
187
|
+
})
|
|
188
|
+
}}
|
|
189
|
+
</span>
|
|
190
|
+
<span v-if="subtasks!.inProgress > 0" class="text-indigo-300">
|
|
191
|
+
{{ t('prReview.reviewing.inProgress', { count: subtasks!.inProgress }) }}
|
|
192
|
+
</span>
|
|
193
|
+
</div>
|
|
194
|
+
<div class="mt-1 h-1.5 overflow-hidden rounded-full bg-slate-700/60">
|
|
195
|
+
<div
|
|
196
|
+
class="h-full rounded-full bg-indigo-400 transition-all duration-500"
|
|
197
|
+
:style="{ width: `${(subtasks!.completed / subtasks!.total) * 100}%` }"
|
|
198
|
+
/>
|
|
199
|
+
</div>
|
|
200
|
+
|
|
201
|
+
<!-- The slice/todo breakdown the agent is working through. -->
|
|
202
|
+
<ul
|
|
203
|
+
v-if="subtasks!.items?.length"
|
|
204
|
+
class="mt-3 space-y-1.5"
|
|
205
|
+
data-testid="pr-review-chunks"
|
|
206
|
+
>
|
|
207
|
+
<li
|
|
208
|
+
v-for="(item, i) in subtasks!.items"
|
|
209
|
+
:key="i"
|
|
210
|
+
class="flex items-start gap-1.5 text-[12px]"
|
|
211
|
+
:class="
|
|
212
|
+
item.status === 'completed'
|
|
213
|
+
? 'text-slate-500 line-through'
|
|
214
|
+
: item.status === 'in_progress'
|
|
215
|
+
? 'text-slate-100'
|
|
216
|
+
: 'text-slate-400'
|
|
217
|
+
"
|
|
218
|
+
>
|
|
219
|
+
<UIcon
|
|
220
|
+
:name="ITEM_ICON[item.status]"
|
|
221
|
+
class="mt-0.5 h-3.5 w-3.5 shrink-0"
|
|
222
|
+
:class="subtaskIconClass(item.status, false)"
|
|
223
|
+
/>
|
|
224
|
+
<span>{{ item.label }}</span>
|
|
225
|
+
</li>
|
|
226
|
+
</ul>
|
|
227
|
+
</div>
|
|
228
|
+
|
|
229
|
+
<!-- Before the reviewer has planned its slices: the cold-start spinner. -->
|
|
230
|
+
<div
|
|
231
|
+
v-else
|
|
232
|
+
class="flex h-full flex-col items-center justify-center gap-2 py-10 text-center text-slate-400"
|
|
233
|
+
>
|
|
234
|
+
<UIcon name="i-lucide-loader-circle" class="h-8 w-8 animate-spin opacity-60" />
|
|
235
|
+
<p class="text-sm">{{ t('prReview.reviewing.title') }}</p>
|
|
236
|
+
<p class="max-w-sm text-[11px] text-slate-500">{{ t('prReview.reviewing.hint') }}</p>
|
|
237
|
+
</div>
|
|
156
238
|
</div>
|
|
157
239
|
|
|
158
240
|
<!-- A resolution is executing: the Fixer is committing / comments are being posted. -->
|
|
@@ -70,11 +70,16 @@ export function createUiResultViews() {
|
|
|
70
70
|
// A step that actually ran the consensus mechanism opens the dedicated Consensus
|
|
71
71
|
// Session window, regardless of its kind's normal result view — consensus is an
|
|
72
72
|
// execution MODE on a kind, not a kind, so it can't be a static archetype `resultView`.
|
|
73
|
+
// A step carrying a PR deep-review parks with BOTH a pending approval and
|
|
74
|
+
// `prReview.status`, so the generic approval button funnels here; route it to the
|
|
75
|
+
// findings-selection window regardless of catalog/manifest state (mirrors consensus).
|
|
73
76
|
const view = step?.consensus?.enabled
|
|
74
77
|
? 'consensus-session'
|
|
75
|
-
: step
|
|
76
|
-
?
|
|
77
|
-
:
|
|
78
|
+
: step?.prReview
|
|
79
|
+
? 'pr-review'
|
|
80
|
+
: step
|
|
81
|
+
? agentKindMeta(step.agentKind).resultView
|
|
82
|
+
: undefined
|
|
78
83
|
if (view && instance) {
|
|
79
84
|
// The brainstorm window is shared by both stages; carry which one from the step's kind.
|
|
80
85
|
const stage =
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it } from 'vitest'
|
|
2
|
+
import { useExecutionStore } from '~/stores/execution'
|
|
3
|
+
import { useUiStore } from '~/stores/ui'
|
|
4
|
+
import type { ExecutionInstance } from '~/types/domain'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Pins the `dispatchStepView` routing seam (the single dispatch every board/inspector/rail
|
|
8
|
+
* entry point uses). Its subtle case is the parked `pr-reviewer` step: it carries BOTH a
|
|
9
|
+
* pending approval and `prReview.status`, so a naive route sends the generic approval button
|
|
10
|
+
* into the prose panel (the #1261 bug). These assertions lock in that a step carrying
|
|
11
|
+
* `prReview` opens the dedicated findings window regardless of catalog/manifest state, and
|
|
12
|
+
* that the consensus MODE still wins over it.
|
|
13
|
+
*/
|
|
14
|
+
function instance(id: string, blockId: string, steps: unknown[]): ExecutionInstance {
|
|
15
|
+
return { id, blockId, steps } as unknown as ExecutionInstance
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe('dispatchStepView routing', () => {
|
|
19
|
+
let ui: ReturnType<typeof useUiStore>
|
|
20
|
+
let execution: ReturnType<typeof useExecutionStore>
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
ui = useUiStore()
|
|
23
|
+
execution = useExecutionStore()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('routes a step carrying prReview to the dedicated pr-review window', () => {
|
|
27
|
+
execution.hydrate(
|
|
28
|
+
[
|
|
29
|
+
instance('e1', 'b1', [
|
|
30
|
+
{
|
|
31
|
+
agentKind: 'pr-reviewer',
|
|
32
|
+
approval: { id: 'a1', status: 'pending' },
|
|
33
|
+
prReview: { status: 'awaiting_selection' },
|
|
34
|
+
},
|
|
35
|
+
]),
|
|
36
|
+
],
|
|
37
|
+
'ws1',
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
ui.openStepDetail('e1', 0)
|
|
41
|
+
|
|
42
|
+
expect(ui.resultView).toEqual({
|
|
43
|
+
view: 'pr-review',
|
|
44
|
+
blockId: 'b1',
|
|
45
|
+
instanceId: 'e1',
|
|
46
|
+
stepIndex: 0,
|
|
47
|
+
})
|
|
48
|
+
// The generic prose panel is NOT opened — routing bypassed it.
|
|
49
|
+
expect(ui.stepDetail).toBeNull()
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('opening the pending approval on a pr-reviewer step still lands on pr-review', () => {
|
|
53
|
+
execution.hydrate(
|
|
54
|
+
[
|
|
55
|
+
instance('e1', 'b1', [
|
|
56
|
+
{
|
|
57
|
+
agentKind: 'pr-reviewer',
|
|
58
|
+
approval: { id: 'a1', status: 'pending' },
|
|
59
|
+
prReview: { status: 'awaiting_selection' },
|
|
60
|
+
},
|
|
61
|
+
]),
|
|
62
|
+
],
|
|
63
|
+
'ws1',
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
// Every surface's generic approval button funnels through openApprovalDetail → dispatch.
|
|
67
|
+
ui.openApprovalDetail('e1', 'a1')
|
|
68
|
+
|
|
69
|
+
expect(ui.resultView?.view).toBe('pr-review')
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('a consensus run wins over prReview (mode precedence)', () => {
|
|
73
|
+
execution.hydrate(
|
|
74
|
+
[
|
|
75
|
+
instance('e1', 'b1', [
|
|
76
|
+
{
|
|
77
|
+
agentKind: 'pr-reviewer',
|
|
78
|
+
consensus: { enabled: true },
|
|
79
|
+
prReview: { status: 'awaiting_selection' },
|
|
80
|
+
},
|
|
81
|
+
]),
|
|
82
|
+
],
|
|
83
|
+
'ws1',
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
ui.openStepDetail('e1', 0)
|
|
87
|
+
|
|
88
|
+
expect(ui.resultView?.view).toBe('consensus-session')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('a plain step with no bespoke view falls back to the generic step-detail panel', () => {
|
|
92
|
+
execution.hydrate([instance('e1', 'b1', [{ agentKind: 'coder' }])], 'ws1')
|
|
93
|
+
|
|
94
|
+
ui.openStepDetail('e1', 0)
|
|
95
|
+
|
|
96
|
+
expect(ui.resultView).toBeNull()
|
|
97
|
+
expect(ui.stepDetail).toEqual({ instanceId: 'e1', stepIndex: 0 })
|
|
98
|
+
})
|
|
99
|
+
})
|
package/app/utils/catalog.ts
CHANGED
|
@@ -65,6 +65,24 @@ export const AGENT_ARCHETYPES: AgentArchetype[] = [
|
|
|
65
65
|
'Read-only, multi-repo codebase investigation that traces the bug to its root cause and decides whether the report is fixable as-is or needs the reporter to clarify (no code changes).',
|
|
66
66
|
resultView: 'generic-structured',
|
|
67
67
|
},
|
|
68
|
+
{
|
|
69
|
+
// A read-only, token-bounded deep review of an EXISTING open pull request (the `pl_review`
|
|
70
|
+
// pipeline's single step). Registered on the backend so it also arrives via the workspace
|
|
71
|
+
// manifest, but modelled statically here so `agentKindMeta('pr-reviewer').resultView`
|
|
72
|
+
// resolves to the findings-selection window on every surface — not just when the manifest
|
|
73
|
+
// is hydrated. Mirrors the backend `presentation` in `pr-reviewer.ts`.
|
|
74
|
+
kind: 'pr-reviewer',
|
|
75
|
+
label: 'PR Reviewer',
|
|
76
|
+
icon: 'i-lucide-clipboard-check',
|
|
77
|
+
color: '#6366f1',
|
|
78
|
+
category: 'review',
|
|
79
|
+
description:
|
|
80
|
+
'Deep, token-bounded review of an open pull request: slices a large diff into cohesive ' +
|
|
81
|
+
'chunks, reviews each, and returns prioritized findings.',
|
|
82
|
+
// Opens the dedicated PR-review window (findings grouped by slice + multi-select →
|
|
83
|
+
// resolve) instead of the generic read-only JSON viewer. See PrReviewWindow.vue.
|
|
84
|
+
resultView: 'pr-review',
|
|
85
|
+
},
|
|
68
86
|
{
|
|
69
87
|
// A timeboxed read-only research/investigation agent. Its structured findings open in the
|
|
70
88
|
// shared generic viewer; the findings document is committed by a backend post-op (delivered
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { freshPromptTokens } from './observability'
|
|
3
|
+
|
|
4
|
+
describe('freshPromptTokens', () => {
|
|
5
|
+
it('subtracts the cached prefix from the prompt-token sum', () => {
|
|
6
|
+
expect(freshPromptTokens(1000, 300)).toBe(700)
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
it('reduces a near-fully-cached agentic run to its tiny fresh input (inclusive shape)', () => {
|
|
10
|
+
// The 31M-cache-read shape from the investigation on the INCLUSIVE shape (subscription
|
|
11
|
+
// harness / OpenAI-style): prompt tokens INCLUDE the cache reads, so subtracting the cached
|
|
12
|
+
// subset leaves the few-hundred-token fresh figure, not tens of millions.
|
|
13
|
+
expect(freshPromptTokens(31_100_498, 31_099_813)).toBe(685)
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('treats promptTokens as already-fresh when cached exceeds it (Anthropic separate shape)', () => {
|
|
17
|
+
// Anthropic via the LLM proxy reports cache reads SEPARATELY, so promptTokens is fresh-only
|
|
18
|
+
// and cachedPromptTokens can far exceed it. The fresh figure is promptTokens itself — NOT 0
|
|
19
|
+
// (the old subtract-and-clamp collapsed real fresh input to zero on this shape).
|
|
20
|
+
expect(freshPromptTokens(685, 31_099_813)).toBe(685)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('never returns negative, and treats a fully-cached inclusive rollup as 0 fresh', () => {
|
|
24
|
+
expect(freshPromptTokens(500, 500)).toBe(0)
|
|
25
|
+
// cached > prompt ⇒ separate shape ⇒ fresh = prompt (never a negative number).
|
|
26
|
+
expect(freshPromptTokens(500, 600)).toBe(500)
|
|
27
|
+
})
|
|
28
|
+
})
|
|
@@ -11,6 +11,34 @@ export function formatTokens(n: number): string {
|
|
|
11
11
|
return `${(n / 1_000_000).toFixed(1)}M`
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* FRESH (uncached) prompt tokens: the input tokens actually processed this call/rollup after
|
|
16
|
+
* excluding the prefix served from the provider's cache. A long agentic run re-sends its whole
|
|
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.
|
|
20
|
+
*
|
|
21
|
+
* `cachedPromptTokens` has PROVIDER-DEPENDENT semantics (see the field docs on `stepMetricsSchema`
|
|
22
|
+
* / `llmCallMetricSchema`), so we can't blindly subtract:
|
|
23
|
+
* - Inclusive shape (OpenAI/DeepSeek, and the subscription-CLI harness, which folds cache into
|
|
24
|
+
* `promptTokens`): cached is a SUBSET of prompt ⇒ fresh = prompt − cached.
|
|
25
|
+
* - Separate shape (Anthropic via the LLM proxy): cache reads are reported SEPARATELY and
|
|
26
|
+
* `promptTokens` is ALREADY fresh-only, so cached can EXCEED prompt. Subtracting there would
|
|
27
|
+
* wrongly collapse a real fresh input to 0 — when cached ≥ prompt, `promptTokens` itself IS
|
|
28
|
+
* the fresh figure.
|
|
29
|
+
*
|
|
30
|
+
* NOTE: with only these two aggregates we cannot distinguish the separate shape while cached is
|
|
31
|
+
* still ≤ prompt (there the subtraction under-counts fresh by the cache-read amount). A fully
|
|
32
|
+
* exact split needs the wire contract to carry cache-read vs cache-write distinctly at the
|
|
33
|
+
* source; this heuristic fixes the dominant (cached ≫ prompt) case and never returns negative.
|
|
34
|
+
*/
|
|
35
|
+
export function freshPromptTokens(promptTokens: number, cachedPromptTokens: number): number {
|
|
36
|
+
// Separate shape: promptTokens is already fresh-only (cache reads counted separately).
|
|
37
|
+
if (cachedPromptTokens > promptTokens) return promptTokens
|
|
38
|
+
// Inclusive shape: cached is a subset of prompt.
|
|
39
|
+
return promptTokens - cachedPromptTokens
|
|
40
|
+
}
|
|
41
|
+
|
|
14
42
|
/** Compact duration: 850 → "850ms", 1500 → "1.5s", 90_000 → "1m 30s". */
|
|
15
43
|
export function formatMs(ms: number): string {
|
|
16
44
|
if (ms < 1000) return `${Math.round(ms)}ms`
|
package/i18n/locales/de.json
CHANGED
|
@@ -1235,7 +1235,8 @@
|
|
|
1235
1235
|
"open": "Öffnen",
|
|
1236
1236
|
"mergePr": "PR mergen",
|
|
1237
1237
|
"chooseApproach": "Ansatz wählen",
|
|
1238
|
-
"elapsedTooltip": "Verstrichene Zeit für diesen Schritt"
|
|
1238
|
+
"elapsedTooltip": "Verstrichene Zeit für diesen Schritt",
|
|
1239
|
+
"reviewFindings": "Befunde prüfen"
|
|
1239
1240
|
},
|
|
1240
1241
|
"structure": {
|
|
1241
1242
|
"title": "Struktur",
|
|
@@ -2748,11 +2749,12 @@
|
|
|
2748
2749
|
"tokensInOut": "Tokens (ein / aus)",
|
|
2749
2750
|
"transportOverhead": "Transport-Overhead",
|
|
2750
2751
|
"modelExecution": "Modellausführung",
|
|
2751
|
-
"truncated": "{count} abgeschnitten | {count} abgeschnitten"
|
|
2752
|
+
"truncated": "{count} abgeschnitten | {count} abgeschnitten",
|
|
2753
|
+
"cached": "{tokens} gecacht"
|
|
2752
2754
|
},
|
|
2753
2755
|
"metricsBar": {
|
|
2754
2756
|
"calls": "{count} Aufruf | {count} Aufrufe",
|
|
2755
|
-
"promptCompletionTokens": "Prompt-/Completion-Tokens",
|
|
2757
|
+
"promptCompletionTokens": "Frische (nicht gecachte) Prompt-/Completion-Tokens",
|
|
2756
2758
|
"cachedTokens": "({tokens} zwischengespeichert)",
|
|
2757
2759
|
"cachedTokensHint": "Prompt-Tokens, die aus dem Cache des Providers bedient wurden",
|
|
2758
2760
|
"errors": "{count} Fehler | {count} Fehler",
|
|
@@ -3256,7 +3258,10 @@
|
|
|
3256
3258
|
"proposing": "Ansätze werden vorgeschlagen…",
|
|
3257
3259
|
"choose": "Ansatz wählen"
|
|
3258
3260
|
},
|
|
3259
|
-
"elapsedTooltip": "Verstrichene Zeit für diesen Schritt"
|
|
3261
|
+
"elapsedTooltip": "Verstrichene Zeit für diesen Schritt",
|
|
3262
|
+
"prReview": {
|
|
3263
|
+
"review": "Befunde prüfen"
|
|
3264
|
+
}
|
|
3260
3265
|
},
|
|
3261
3266
|
"health": {
|
|
3262
3267
|
"title": "Pipeline-Zustand",
|
|
@@ -4936,7 +4941,9 @@
|
|
|
4936
4941
|
"line": "Zeile {line}",
|
|
4937
4942
|
"reviewing": {
|
|
4938
4943
|
"title": "Pull Request wird geprüft…",
|
|
4939
|
-
"hint": "Der Diff wird in zusammenhängende Teile zerlegt und einzeln geprüft."
|
|
4944
|
+
"hint": "Der Diff wird in zusammenhängende Teile zerlegt und einzeln geprüft.",
|
|
4945
|
+
"chunks": "{completed} von {total} Abschnitten geprüft",
|
|
4946
|
+
"inProgress": "{count} in Bearbeitung"
|
|
4940
4947
|
},
|
|
4941
4948
|
"fixing": {
|
|
4942
4949
|
"title": "Ausgewählte Befunde werden behoben…",
|
package/i18n/locales/en.json
CHANGED
|
@@ -1010,7 +1010,8 @@
|
|
|
1010
1010
|
"open": "Open",
|
|
1011
1011
|
"mergePr": "Merge PR",
|
|
1012
1012
|
"chooseApproach": "Choose approach",
|
|
1013
|
-
"elapsedTooltip": "Elapsed time on this step"
|
|
1013
|
+
"elapsedTooltip": "Elapsed time on this step",
|
|
1014
|
+
"reviewFindings": "Review findings"
|
|
1014
1015
|
},
|
|
1015
1016
|
"structure": {
|
|
1016
1017
|
"title": "Structure",
|
|
@@ -1326,11 +1327,12 @@
|
|
|
1326
1327
|
"tokensInOut": "Tokens (in / out)",
|
|
1327
1328
|
"transportOverhead": "Transport overhead",
|
|
1328
1329
|
"modelExecution": "Model execution",
|
|
1329
|
-
"truncated": "{count} truncated | {count} truncated"
|
|
1330
|
+
"truncated": "{count} truncated | {count} truncated",
|
|
1331
|
+
"cached": "{tokens} cached"
|
|
1330
1332
|
},
|
|
1331
1333
|
"metricsBar": {
|
|
1332
1334
|
"calls": "{count} call | {count} calls",
|
|
1333
|
-
"promptCompletionTokens": "
|
|
1335
|
+
"promptCompletionTokens": "Fresh (uncached) prompt / completion tokens",
|
|
1334
1336
|
"cachedTokens": "({tokens} cached)",
|
|
1335
1337
|
"cachedTokensHint": "Prompt tokens served from the provider's cache",
|
|
1336
1338
|
"errors": "{count} error | {count} errors",
|
|
@@ -3622,7 +3624,10 @@
|
|
|
3622
3624
|
"proposing": "Proposing approaches…",
|
|
3623
3625
|
"choose": "Choose an approach"
|
|
3624
3626
|
},
|
|
3625
|
-
"elapsedTooltip": "Elapsed time on this step"
|
|
3627
|
+
"elapsedTooltip": "Elapsed time on this step",
|
|
3628
|
+
"prReview": {
|
|
3629
|
+
"review": "Review findings"
|
|
3630
|
+
}
|
|
3626
3631
|
},
|
|
3627
3632
|
"health": {
|
|
3628
3633
|
"title": "Pipeline health",
|
|
@@ -5065,7 +5070,9 @@
|
|
|
5065
5070
|
"line": "line {line}",
|
|
5066
5071
|
"reviewing": {
|
|
5067
5072
|
"title": "Reviewing the pull request…",
|
|
5068
|
-
"hint": "Slicing the diff into cohesive chunks and reviewing each one."
|
|
5073
|
+
"hint": "Slicing the diff into cohesive chunks and reviewing each one.",
|
|
5074
|
+
"chunks": "{completed} of {total} chunks reviewed",
|
|
5075
|
+
"inProgress": "{count} in progress"
|
|
5069
5076
|
},
|
|
5070
5077
|
"fixing": {
|
|
5071
5078
|
"title": "Fixing the selected findings…",
|
package/i18n/locales/es.json
CHANGED
|
@@ -953,7 +953,8 @@
|
|
|
953
953
|
"body": "Inicia un pipeline para ver el historial de ejecución aquí."
|
|
954
954
|
},
|
|
955
955
|
"chooseApproach": "Elegir enfoque",
|
|
956
|
-
"elapsedTooltip": "Tiempo transcurrido en este paso"
|
|
956
|
+
"elapsedTooltip": "Tiempo transcurrido en este paso",
|
|
957
|
+
"reviewFindings": "Revisar hallazgos"
|
|
957
958
|
},
|
|
958
959
|
"structure": {
|
|
959
960
|
"title": "Estructura",
|
|
@@ -1266,11 +1267,12 @@
|
|
|
1266
1267
|
"tokensInOut": "Tokens (entrada / salida)",
|
|
1267
1268
|
"transportOverhead": "Sobrecarga de transporte",
|
|
1268
1269
|
"modelExecution": "Ejecución del modelo",
|
|
1269
|
-
"truncated": "{count} truncada | {count} truncadas"
|
|
1270
|
+
"truncated": "{count} truncada | {count} truncadas",
|
|
1271
|
+
"cached": "{tokens} en caché"
|
|
1270
1272
|
},
|
|
1271
1273
|
"metricsBar": {
|
|
1272
1274
|
"calls": "{count} llamada | {count} llamadas",
|
|
1273
|
-
"promptCompletionTokens": "Tokens de prompt / completado",
|
|
1275
|
+
"promptCompletionTokens": "Tokens frescos (sin caché) de prompt / completado",
|
|
1274
1276
|
"cachedTokens": "({tokens} en caché)",
|
|
1275
1277
|
"cachedTokensHint": "Tokens de prompt servidos desde la caché del proveedor",
|
|
1276
1278
|
"errors": "{count} error | {count} errores",
|
|
@@ -3523,7 +3525,10 @@
|
|
|
3523
3525
|
"proposing": "Proponiendo enfoques…",
|
|
3524
3526
|
"choose": "Elegir un enfoque"
|
|
3525
3527
|
},
|
|
3526
|
-
"elapsedTooltip": "Tiempo transcurrido en este paso"
|
|
3528
|
+
"elapsedTooltip": "Tiempo transcurrido en este paso",
|
|
3529
|
+
"prReview": {
|
|
3530
|
+
"review": "Revisar hallazgos"
|
|
3531
|
+
}
|
|
3527
3532
|
},
|
|
3528
3533
|
"health": {
|
|
3529
3534
|
"title": "Estado de los pipelines",
|
|
@@ -4924,7 +4929,9 @@
|
|
|
4924
4929
|
"line": "línea {line}",
|
|
4925
4930
|
"reviewing": {
|
|
4926
4931
|
"title": "Revisando el pull request…",
|
|
4927
|
-
"hint": "Dividiendo el diff en bloques coherentes y revisando cada uno."
|
|
4932
|
+
"hint": "Dividiendo el diff en bloques coherentes y revisando cada uno.",
|
|
4933
|
+
"chunks": "{completed} de {total} fragmentos revisados",
|
|
4934
|
+
"inProgress": "{count} en curso"
|
|
4928
4935
|
},
|
|
4929
4936
|
"fixing": {
|
|
4930
4937
|
"title": "Corrigiendo los hallazgos seleccionados…",
|
package/i18n/locales/fr.json
CHANGED
|
@@ -953,7 +953,8 @@
|
|
|
953
953
|
"body": "Lancez un pipeline pour voir l'historique d'exécution ici."
|
|
954
954
|
},
|
|
955
955
|
"chooseApproach": "Choisir l'approche",
|
|
956
|
-
"elapsedTooltip": "Temps écoulé sur cette étape"
|
|
956
|
+
"elapsedTooltip": "Temps écoulé sur cette étape",
|
|
957
|
+
"reviewFindings": "Examiner les remarques"
|
|
957
958
|
},
|
|
958
959
|
"structure": {
|
|
959
960
|
"title": "Structure",
|
|
@@ -1266,11 +1267,12 @@
|
|
|
1266
1267
|
"tokensInOut": "Tokens (entrée / sortie)",
|
|
1267
1268
|
"transportOverhead": "Surcoût de transport",
|
|
1268
1269
|
"modelExecution": "Exécution du modèle",
|
|
1269
|
-
"truncated": "{count} tronqué | {count} tronqués"
|
|
1270
|
+
"truncated": "{count} tronqué | {count} tronqués",
|
|
1271
|
+
"cached": "{tokens} en cache"
|
|
1270
1272
|
},
|
|
1271
1273
|
"metricsBar": {
|
|
1272
1274
|
"calls": "{count} appel | {count} appels",
|
|
1273
|
-
"promptCompletionTokens": "Tokens de prompt / complétion",
|
|
1275
|
+
"promptCompletionTokens": "Tokens frais (non mis en cache) de prompt / complétion",
|
|
1274
1276
|
"cachedTokens": "({tokens} en cache)",
|
|
1275
1277
|
"cachedTokensHint": "Tokens de prompt servis depuis le cache du fournisseur",
|
|
1276
1278
|
"errors": "{count} erreur | {count} erreurs",
|
|
@@ -3523,7 +3525,10 @@
|
|
|
3523
3525
|
"proposing": "Proposition d'approches…",
|
|
3524
3526
|
"choose": "Choisir une approche"
|
|
3525
3527
|
},
|
|
3526
|
-
"elapsedTooltip": "Temps écoulé sur cette étape"
|
|
3528
|
+
"elapsedTooltip": "Temps écoulé sur cette étape",
|
|
3529
|
+
"prReview": {
|
|
3530
|
+
"review": "Examiner les remarques"
|
|
3531
|
+
}
|
|
3527
3532
|
},
|
|
3528
3533
|
"health": {
|
|
3529
3534
|
"title": "État des pipelines",
|
|
@@ -4924,7 +4929,9 @@
|
|
|
4924
4929
|
"line": "ligne {line}",
|
|
4925
4930
|
"reviewing": {
|
|
4926
4931
|
"title": "Revue de la pull request…",
|
|
4927
|
-
"hint": "Découpage du diff en blocs cohérents et revue de chacun."
|
|
4932
|
+
"hint": "Découpage du diff en blocs cohérents et revue de chacun.",
|
|
4933
|
+
"chunks": "{completed} sur {total} sections examinées",
|
|
4934
|
+
"inProgress": "{count} en cours"
|
|
4928
4935
|
},
|
|
4929
4936
|
"fixing": {
|
|
4930
4937
|
"title": "Correction des points sélectionnés…",
|
package/i18n/locales/he.json
CHANGED
|
@@ -953,7 +953,8 @@
|
|
|
953
953
|
"body": "התחל pipeline כדי לראות כאן את היסטוריית ההרצות."
|
|
954
954
|
},
|
|
955
955
|
"chooseApproach": "בחר גישה",
|
|
956
|
-
"elapsedTooltip": "הזמן שחלף בשלב זה"
|
|
956
|
+
"elapsedTooltip": "הזמן שחלף בשלב זה",
|
|
957
|
+
"reviewFindings": "עיין בממצאים"
|
|
957
958
|
},
|
|
958
959
|
"structure": {
|
|
959
960
|
"title": "מבנה",
|
|
@@ -1266,11 +1267,12 @@
|
|
|
1266
1267
|
"tokensInOut": "טוקנים (נכנס / יוצא)",
|
|
1267
1268
|
"transportOverhead": "תקורת תעבורה",
|
|
1268
1269
|
"modelExecution": "הרצת מודל",
|
|
1269
|
-
"truncated": "{count} נקטע | {count} נקטעו"
|
|
1270
|
+
"truncated": "{count} נקטע | {count} נקטעו",
|
|
1271
|
+
"cached": "{tokens} במטמון"
|
|
1270
1272
|
},
|
|
1271
1273
|
"metricsBar": {
|
|
1272
1274
|
"calls": "{count} קריאה | {count} קריאות",
|
|
1273
|
-
"promptCompletionTokens": "טוקני פרומפט / השלמה",
|
|
1275
|
+
"promptCompletionTokens": "טוקני פרומפט / השלמה חדשים (ללא מטמון)",
|
|
1274
1276
|
"cachedTokens": "({tokens} במטמון)",
|
|
1275
1277
|
"cachedTokensHint": "טוקני פרומפט שהוגשו ממטמון הספק",
|
|
1276
1278
|
"errors": "{count} שגיאה | {count} שגיאות",
|
|
@@ -3534,7 +3536,10 @@
|
|
|
3534
3536
|
"proposing": "מציע גישות…",
|
|
3535
3537
|
"choose": "בחר גישה"
|
|
3536
3538
|
},
|
|
3537
|
-
"elapsedTooltip": "הזמן שחלף בשלב זה"
|
|
3539
|
+
"elapsedTooltip": "הזמן שחלף בשלב זה",
|
|
3540
|
+
"prReview": {
|
|
3541
|
+
"review": "עיין בממצאים"
|
|
3542
|
+
}
|
|
3538
3543
|
},
|
|
3539
3544
|
"health": {
|
|
3540
3545
|
"title": "בריאות הצינור",
|
|
@@ -4935,7 +4940,9 @@
|
|
|
4935
4940
|
"line": "שורה {line}",
|
|
4936
4941
|
"reviewing": {
|
|
4937
4942
|
"title": "בודק את בקשת המשיכה…",
|
|
4938
|
-
"hint": "מחלק את ההבדלים לקטעים לכידים ובודק כל אחד."
|
|
4943
|
+
"hint": "מחלק את ההבדלים לקטעים לכידים ובודק כל אחד.",
|
|
4944
|
+
"chunks": "{completed} מתוך {total} מקטעים נבדקו",
|
|
4945
|
+
"inProgress": "{count} בתהליך"
|
|
4939
4946
|
},
|
|
4940
4947
|
"fixing": {
|
|
4941
4948
|
"title": "מתקן את הממצאים שנבחרו…",
|
package/i18n/locales/it.json
CHANGED
|
@@ -1235,7 +1235,8 @@
|
|
|
1235
1235
|
"open": "Aperta",
|
|
1236
1236
|
"mergePr": "Unisci PR",
|
|
1237
1237
|
"chooseApproach": "Scegli approccio",
|
|
1238
|
-
"elapsedTooltip": "Tempo trascorso su questo passaggio"
|
|
1238
|
+
"elapsedTooltip": "Tempo trascorso su questo passaggio",
|
|
1239
|
+
"reviewFindings": "Esamina i rilievi"
|
|
1239
1240
|
},
|
|
1240
1241
|
"structure": {
|
|
1241
1242
|
"title": "Struttura",
|
|
@@ -2748,11 +2749,12 @@
|
|
|
2748
2749
|
"tokensInOut": "Token (in / out)",
|
|
2749
2750
|
"transportOverhead": "Overhead di trasporto",
|
|
2750
2751
|
"modelExecution": "Esecuzione del modello",
|
|
2751
|
-
"truncated": "{count} troncata | {count} troncate"
|
|
2752
|
+
"truncated": "{count} troncata | {count} troncate",
|
|
2753
|
+
"cached": "{tokens} in cache"
|
|
2752
2754
|
},
|
|
2753
2755
|
"metricsBar": {
|
|
2754
2756
|
"calls": "{count} chiamata | {count} chiamate",
|
|
2755
|
-
"promptCompletionTokens": "Token di prompt / completion",
|
|
2757
|
+
"promptCompletionTokens": "Token freschi (non in cache) di prompt / completion",
|
|
2756
2758
|
"cachedTokens": "({tokens} in cache)",
|
|
2757
2759
|
"cachedTokensHint": "Token di prompt serviti dalla cache del provider",
|
|
2758
2760
|
"errors": "{count} errore | {count} errori",
|
|
@@ -3256,7 +3258,10 @@
|
|
|
3256
3258
|
"proposing": "Proposta di approcci…",
|
|
3257
3259
|
"choose": "Scegli un approccio"
|
|
3258
3260
|
},
|
|
3259
|
-
"elapsedTooltip": "Tempo trascorso su questo passaggio"
|
|
3261
|
+
"elapsedTooltip": "Tempo trascorso su questo passaggio",
|
|
3262
|
+
"prReview": {
|
|
3263
|
+
"review": "Esamina i rilievi"
|
|
3264
|
+
}
|
|
3260
3265
|
},
|
|
3261
3266
|
"health": {
|
|
3262
3267
|
"title": "Stato delle pipeline",
|
|
@@ -4936,7 +4941,9 @@
|
|
|
4936
4941
|
"line": "riga {line}",
|
|
4937
4942
|
"reviewing": {
|
|
4938
4943
|
"title": "Revisione della pull request…",
|
|
4939
|
-
"hint": "Suddivisione del diff in blocchi coerenti e revisione di ciascuno."
|
|
4944
|
+
"hint": "Suddivisione del diff in blocchi coerenti e revisione di ciascuno.",
|
|
4945
|
+
"chunks": "{completed} di {total} sezioni esaminate",
|
|
4946
|
+
"inProgress": "{count} in corso"
|
|
4940
4947
|
},
|
|
4941
4948
|
"fixing": {
|
|
4942
4949
|
"title": "Correzione dei rilievi selezionati…",
|
package/i18n/locales/ja.json
CHANGED
|
@@ -953,7 +953,8 @@
|
|
|
953
953
|
"body": "パイプラインを開始すると、ここに実行履歴が表示されます。"
|
|
954
954
|
},
|
|
955
955
|
"chooseApproach": "アプローチを選択",
|
|
956
|
-
"elapsedTooltip": "このステップの経過時間"
|
|
956
|
+
"elapsedTooltip": "このステップの経過時間",
|
|
957
|
+
"reviewFindings": "指摘を確認"
|
|
957
958
|
},
|
|
958
959
|
"structure": {
|
|
959
960
|
"title": "構造",
|
|
@@ -1266,11 +1267,12 @@
|
|
|
1266
1267
|
"tokensInOut": "トークン (入力 / 出力)",
|
|
1267
1268
|
"transportOverhead": "転送オーバーヘッド",
|
|
1268
1269
|
"modelExecution": "モデル実行",
|
|
1269
|
-
"truncated": "{count} 件が切り詰め | {count} 件が切り詰め"
|
|
1270
|
+
"truncated": "{count} 件が切り詰め | {count} 件が切り詰め",
|
|
1271
|
+
"cached": "{tokens} キャッシュ済み"
|
|
1270
1272
|
},
|
|
1271
1273
|
"metricsBar": {
|
|
1272
1274
|
"calls": "{count} 件の呼び出し | {count} 件の呼び出し",
|
|
1273
|
-
"promptCompletionTokens": "
|
|
1275
|
+
"promptCompletionTokens": "新規(キャッシュ外)のプロンプト / 完了トークン",
|
|
1274
1276
|
"cachedTokens": "({tokens} 件キャッシュ済み)",
|
|
1275
1277
|
"cachedTokensHint": "プロバイダーのキャッシュから提供されたプロンプトトークン",
|
|
1276
1278
|
"errors": "{count} 件のエラー | {count} 件のエラー",
|
|
@@ -3535,7 +3537,10 @@
|
|
|
3535
3537
|
"proposing": "アプローチを提案中…",
|
|
3536
3538
|
"choose": "アプローチを選択"
|
|
3537
3539
|
},
|
|
3538
|
-
"elapsedTooltip": "このステップの経過時間"
|
|
3540
|
+
"elapsedTooltip": "このステップの経過時間",
|
|
3541
|
+
"prReview": {
|
|
3542
|
+
"review": "指摘を確認"
|
|
3543
|
+
}
|
|
3539
3544
|
},
|
|
3540
3545
|
"health": {
|
|
3541
3546
|
"title": "パイプラインの状態",
|
|
@@ -4936,7 +4941,9 @@
|
|
|
4936
4941
|
"line": "{line}行目",
|
|
4937
4942
|
"reviewing": {
|
|
4938
4943
|
"title": "プルリクエストをレビュー中…",
|
|
4939
|
-
"hint": "差分をまとまりのある単位に分割し、各単位をレビューしています。"
|
|
4944
|
+
"hint": "差分をまとまりのある単位に分割し、各単位をレビューしています。",
|
|
4945
|
+
"chunks": "{total} 個中 {completed} 個のチャンクをレビュー済み",
|
|
4946
|
+
"inProgress": "{count} 件処理中"
|
|
4940
4947
|
},
|
|
4941
4948
|
"fixing": {
|
|
4942
4949
|
"title": "選択した指摘を修正中…",
|
package/i18n/locales/pl.json
CHANGED
|
@@ -953,7 +953,8 @@
|
|
|
953
953
|
"body": "Uruchom pipeline, aby zobaczyć tutaj historię uruchomień."
|
|
954
954
|
},
|
|
955
955
|
"chooseApproach": "Wybierz podejście",
|
|
956
|
-
"elapsedTooltip": "Czas, który upłynął na tym kroku"
|
|
956
|
+
"elapsedTooltip": "Czas, który upłynął na tym kroku",
|
|
957
|
+
"reviewFindings": "Przejrzyj ustalenia"
|
|
957
958
|
},
|
|
958
959
|
"structure": {
|
|
959
960
|
"title": "Struktura",
|
|
@@ -1266,11 +1267,12 @@
|
|
|
1266
1267
|
"tokensInOut": "Tokeny (we / wy)",
|
|
1267
1268
|
"transportOverhead": "Narzut transportu",
|
|
1268
1269
|
"modelExecution": "Wykonanie modelu",
|
|
1269
|
-
"truncated": "{count} obcięte | {count} obcięte | {count} obciętych"
|
|
1270
|
+
"truncated": "{count} obcięte | {count} obcięte | {count} obciętych",
|
|
1271
|
+
"cached": "{tokens} z pamięci podręcznej"
|
|
1270
1272
|
},
|
|
1271
1273
|
"metricsBar": {
|
|
1272
1274
|
"calls": "{count} wywołanie | {count} wywołania | {count} wywołań",
|
|
1273
|
-
"promptCompletionTokens": "
|
|
1275
|
+
"promptCompletionTokens": "Świeże (niebuforowane) tokeny promptu / dopełnienia",
|
|
1274
1276
|
"cachedTokens": "({tokens} z pamięci podręcznej)",
|
|
1275
1277
|
"cachedTokensHint": "Tokeny promptu obsłużone z pamięci podręcznej dostawcy",
|
|
1276
1278
|
"errors": "{count} błąd | {count} błędy | {count} błędów",
|
|
@@ -3523,7 +3525,10 @@
|
|
|
3523
3525
|
"proposing": "Proponowanie podejść…",
|
|
3524
3526
|
"choose": "Wybierz podejście"
|
|
3525
3527
|
},
|
|
3526
|
-
"elapsedTooltip": "Czas, który upłynął na tym kroku"
|
|
3528
|
+
"elapsedTooltip": "Czas, który upłynął na tym kroku",
|
|
3529
|
+
"prReview": {
|
|
3530
|
+
"review": "Przejrzyj ustalenia"
|
|
3531
|
+
}
|
|
3527
3532
|
},
|
|
3528
3533
|
"health": {
|
|
3529
3534
|
"title": "Stan pipeline'ów",
|
|
@@ -4924,7 +4929,9 @@
|
|
|
4924
4929
|
"line": "wiersz {line}",
|
|
4925
4930
|
"reviewing": {
|
|
4926
4931
|
"title": "Przeglądanie pull requesta…",
|
|
4927
|
-
"hint": "Dzielenie zmian na spójne części i przeglądanie każdej z nich."
|
|
4932
|
+
"hint": "Dzielenie zmian na spójne części i przeglądanie każdej z nich.",
|
|
4933
|
+
"chunks": "Sprawdzono {completed} z {total} fragmentów",
|
|
4934
|
+
"inProgress": "{count} w toku"
|
|
4928
4935
|
},
|
|
4929
4936
|
"fixing": {
|
|
4930
4937
|
"title": "Naprawianie wybranych uwag…",
|
package/i18n/locales/tr.json
CHANGED
|
@@ -953,7 +953,8 @@
|
|
|
953
953
|
"body": "Çalıştırma geçmişini burada görmek için bir pipeline başlatın."
|
|
954
954
|
},
|
|
955
955
|
"chooseApproach": "Yaklaşım seç",
|
|
956
|
-
"elapsedTooltip": "Bu adımda geçen süre"
|
|
956
|
+
"elapsedTooltip": "Bu adımda geçen süre",
|
|
957
|
+
"reviewFindings": "Bulguları incele"
|
|
957
958
|
},
|
|
958
959
|
"structure": {
|
|
959
960
|
"title": "Yapı",
|
|
@@ -1266,11 +1267,12 @@
|
|
|
1266
1267
|
"tokensInOut": "Token (giriş / çıkış)",
|
|
1267
1268
|
"transportOverhead": "Taşıma yükü",
|
|
1268
1269
|
"modelExecution": "Model yürütme",
|
|
1269
|
-
"truncated": "{count} kesildi | {count} kesildi"
|
|
1270
|
+
"truncated": "{count} kesildi | {count} kesildi",
|
|
1271
|
+
"cached": "{tokens} önbellekte"
|
|
1270
1272
|
},
|
|
1271
1273
|
"metricsBar": {
|
|
1272
1274
|
"calls": "{count} çağrı | {count} çağrı",
|
|
1273
|
-
"promptCompletionTokens": "
|
|
1275
|
+
"promptCompletionTokens": "Yeni (önbelleğe alınmamış) istem / tamamlama token'ları",
|
|
1274
1276
|
"cachedTokens": "({tokens} önbelleğe alındı)",
|
|
1275
1277
|
"cachedTokensHint": "Sağlayıcının önbelleğinden sunulan istem token'ları",
|
|
1276
1278
|
"errors": "{count} hata | {count} hata",
|
|
@@ -3535,7 +3537,10 @@
|
|
|
3535
3537
|
"proposing": "Yaklaşımlar öneriliyor…",
|
|
3536
3538
|
"choose": "Bir yaklaşım seçin"
|
|
3537
3539
|
},
|
|
3538
|
-
"elapsedTooltip": "Bu adımda geçen süre"
|
|
3540
|
+
"elapsedTooltip": "Bu adımda geçen süre",
|
|
3541
|
+
"prReview": {
|
|
3542
|
+
"review": "Bulguları incele"
|
|
3543
|
+
}
|
|
3539
3544
|
},
|
|
3540
3545
|
"health": {
|
|
3541
3546
|
"title": "Pipeline sağlığı",
|
|
@@ -4936,7 +4941,9 @@
|
|
|
4936
4941
|
"line": "satır {line}",
|
|
4937
4942
|
"reviewing": {
|
|
4938
4943
|
"title": "Pull request inceleniyor…",
|
|
4939
|
-
"hint": "Fark tutarlı parçalara bölünüp her biri inceleniyor."
|
|
4944
|
+
"hint": "Fark tutarlı parçalara bölünüp her biri inceleniyor.",
|
|
4945
|
+
"chunks": "{total} bölümden {completed} tanesi incelendi",
|
|
4946
|
+
"inProgress": "{count} devam ediyor"
|
|
4940
4947
|
},
|
|
4941
4948
|
"fixing": {
|
|
4942
4949
|
"title": "Seçili bulgular düzeltiliyor…",
|
package/i18n/locales/uk.json
CHANGED
|
@@ -953,7 +953,8 @@
|
|
|
953
953
|
"body": "Запустіть pipeline, щоб побачити тут історію запусків."
|
|
954
954
|
},
|
|
955
955
|
"chooseApproach": "Обрати підхід",
|
|
956
|
-
"elapsedTooltip": "Час, що минув на цьому кроці"
|
|
956
|
+
"elapsedTooltip": "Час, що минув на цьому кроці",
|
|
957
|
+
"reviewFindings": "Переглянути зауваження"
|
|
957
958
|
},
|
|
958
959
|
"structure": {
|
|
959
960
|
"title": "Структура",
|
|
@@ -1266,11 +1267,12 @@
|
|
|
1266
1267
|
"tokensInOut": "Токени (вхід / вихід)",
|
|
1267
1268
|
"transportOverhead": "Накладні витрати транспорту",
|
|
1268
1269
|
"modelExecution": "Виконання моделі",
|
|
1269
|
-
"truncated": "{count} обрізаний | {count} обрізані | {count} обрізаних"
|
|
1270
|
+
"truncated": "{count} обрізаний | {count} обрізані | {count} обрізаних",
|
|
1271
|
+
"cached": "{tokens} з кешу"
|
|
1270
1272
|
},
|
|
1271
1273
|
"metricsBar": {
|
|
1272
1274
|
"calls": "{count} виклик | {count} виклики | {count} викликів",
|
|
1273
|
-
"promptCompletionTokens": "
|
|
1275
|
+
"promptCompletionTokens": "Нові (некешовані) токени запиту / завершення",
|
|
1274
1276
|
"cachedTokens": "({tokens} з кешу)",
|
|
1275
1277
|
"cachedTokensHint": "Токени запиту, надані з кешу провайдера",
|
|
1276
1278
|
"errors": "{count} помилка | {count} помилки | {count} помилок",
|
|
@@ -3523,7 +3525,10 @@
|
|
|
3523
3525
|
"proposing": "Пропонування підходів…",
|
|
3524
3526
|
"choose": "Оберіть підхід"
|
|
3525
3527
|
},
|
|
3526
|
-
"elapsedTooltip": "Час, що минув на цьому кроці"
|
|
3528
|
+
"elapsedTooltip": "Час, що минув на цьому кроці",
|
|
3529
|
+
"prReview": {
|
|
3530
|
+
"review": "Переглянути зауваження"
|
|
3531
|
+
}
|
|
3527
3532
|
},
|
|
3528
3533
|
"health": {
|
|
3529
3534
|
"title": "Стан пайплайнів",
|
|
@@ -4924,7 +4929,9 @@
|
|
|
4924
4929
|
"line": "рядок {line}",
|
|
4925
4930
|
"reviewing": {
|
|
4926
4931
|
"title": "Перевірка pull request…",
|
|
4927
|
-
"hint": "Поділ змін на цілісні частини та огляд кожної з них."
|
|
4932
|
+
"hint": "Поділ змін на цілісні частини та огляд кожної з них.",
|
|
4933
|
+
"chunks": "Перевірено {completed} з {total} фрагментів",
|
|
4934
|
+
"inProgress": "{count} у процесі"
|
|
4928
4935
|
},
|
|
4929
4936
|
"fixing": {
|
|
4930
4937
|
"title": "Виправлення вибраних зауважень…",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.145.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",
|