@contraagent/ui 0.7.2 → 0.8.1
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 +1 -1
- package/custom-elements.json +105 -79
- package/dist/adapters/filters.d.ts +7 -1
- package/dist/adapters/filters.d.ts.map +1 -1
- package/dist/adapters/filters.js +8 -2
- package/dist/adapters/filters.js.map +1 -1
- package/dist/adapters/journal-columns.d.ts +2 -0
- package/dist/adapters/journal-columns.d.ts.map +1 -1
- package/dist/adapters/journal-columns.js +20 -7
- package/dist/adapters/journal-columns.js.map +1 -1
- package/dist/adapters/kpi-tiles.d.ts +8 -3
- package/dist/adapters/kpi-tiles.d.ts.map +1 -1
- package/dist/adapters/kpi-tiles.js +38 -17
- package/dist/adapters/kpi-tiles.js.map +1 -1
- package/dist/adapters/transcript/sections.d.ts +5 -0
- package/dist/adapters/transcript/sections.d.ts.map +1 -1
- package/dist/adapters/transcript/sections.js +7 -1
- package/dist/adapters/transcript/sections.js.map +1 -1
- package/dist/contraagent-ui.js +687 -697
- package/dist/elements/lists/ca-contracts.d.ts +3 -4
- package/dist/elements/lists/ca-contracts.d.ts.map +1 -1
- package/dist/elements/lists/ca-contracts.js +26 -20
- package/dist/elements/lists/ca-contracts.js.map +1 -1
- package/dist/elements/overview/ca-kpis.d.ts +3 -1
- package/dist/elements/overview/ca-kpis.d.ts.map +1 -1
- package/dist/elements/overview/ca-kpis.js +7 -2
- package/dist/elements/overview/ca-kpis.js.map +1 -1
- package/dist/elements/overview/ca-model-usage.d.ts +2 -1
- package/dist/elements/overview/ca-model-usage.d.ts.map +1 -1
- package/dist/elements/overview/ca-model-usage.js +3 -2
- package/dist/elements/overview/ca-model-usage.js.map +1 -1
- package/dist/elements/overview/ca-overview.d.ts +1 -5
- package/dist/elements/overview/ca-overview.d.ts.map +1 -1
- package/dist/elements/overview/ca-overview.js +53 -77
- package/dist/elements/overview/ca-overview.js.map +1 -1
- package/dist/elements/overview/ca-pipeline-graph.d.ts +8 -1
- package/dist/elements/overview/ca-pipeline-graph.d.ts.map +1 -1
- package/dist/elements/overview/ca-pipeline-graph.js +11 -6
- package/dist/elements/overview/ca-pipeline-graph.js.map +1 -1
- package/dist/elements/overview/ca-run-driver.d.ts.map +1 -1
- package/dist/elements/overview/ca-run-driver.js +6 -5
- package/dist/elements/overview/ca-run-driver.js.map +1 -1
- package/dist/elements/overview/pipeline-graph/strings.js +3 -3
- package/dist/elements/overview/pipeline-graph/strings.js.map +1 -1
- package/dist/elements/shared/ca-definition.d.ts.map +1 -1
- package/dist/elements/shared/ca-definition.js +1 -2
- package/dist/elements/shared/ca-definition.js.map +1 -1
- package/dist/elements/shared/file-card.d.ts.map +1 -1
- package/dist/elements/shared/file-card.js +2 -2
- package/dist/elements/shared/file-card.js.map +1 -1
- package/dist/elements/shell/ca-hosts.d.ts.map +1 -1
- package/dist/elements/shell/ca-hosts.js +1 -2
- package/dist/elements/shell/ca-hosts.js.map +1 -1
- package/dist/elements/shell/ca-monitor.d.ts +3 -1
- package/dist/elements/shell/ca-monitor.d.ts.map +1 -1
- package/dist/elements/shell/ca-monitor.js +20 -9
- package/dist/elements/shell/ca-monitor.js.map +1 -1
- package/dist/elements/shell/ca-run-picker.js +1 -1
- package/dist/elements/shell/ca-run-picker.js.map +1 -1
- package/dist/elements/shell/ca-theme-switch.d.ts.map +1 -1
- package/dist/elements/shell/ca-theme-switch.js +6 -1
- package/dist/elements/shell/ca-theme-switch.js.map +1 -1
- package/dist/elements/task/ca-task-view.js +2 -2
- package/dist/elements/task/ca-task-view.js.map +1 -1
- package/dist/elements/task/ca-transcript.d.ts +3 -0
- package/dist/elements/task/ca-transcript.d.ts.map +1 -1
- package/dist/elements/task/ca-transcript.js +11 -4
- package/dist/elements/task/ca-transcript.js.map +1 -1
- package/dist/elements/task/context.d.ts +1 -3
- package/dist/elements/task/context.d.ts.map +1 -1
- package/dist/elements/task/context.js +2 -1
- package/dist/elements/task/context.js.map +1 -1
- package/dist/elements/task/header.d.ts +3 -0
- package/dist/elements/task/header.d.ts.map +1 -1
- package/dist/elements/task/header.js +25 -14
- package/dist/elements/task/header.js.map +1 -1
- package/dist/elements/task/panes/io.d.ts +1 -1
- package/dist/elements/task/panes/io.d.ts.map +1 -1
- package/dist/elements/task/panes/io.js +21 -25
- package/dist/elements/task/panes/io.js.map +1 -1
- package/dist/elements/trends/ca-trends.d.ts.map +1 -1
- package/dist/elements/trends/ca-trends.js +2 -1
- package/dist/elements/trends/ca-trends.js.map +1 -1
- package/dist/locales/ja.d.ts +25 -32
- package/dist/locales/ja.d.ts.map +1 -1
- package/dist/locales/ja.js +25 -32
- package/dist/locales/ja.js.map +1 -1
- package/dist/words/contract.d.ts +4 -2
- package/dist/words/contract.d.ts.map +1 -1
- package/dist/words/contract.js +7 -5
- package/dist/words/contract.js.map +1 -1
- package/dist/words/index.d.ts +1 -0
- package/dist/words/index.d.ts.map +1 -1
- package/dist/words/index.js +1 -0
- package/dist/words/index.js.map +1 -1
- package/dist/words/lineage.d.ts +11 -0
- package/dist/words/lineage.d.ts.map +1 -1
- package/dist/words/lineage.js +13 -1
- package/dist/words/lineage.js.map +1 -1
- package/dist/words/quota.d.ts +2 -0
- package/dist/words/quota.d.ts.map +1 -1
- package/dist/words/quota.js +4 -0
- package/dist/words/quota.js.map +1 -1
- package/dist/words/rounds.d.ts +2 -2
- package/dist/words/rounds.js +4 -4
- package/dist/words/rounds.js.map +1 -1
- package/dist/words/run-line.d.ts +5 -3
- package/dist/words/run-line.d.ts.map +1 -1
- package/dist/words/run-line.js +6 -4
- package/dist/words/run-line.js.map +1 -1
- package/dist/words/trends.d.ts +2 -2
- package/dist/words/trends.d.ts.map +1 -1
- package/dist/words/trends.js +5 -3
- package/dist/words/trends.js.map +1 -1
- package/dist/words/working-directory.d.ts +5 -0
- package/dist/words/working-directory.d.ts.map +1 -0
- package/dist/words/working-directory.js +7 -0
- package/dist/words/working-directory.js.map +1 -0
- package/package.json +3 -3
- package/src/adapters/filters.ts +10 -2
- package/src/adapters/journal-columns.ts +21 -7
- package/src/adapters/kpi-tiles.ts +40 -18
- package/src/adapters/transcript/sections.ts +10 -2
- package/src/elements/lists/ca-contracts.ts +26 -20
- package/src/elements/overview/ca-kpis.ts +4 -2
- package/src/elements/overview/ca-model-usage.ts +3 -2
- package/src/elements/overview/ca-overview.ts +49 -79
- package/src/elements/overview/ca-pipeline-graph.ts +11 -6
- package/src/elements/overview/ca-run-driver.ts +5 -6
- package/src/elements/overview/pipeline-graph/strings.ts +3 -3
- package/src/elements/shared/ca-definition.ts +1 -2
- package/src/elements/shared/file-card.ts +2 -2
- package/src/elements/shell/ca-hosts.ts +1 -2
- package/src/elements/shell/ca-monitor.ts +19 -8
- package/src/elements/shell/ca-run-picker.ts +1 -1
- package/src/elements/shell/ca-theme-switch.ts +6 -1
- package/src/elements/task/ca-task-view.ts +2 -2
- package/src/elements/task/ca-transcript.ts +9 -4
- package/src/elements/task/context.ts +2 -1
- package/src/elements/task/header.ts +27 -15
- package/src/elements/task/panes/io.ts +21 -25
- package/src/elements/trends/ca-trends.ts +2 -1
- package/src/locales/ja.ts +25 -32
- package/src/words/contract.ts +9 -5
- package/src/words/index.ts +1 -0
- package/src/words/lineage.ts +16 -2
- package/src/words/quota.ts +6 -0
- package/src/words/rounds.ts +4 -4
- package/src/words/run-line.ts +8 -5
- package/src/words/trends.ts +5 -3
- package/src/words/working-directory.ts +8 -0
|
@@ -8,19 +8,16 @@ import { RememberedSet } from '../../core/memory.js';
|
|
|
8
8
|
import type { TaskView } from '../../core/view-route.js';
|
|
9
9
|
import { base } from '@contraagent/elements/styles';
|
|
10
10
|
import { executorIcon, executorIconStyles } from '../../words/executor.js';
|
|
11
|
-
import { kindUnit } from '../../words/format.js';
|
|
12
|
-
import {
|
|
11
|
+
import { facts, kindUnit } from '../../words/format.js';
|
|
12
|
+
import { contractStatusLabel, correctionRoundTip, correctionRoundsLabel, notRunText, type Producer } from '../../words/contract.js';
|
|
13
13
|
import { contractChip, contractStyles, fieldCheckTable, fileConditions, inputChip } from '../shared/contract-parts.js';
|
|
14
14
|
|
|
15
15
|
const CT_ORDER: readonly ContractStatus[] = ['invalid', 'refused', 'failed', 'running', 'pending', 'valid'];
|
|
16
16
|
|
|
17
|
-
/** Output contracts per status, worst first
|
|
18
|
-
|
|
17
|
+
/** Output contracts per status that is not passed, worst first: the passed ones head their own group. */
|
|
18
|
+
function ctChips(outputs: Outputs | null) {
|
|
19
19
|
const t = outputs?.tally;
|
|
20
|
-
|
|
21
|
-
return chips.length
|
|
22
|
-
? chips.map((k) => contractChip(k, t?.[k]))
|
|
23
|
-
: html`<span class="meta">${msg('No checked files')}</span>`;
|
|
20
|
+
return (t ? CT_ORDER.filter((k) => k !== 'valid' && t[k]) : []).map((k) => contractChip(k, t?.[k]));
|
|
24
21
|
}
|
|
25
22
|
|
|
26
23
|
const shortPath = (p: string) => p.split('/').slice(-2).join('/');
|
|
@@ -34,8 +31,9 @@ const rank = (s: ContractStatus | null | undefined) => (s ? CT_ORDER.indexOf(s)
|
|
|
34
31
|
|
|
35
32
|
/**
|
|
36
33
|
* The files each task must write (`OutputContract`) and read (`InputContract`),
|
|
37
|
-
* problems first, each
|
|
38
|
-
*
|
|
34
|
+
* problems first, each with the chip of its status, then the passed ones under
|
|
35
|
+
* one chip; each checked field by field against its schema. Links open the
|
|
36
|
+
* task (`ca-open-task`).
|
|
39
37
|
*
|
|
40
38
|
* @fires ca-open-task - `{key, view}`: a link to the task's input, output or transcript
|
|
41
39
|
*/
|
|
@@ -49,6 +47,8 @@ export class CaContracts extends LitElement {
|
|
|
49
47
|
css`
|
|
50
48
|
:host { display: block; container-type: inline-size; }
|
|
51
49
|
.ct-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
|
|
50
|
+
/* the passed outputs: one chip heads them, their rows carry none */
|
|
51
|
+
.passed { margin: 6px 0 0; padding: 10px 0 8px; font: inherit; border-top: 1px solid var(--line); }
|
|
52
52
|
details.ct { border-top: 1px solid var(--line); }
|
|
53
53
|
details.ct > summary { list-style: none; cursor: pointer; padding: 7px 4px; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; }
|
|
54
54
|
details.ct > summary > * { min-width: 0; overflow-wrap: anywhere; }
|
|
@@ -85,24 +85,30 @@ export class CaContracts extends LitElement {
|
|
|
85
85
|
const cs = this.outputs?.contracts ?? [];
|
|
86
86
|
this.outcomes = this.plan ? deriveRun(this.journal, this.plan).outcomes : new Map<string, TaskOutcome>();
|
|
87
87
|
if (!cs.length) {
|
|
88
|
-
return html`<div class="blank"><span class="ic" aria-hidden="true">▣</span><b>${msg('No checked files')}</b
|
|
89
|
-
<span>${msg('No task declares an OutputContract or an InputContract')}</span></div>`;
|
|
88
|
+
return html`<div class="blank"><span class="ic" aria-hidden="true">▣</span><b>${facts(msg('No checked files'), msg('no task declares an OutputContract or an InputContract'))}</b></div>`;
|
|
90
89
|
}
|
|
91
90
|
const outs = cs
|
|
92
91
|
.flatMap((c) => (c.outputs ?? []).map((o) => [c, o] as const))
|
|
93
92
|
.sort(([a, x], [b, y]) => rank(x.status) - rank(y.status) || a.key.localeCompare(b.key));
|
|
94
93
|
const ins = cs.flatMap((c) => (c.inputs ?? []).map((i) => [c, i] as const));
|
|
94
|
+
const others = outs.filter(([, o]) => o.status !== 'valid');
|
|
95
|
+
const passed = outs.filter(([, o]) => o.status === 'valid');
|
|
96
|
+
const chips = ctChips(this.outputs);
|
|
95
97
|
return html`<div class="g12">
|
|
96
98
|
<section class="panel c12">
|
|
97
|
-
<h3 title=${msg('OutputContract')}>${msg('Outputs')}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
${
|
|
99
|
+
<h3 title=${msg('Files each task must write (OutputContract)')}>${msg('Outputs')}</h3>
|
|
100
|
+
${chips.length ? html`<div class="ct-row">${chips}</div>` : nothing}
|
|
101
|
+
${repeat(others, ([c, o]) => `out|${c.key}|${o.path}`, ([c, o]) => this.outRow(c, o))}
|
|
102
|
+
${passed.length
|
|
103
|
+
? html`<h4 class="passed">${contractChip('valid', passed.length)}</h4>
|
|
104
|
+
<div role="group" aria-label=${contractStatusLabel('valid')}>
|
|
105
|
+
${repeat(passed, ([c, o]) => `out|${c.key}|${o.path}`, ([c, o]) => this.outRow(c, o))}
|
|
106
|
+
</div>`
|
|
107
|
+
: nothing}
|
|
101
108
|
</section>
|
|
102
109
|
${ins.length
|
|
103
110
|
? html`<section class="panel c12">
|
|
104
|
-
<h3 title=${msg('InputContract')}>${msg('Inputs')}
|
|
105
|
-
<span class="r">${msg('Files each task reads')}</span></h3>
|
|
111
|
+
<h3 title=${msg('Files each task reads (InputContract)')}>${msg('Inputs')}</h3>
|
|
106
112
|
${repeat(ins, ([c, i]) => `in|${c.key}|${i.path}`, ([c, i]) => this.inRow(c, i))}
|
|
107
113
|
</section>`
|
|
108
114
|
: nothing}
|
|
@@ -165,8 +171,8 @@ export class CaContracts extends LitElement {
|
|
|
165
171
|
// The chip says why there is no file; the size column shows a size only when there is one.
|
|
166
172
|
return this.details(
|
|
167
173
|
`out|${c.key}|${o.path}`,
|
|
168
|
-
html`${contractChip(status)}
|
|
169
|
-
${rounds > 1 ? html`<span class="meta" title=${
|
|
174
|
+
html`${status === 'valid' ? nothing : contractChip(status)}
|
|
175
|
+
${rounds > 1 ? html`<span class="meta" title=${correctionRoundTip()}>${correctionRoundsLabel(rounds, status === 'valid')}</span>` : nothing}
|
|
170
176
|
${this.who(c)}
|
|
171
177
|
<span class="jmono jdim ct-path" title=${o.path}>${shortPath(o.path)}</span>
|
|
172
178
|
${status === 'failed' && this.reasonOf(c.key) ? html`<span class="why">${this.reasonOf(c.key)}</span>` : nothing}
|
|
@@ -19,7 +19,7 @@ import { emit } from '../../core/events.js';
|
|
|
19
19
|
* @csspart label - a tile's label
|
|
20
20
|
* @csspart value - a tile's value
|
|
21
21
|
* @csspart sub - each line under the value
|
|
22
|
-
* @csspart action - a tile's link
|
|
22
|
+
* @csspart action - a tile's link, over the whole tile
|
|
23
23
|
*/
|
|
24
24
|
@customElement('ca-kpis')
|
|
25
25
|
@localized()
|
|
@@ -31,6 +31,8 @@ export class CaKpis extends LitElement {
|
|
|
31
31
|
@property({ attribute: false }) journal: JournalRow[] = [];
|
|
32
32
|
/** The scheduled tasks; without it, tasks are counted from the journal. */
|
|
33
33
|
@property({ attribute: false }) plan: Plan = { nodes: [], groups: [] };
|
|
34
|
+
/** Leaves the kind with the highest cost out of the cost tile, for a page that shows the cost by kind beside it. */
|
|
35
|
+
@property({ type: Boolean, attribute: 'no-highest-cost' }) noHighestCost = false;
|
|
34
36
|
|
|
35
37
|
private readonly onAction = (e: CustomEvent<{ action: string }>): void => {
|
|
36
38
|
e.stopPropagation();
|
|
@@ -40,7 +42,7 @@ export class CaKpis extends LitElement {
|
|
|
40
42
|
};
|
|
41
43
|
|
|
42
44
|
override render() {
|
|
43
|
-
return html`<cae-stat-tiles exportparts="tiles, tile, label, value, sub, action" .tiles=${kpiTiles(this.journal, deriveRun(this.journal, this.plan))} @cae-action=${this.onAction}></cae-stat-tiles>`;
|
|
45
|
+
return html`<cae-stat-tiles exportparts="tiles, tile, label, value, sub, action" .tiles=${kpiTiles(this.journal, deriveRun(this.journal, this.plan), { highestCost: !this.noHighestCost })} @cae-action=${this.onAction}></cae-stat-tiles>`;
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
|
|
@@ -16,7 +16,8 @@ const COLUMNS: readonly ModelMeasure[] = ['cost', 'tokens', 'time', 'sessions'];
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* What each model was used for in a run (`Plan.models`): the share of each model in
|
|
19
|
-
* the chosen measure (cost, tokens, time or agent sessions) as one bar
|
|
19
|
+
* the chosen measure (cost, tokens, time or agent sessions) as one bar (the table
|
|
20
|
+
* names each segment, so the bar has no names under it), and a table
|
|
20
21
|
* of every model with its share and every measure, and its peak context when
|
|
21
22
|
* a session on it reported one. A model keeps its colour, and
|
|
22
23
|
* its place, in the order it was first used, whatever the measure; past six models
|
|
@@ -74,7 +75,7 @@ export class CaModelUsage extends LitElement {
|
|
|
74
75
|
@cae-change=${(e: CustomEvent<{ value: string }>) => (this.measure = e.detail.value as ModelMeasure)}></cae-segmented>
|
|
75
76
|
</div>`
|
|
76
77
|
: nothing}
|
|
77
|
-
${shareBar(shareParts(this.models, measure), { label: measureLabel(measure) })}
|
|
78
|
+
${shareBar(shareParts(this.models, measure), { label: measureLabel(measure), names: false })}
|
|
78
79
|
<div class="wrap" data-scroll="x" tabindex="0" role="region" aria-label=${msg('Models')}>
|
|
79
80
|
<table>
|
|
80
81
|
<thead>
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
type TypedPanelBody,
|
|
8
8
|
liveActivities,
|
|
9
9
|
progress,
|
|
10
|
-
result,
|
|
11
10
|
runAccounts,
|
|
12
11
|
runRelative,
|
|
13
12
|
spendOf,
|
|
@@ -29,9 +28,9 @@ import { facts, kindUnit, localTime, sentence } from '../../words/format.js';
|
|
|
29
28
|
import { notStartedCause, outcomeLabel, stateCount, stopLabel } from '../../words/index.js';
|
|
30
29
|
import { base } from '@contraagent/elements/styles';
|
|
31
30
|
import { pill, statusWord } from '@contraagent/elements/primitives';
|
|
32
|
-
import {
|
|
31
|
+
import { outcomeTone } from '../../lib/tone.js';
|
|
33
32
|
import { contractChip, formatOf } from '../shared/contract-parts.js';
|
|
34
|
-
import { contractStatusLabel
|
|
33
|
+
import { contractStatusLabel } from '../../words/contract.js';
|
|
35
34
|
import { taskChip } from '../shared/task-chip.js';
|
|
36
35
|
import '../lists/ca-proc-tree.js';
|
|
37
36
|
import './ca-kpis.js';
|
|
@@ -132,11 +131,15 @@ export class CaOverview extends LitElement {
|
|
|
132
131
|
}
|
|
133
132
|
.ok { display: flex; align-items: baseline; gap: 6px; color: var(--text-2); }
|
|
134
133
|
.ok span[aria-hidden] { color: var(--status-done); }
|
|
135
|
-
/* a failed output
|
|
136
|
-
.ofl { grid-template-columns:
|
|
137
|
-
.ofl > .jstop { white-space: nowrap; }
|
|
134
|
+
/* a failed output, under the chip of its status: its task and what it is on one line, where under them */
|
|
135
|
+
.ofl { grid-template-columns: minmax(0, 1fr) auto; }
|
|
138
136
|
.ofl > b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
139
|
-
.ofl > .meta {
|
|
137
|
+
.ofl > .meta { overflow: hidden; text-overflow: ellipsis; }
|
|
138
|
+
.ofl > .meta:last-child { grid-column: 1 / -1; }
|
|
139
|
+
.ogroup + .ogroup, .ogroup + .ct-row { margin-top: 10px; }
|
|
140
|
+
/* a heading that is a link to its tab */
|
|
141
|
+
h3 a.hl { color: inherit; text-decoration: none; }
|
|
142
|
+
h3 a.hl:hover { color: var(--accent); text-decoration: underline; }
|
|
140
143
|
.ct-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
|
|
141
144
|
.pcards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr)); gap: 12px; }
|
|
142
145
|
.pcard { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 12px; align-items: start; padding: 12px 14px; border-radius: 10px;
|
|
@@ -158,10 +161,8 @@ export class CaOverview extends LitElement {
|
|
|
158
161
|
.ofl > .meta { white-space: nowrap; }
|
|
159
162
|
.stopped { grid-column: 1 / 4; color: var(--text-muted); font-size: 11px; display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
|
|
160
163
|
.fl.muted { opacity: 0.7; }
|
|
161
|
-
|
|
162
|
-
.
|
|
163
|
-
.next { margin: 10px 2px 2px; font-size: 12px; color: var(--text-2); }
|
|
164
|
-
.next code { font-family: var(--mono); }
|
|
164
|
+
/* the tasks done after retrying: a group of their own under a rule, after the problems */
|
|
165
|
+
.recovered { margin-top: 8px; padding-top: 6px; border-top: 1px solid var(--line); }
|
|
165
166
|
.more { font-size: 12px; margin: 6px 10px 0; }
|
|
166
167
|
`,
|
|
167
168
|
];
|
|
@@ -211,29 +212,27 @@ export class CaOverview extends LitElement {
|
|
|
211
212
|
<section class="panel enter problems">
|
|
212
213
|
<h3>${msg('Problems')}
|
|
213
214
|
<span class="r"><a class="lnk" href="#" @click=${(e: Event) => this.nav(e, () => emit(this, 'ca-navigate', { tab: 'journal', stop: 'bad' }))}>${msg('Failed attempts in history')}</a></span></h3>
|
|
214
|
-
${this.problems(
|
|
215
|
+
${this.problems()}
|
|
215
216
|
</section>
|
|
216
217
|
<section class="panel enter outputs">
|
|
217
|
-
<h3 title=${msg('Checked files (OutputContract, InputContract)')}>${msg('Outputs')}
|
|
218
|
-
<span class="r"><a class="lnk" href="#" @click=${(e: Event) => this.nav(e, () => this.go('outputs'))}>${msg('All outputs')}</a></span></h3>
|
|
218
|
+
<h3 title=${msg('Checked files (OutputContract, InputContract)')}><a class="hl" href="#" @click=${(e: Event) => this.nav(e, () => this.go('outputs'))}>${msg('Outputs')}</a></h3>
|
|
219
219
|
${this.outputs()}
|
|
220
220
|
</section>
|
|
221
221
|
${running ? html`<div class="row">${this.runningCard(live, busy, max)}</div>` : nothing}
|
|
222
222
|
</div>
|
|
223
223
|
<section class="panel enter">
|
|
224
224
|
<h3 title=${msg('Every task the run scheduled, by kind (plan.jsonl)')}>${msg('Pipeline')}
|
|
225
|
-
|
|
225
|
+
${live ? html`<span class="r">${this.progressLine()}</span>` : nothing}</h3>
|
|
226
226
|
<ca-pipeline-graph .plan=${s.plan} .forecast=${s.forecast} .journal=${s.journal} .run=${this.run} .layer=${this.layer} .unit=${this.unit} .sel=${this.sel} ?live=${live}></ca-pipeline-graph>
|
|
227
227
|
</section>
|
|
228
228
|
<section class="panel enter">
|
|
229
229
|
<h3 title=${msg('Counted from every finished attempt (journal.jsonl)')}>${msg('Totals')}</h3>
|
|
230
|
-
<ca-kpis .journal=${s.journal} .plan=${s.plan}></ca-kpis>
|
|
230
|
+
<ca-kpis .journal=${s.journal} .plan=${s.plan} no-highest-cost></ca-kpis>
|
|
231
231
|
</section>
|
|
232
232
|
<div class="band parts">
|
|
233
233
|
${live
|
|
234
234
|
? html`<section class="panel enter">
|
|
235
|
-
<h3>${msg('Process tree')}
|
|
236
|
-
<span class="r"><a class="lnk" href="#" @click=${(e: Event) => this.nav(e, () => this.go('procs'))}>${msg('All processes')}</a></span></h3>
|
|
235
|
+
<h3><a class="hl" href="#" @click=${(e: Event) => this.nav(e, () => this.go('procs'))}>${msg('Process tree')}</a></h3>
|
|
237
236
|
<ca-proc-tree .procs=${s.procs}></ca-proc-tree>
|
|
238
237
|
</section>`
|
|
239
238
|
: nothing}
|
|
@@ -245,15 +244,13 @@ export class CaOverview extends LitElement {
|
|
|
245
244
|
: nothing}
|
|
246
245
|
${s.plan.models?.length
|
|
247
246
|
? html`<section class="panel enter">
|
|
248
|
-
<h3 title=${msg('What the agent sessions spent on each model, each model of a model switch counted separately (Plan.models)')}>${msg('Models')}
|
|
249
|
-
<span class="r">${s.plan.models.length === 1 ? msg('1 model') : msg(str`${s.plan.models.length} models`)}</span></h3>
|
|
247
|
+
<h3 title=${msg('What the agent sessions spent on each model, each model of a model switch counted separately (Plan.models)')}>${msg('Models')}</h3>
|
|
250
248
|
<ca-model-usage .models=${s.plan.models}></ca-model-usage>
|
|
251
249
|
</section>`
|
|
252
250
|
: nothing}
|
|
253
251
|
${runAccounts(s.journal).length || s.plan.rests?.length
|
|
254
252
|
? html`<section class="panel enter">
|
|
255
|
-
<h3 title=${msg('Account-wide | read at each agent session start')}>
|
|
256
|
-
${msg('Subscription usage')}<span class="r">${msg('Per account, first → last reading')}</span></h3>
|
|
253
|
+
<h3 title=${msg('Account-wide | first and last reading per account | read at each agent session start')}>${msg('Subscription usage')}</h3>
|
|
257
254
|
<ca-quota .journal=${s.journal} .caps=${s.plan.quota_caps ?? []} .rests=${s.plan.rests ?? []} .rule=${s.plan.quota_rule ?? ''} ?live=${live}></ca-quota>
|
|
258
255
|
</section>`
|
|
259
256
|
: nothing}
|
|
@@ -277,8 +274,7 @@ export class CaOverview extends LitElement {
|
|
|
277
274
|
</section>`
|
|
278
275
|
: nothing}
|
|
279
276
|
<section class="panel enter">
|
|
280
|
-
<h3>${msg('Timeline')}
|
|
281
|
-
<span class="r">${this.triesLine()}</span></h3>
|
|
277
|
+
<h3>${msg('Timeline')}</h3>
|
|
282
278
|
<ca-timeline .journal=${s.journal} .plan=${s.plan} .procs=${s.procs} .live=${live} .run=${this.run}></ca-timeline>
|
|
283
279
|
</section>
|
|
284
280
|
</div>`;
|
|
@@ -298,60 +294,44 @@ export class CaOverview extends LitElement {
|
|
|
298
294
|
if (!contracts.length) {
|
|
299
295
|
return html`<div class="meta">${msg('No output files')}</div>`;
|
|
300
296
|
}
|
|
301
|
-
const chips = CT_ORDER.filter((k) => tally[k]);
|
|
302
297
|
// Only what went wrong with a file; tasks that never started are the problems section's.
|
|
303
298
|
const bad = contracts
|
|
304
299
|
.flatMap((c) => (c.outputs ?? []).map((o): [ContractRecord, ContractSpec] => [c, o]))
|
|
305
300
|
.filter(([, o]) => o.status === 'invalid' || o.status === 'failed');
|
|
306
301
|
const shown = bad.slice(0, OUTPUTS_SHOWN);
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
302
|
+
// The rows shown sit under the chip of their status; the other statuses are a row of chips after them.
|
|
303
|
+
const groups = CT_ORDER.filter((k) => tally[k] && shown.some(([, o]) => o.status === k));
|
|
304
|
+
const chips = CT_ORDER.filter((k) => tally[k] && !groups.includes(k));
|
|
305
|
+
return html`${groups.map(
|
|
306
|
+
(k) => html`<div class="ogroup" role="group" aria-label=${contractStatusLabel(k)}>
|
|
307
|
+
<div class="ct-row">${contractChip(k, tally[k])}</div>
|
|
308
|
+
${shown
|
|
309
|
+
.filter(([, o]) => o.status === k)
|
|
310
|
+
.map(
|
|
311
|
+
([c, o]) => html`<button type="button" class="fl ofl" @click=${() => this.go('outputs')}>
|
|
312
|
+
<b class="jmono" title=${c.key}>${kindUnit({ kind: c.kind, unit: c.unit === c.key ? '' : c.unit })}</b>
|
|
313
|
+
<span class="meta">${formatOf(o)}</span>
|
|
314
|
+
<span class="meta" title=${runRelative(o.errors?.[0] || o.path, this.run)}>${runRelative(o.errors?.[0] || o.path, this.run)}</span>
|
|
315
|
+
</button>`,
|
|
316
|
+
)}
|
|
317
|
+
</div>`,
|
|
320
318
|
)}
|
|
321
319
|
${bad.length > shown.length
|
|
322
320
|
? html`<div class="more"><a class="lnk" href="#" @click=${(e: Event) => this.nav(e, () => this.go('outputs'))}>${bad.length - shown.length === 1
|
|
323
321
|
? msg('1 more output')
|
|
324
322
|
: msg(str`${bad.length - shown.length} more outputs`)}</a></div>`
|
|
325
323
|
: nothing}
|
|
326
|
-
${
|
|
327
|
-
? html`<div class="
|
|
328
|
-
?
|
|
329
|
-
|
|
324
|
+
${chips.length || !groups.length
|
|
325
|
+
? html`<div class="ct-row">
|
|
326
|
+
${chips.length ? chips.map((k) => contractChip(k, tally[k])) : html`<span class="meta">${msg('No checked files')}</span>`}
|
|
327
|
+
</div>`
|
|
330
328
|
: nothing}`;
|
|
331
329
|
}
|
|
332
330
|
|
|
333
|
-
/** While running, how far the run is; once over, how its tasks ended. */
|
|
334
|
-
private progressLine(
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
if (live || r.left) {
|
|
338
|
-
const p = progress(plan);
|
|
339
|
-
return facts(msg(str`${p.pct}%`), msg(str`${p.done} of ${p.total} tasks done`), p.partial ? stateCount('partial', p.partial) : '', p.skipped ? stateCount('skipped', p.skipped) : '', p.cancelled ? stateCount('cancelled', p.cancelled) : '');
|
|
340
|
-
}
|
|
341
|
-
return facts(
|
|
342
|
-
stateCount('done', r.done),
|
|
343
|
-
r.skipped ? stateCount('skipped', r.skipped) : '',
|
|
344
|
-
r.failed ? stateCount('failed', r.failed) : '',
|
|
345
|
-
r.notStarted ? stateCount('not_started', r.notStarted) : '',
|
|
346
|
-
r.partial ? stateCount('partial', r.partial) : '',
|
|
347
|
-
r.cancelled ? stateCount('cancelled', r.cancelled) : '',
|
|
348
|
-
);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/** "23 attempts | 4 not started": a task that never started has no attempt. */
|
|
352
|
-
private triesLine(): string {
|
|
353
|
-
const { tries, notStarted } = deriveRun(this.state.journal, this.state.plan).tries;
|
|
354
|
-
return facts(tries === 1 ? msg('1 attempt') : msg(str`${tries} attempts`), notStarted ? stateCount('not_started', notStarted) : '');
|
|
331
|
+
/** While running, how far the run is; once over, the run's state and the tiles tell how its tasks ended. */
|
|
332
|
+
private progressLine(): string {
|
|
333
|
+
const p = progress(this.state.plan);
|
|
334
|
+
return facts(msg(str`${p.pct}%`), msg(str`${p.done} of ${p.total} tasks done`), p.partial ? stateCount('partial', p.partial) : '', p.skipped ? stateCount('skipped', p.skipped) : '', p.cancelled ? stateCount('cancelled', p.cancelled) : '');
|
|
355
335
|
}
|
|
356
336
|
|
|
357
337
|
/** A link's click: no navigation of the page's own, then `go`. */
|
|
@@ -425,7 +405,7 @@ export class CaOverview extends LitElement {
|
|
|
425
405
|
return kindUnit(t);
|
|
426
406
|
}
|
|
427
407
|
|
|
428
|
-
private problems(
|
|
408
|
+
private problems() {
|
|
429
409
|
const { outcomes, problems } = deriveRun(this.state.journal, this.state.plan);
|
|
430
410
|
const { failed, notStarted, partial, recovered } = problems;
|
|
431
411
|
const issues = failed.length + notStarted.length + partial.length;
|
|
@@ -482,8 +462,8 @@ export class CaOverview extends LitElement {
|
|
|
482
462
|
</div>`,
|
|
483
463
|
)}
|
|
484
464
|
${rest(partial.length, PROBLEMS_SHOWN, 'partial')}
|
|
485
|
-
${recovered.length
|
|
486
|
-
|
|
465
|
+
${recovered.length
|
|
466
|
+
? html`<div class="recovered" role="group" aria-label=${sentence(outcomeLabel('recovered'))}>${repeat(
|
|
487
467
|
recovered.slice(0, RECOVERED_SHOWN),
|
|
488
468
|
(t) => t.key,
|
|
489
469
|
(t) => {
|
|
@@ -498,24 +478,14 @@ export class CaOverview extends LitElement {
|
|
|
498
478
|
</div>`;
|
|
499
479
|
},
|
|
500
480
|
)}
|
|
501
|
-
${rest(recovered.length, RECOVERED_SHOWN, 'retried')}
|
|
502
|
-
|
|
481
|
+
${rest(recovered.length, RECOVERED_SHOWN, 'retried')}</div>`
|
|
482
|
+
: nothing}`;
|
|
503
483
|
}
|
|
504
484
|
|
|
505
485
|
/** A row's second line: one line, the whole of it in its tooltip. */
|
|
506
486
|
private metaLine(text: string) {
|
|
507
487
|
return html`<div class="meta" title=${text}>${text}</div>`;
|
|
508
488
|
}
|
|
509
|
-
|
|
510
|
-
/** For a finished run with problems: how many tasks are not done (the tasks resume=True runs again). */
|
|
511
|
-
private nextStep(live: boolean, problemCount: number) {
|
|
512
|
-
if (live || !problemCount) return nothing;
|
|
513
|
-
const c = deriveRun(this.state.journal, this.state.plan).counts;
|
|
514
|
-
// A partly done task is finished in this run, and not done: a resume runs it again.
|
|
515
|
-
const again = c.total - c.finished + c.partial;
|
|
516
|
-
if (!again) return nothing;
|
|
517
|
-
return html`<div class="next" title="resume=True">${msg(str`${again} of ${c.total} tasks not done`)}</div>`;
|
|
518
|
-
}
|
|
519
489
|
}
|
|
520
490
|
|
|
521
491
|
declare global {
|
|
@@ -102,7 +102,9 @@ const EMPTY_LAYER: LayerGraph = {
|
|
|
102
102
|
* of passes or by status (`<cae-mark-matrix>`). The breadcrumb, shown on every layer
|
|
103
103
|
* below the top (a loop named by its file and line), and Escape go back up. On a
|
|
104
104
|
* narrow screen the graph runs top to bottom. "Graph | Table" changes the view; in a
|
|
105
|
-
* loop's passes, "Graph" opens the layer the loop is in, with its box selected.
|
|
105
|
+
* loop's passes, "Graph" opens the layer the loop is in, with its box selected. With
|
|
106
|
+
* `controls` false, the graph is only shown: no outline, no "Show all inside" and
|
|
107
|
+
* "Hide all inside", no zoom buttons and no "Graph | Table".
|
|
106
108
|
* A height set on the element (or given it by a flex or grid container) is the
|
|
107
109
|
* graph's, less the outline's line above it: the drawing fits in it.
|
|
108
110
|
*
|
|
@@ -119,6 +121,7 @@ export class CaPipelineGraph extends LitElement {
|
|
|
119
121
|
journal: { attribute: false },
|
|
120
122
|
run: {},
|
|
121
123
|
live: { type: Boolean },
|
|
124
|
+
controls: { type: Boolean },
|
|
122
125
|
layer: {},
|
|
123
126
|
unit: {},
|
|
124
127
|
sel: {},
|
|
@@ -139,6 +142,8 @@ export class CaPipelineGraph extends LitElement {
|
|
|
139
142
|
run = '';
|
|
140
143
|
/** The run is running: tasks still pending are waiting; once it is over, they did not run. */
|
|
141
144
|
live = false;
|
|
145
|
+
/** The outline, "Show all inside" and "Hide all inside", the zoom buttons and "Graph | Table"; false for a graph that is only shown. */
|
|
146
|
+
controls = true;
|
|
142
147
|
/** The layer shown: its segments (function names, then `loop:<line>` for a loop's passes) joined by `/`; '' for the layer the graph opens on. */
|
|
143
148
|
layer = '';
|
|
144
149
|
/** The unit highlighted while nothing is hovered or focused. */
|
|
@@ -436,8 +441,8 @@ export class CaPipelineGraph extends LitElement {
|
|
|
436
441
|
// The graph keeps its place in one template whichever it is, and whether there is an
|
|
437
442
|
// outline: a change between them (the first size report, a resize, a plan that gains a
|
|
438
443
|
// function) keeps the graph's element, and with it the focus, the zoom and the pan.
|
|
439
|
-
const side = this.wide && this.tree.length > 0;
|
|
440
|
-
const part = !this.tree.length
|
|
444
|
+
const side = this.controls && this.wide && this.tree.length > 0;
|
|
445
|
+
const part = !this.controls || !this.tree.length
|
|
441
446
|
? nothing
|
|
442
447
|
: side
|
|
443
448
|
? outline(this.oh, this.tree)
|
|
@@ -451,10 +456,10 @@ export class CaPipelineGraph extends LitElement {
|
|
|
451
456
|
return html`<cae-layered-graph .graph=${this.input} .states=${this.states} .selected=${this.sel || null} .highlight=${this.unit || null}
|
|
452
457
|
.order=${this.prevOrder} key=${this.segments.join('/')} direction=${this.down || this.tall ? 'down' : 'across'} .matrix=${this.matrixIn}
|
|
453
458
|
.related=${this.lights} .strings=${graphStrings(!!parentLayer(this.segments, this.auto), functions)} .matrixStrings=${matrixStrings()}
|
|
454
|
-
.renderIcon=${renderIcon} .iconStyles=${iconStyles}
|
|
459
|
+
.renderIcon=${renderIcon} .iconStyles=${iconStyles} .controls=${this.controls}
|
|
455
460
|
@cae-select=${this.onSelect} @cae-activate=${this.onActivate} @cae-drill=${this.onDrill} @cae-view-change=${this.onView} @cae-toggle=${this.onToggle}
|
|
456
461
|
@cae-sort=${(e: CustomEvent<{ id: string }>) => (this.sort = e.detail.id as MatrixSort)}>
|
|
457
|
-
<div slot="crumbs">${crumbs(this.h, splitLayer(this.segments).loop ? null : openControls(this.openMode(), (m) => this.setMode(m)))}${missingLine(this.missing)}${this.segments.join('/') === this.auto.join('/') ? html`${forecastNote(this.plan, this.forecast)}${unawaitedLine(this.h)}` : nothing}</div>
|
|
462
|
+
<div slot="crumbs">${crumbs(this.h, splitLayer(this.segments).loop || !this.controls ? null : openControls(this.openMode(), (m) => this.setMode(m)))}${missingLine(this.missing)}${this.segments.join('/') === this.auto.join('/') ? html`${forecastNote(this.plan, this.forecast)}${unawaitedLine(this.h)}` : nothing}</div>
|
|
458
463
|
${s ? inspector(this.h, s) : nothing}
|
|
459
464
|
</cae-layered-graph>`;
|
|
460
465
|
}
|
|
@@ -462,7 +467,7 @@ export class CaPipelineGraph extends LitElement {
|
|
|
462
467
|
/** The graph's own width: the element's, less the outline's column beside it. */
|
|
463
468
|
private graphWidth(): number {
|
|
464
469
|
const w = this.clientWidth || 1200;
|
|
465
|
-
return this.tree.length && w >= OUTLINE_WIDE ? w - OUTLINE_COLUMN : w;
|
|
470
|
+
return this.controls && this.tree.length && w >= OUTLINE_WIDE ? w - OUTLINE_COLUMN : w;
|
|
466
471
|
}
|
|
467
472
|
|
|
468
473
|
/** The place keys on the way to the layer shown (the functions of its path). */
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { result, runActivity, runIdOf, type HostSummary, type Plan, type Procs, type RunSummary } from '@contraagent/api';
|
|
2
2
|
import { localized, msg, str } from '@lit/localize';
|
|
3
3
|
import { LitElement, css, html, nothing } from 'lit';
|
|
4
4
|
import { customElement, property } from 'lit/decorators.js';
|
|
5
5
|
import { starts } from '@contraagent/elements';
|
|
6
|
-
import { facts,
|
|
6
|
+
import { facts, localTime, sentence } from '../../words/format.js';
|
|
7
7
|
import { hostFact, lastReport, noReportLabel } from '../../words/hosts.js';
|
|
8
8
|
import { preflightLabel, preflightStoppedCause, preflightStoppedTitle, preflightTip } from '../../words/preflight.js';
|
|
9
9
|
import { preflightRows } from '../../adapters/preflight.js';
|
|
@@ -80,7 +80,6 @@ export class CaRunDriver extends LitElement {
|
|
|
80
80
|
// Its host stopped reporting (a hub): not known to run, not known to have ended.
|
|
81
81
|
const quiet = runActivity(r) === 'unresponsive';
|
|
82
82
|
const [title, tone]: [string, Tone] = quiet ? [sentence(noReportLabel()), 'attention'] : this.stateTitle();
|
|
83
|
-
const took = quiet ? null : elapsedS(r);
|
|
84
83
|
return html`<div class="drv off">
|
|
85
84
|
<div class="drv-ic" data-tone=${toneAttr(tone)} aria-hidden="true">${MARK[tone]}</div>
|
|
86
85
|
<div>
|
|
@@ -89,8 +88,8 @@ export class CaRunDriver extends LitElement {
|
|
|
89
88
|
this.plan.preflight?.stopped?.length ? preflightStoppedCause(this.plan.preflight.stopped) : '',
|
|
90
89
|
quiet ? lastReport(this.host) : '',
|
|
91
90
|
!r?.last_ts ? msg('No activity') : quiet ? msg(str`Last activity ${localTime(r.last_ts, true)}`) : msg(str`Ended ${localTime(r.last_ts, true)}`),
|
|
92
|
-
took
|
|
93
|
-
r?.run_group ? msg(str`Run group ${r.run_group}`) : '',
|
|
91
|
+
// How long it took is in the header's run line; a run group named as the run is no fact of its own.
|
|
92
|
+
r?.run_group && r.run_group !== runIdOf(r) ? msg(str`Run group ${r.run_group}`) : '',
|
|
94
93
|
quiet ? hostFact(r?.host_id ?? '') : '',
|
|
95
94
|
)}</div>
|
|
96
95
|
${this.preflight()}
|
|
@@ -101,7 +100,7 @@ export class CaRunDriver extends LitElement {
|
|
|
101
100
|
const since = starts.at(`drv:${p.pid ?? ''}`, Number.isNaN(started) ? 1 : (Date.now() - started) / 1000);
|
|
102
101
|
const rows: [string, string | number][] = [
|
|
103
102
|
[msg('PID'), p.pid ?? '—'],
|
|
104
|
-
[msg('Run group'), p.run_group],
|
|
103
|
+
...(r && p.run_group === runIdOf(r) ? [] : [[msg('Run group'), p.run_group] as [string, string]]),
|
|
105
104
|
[msg('Running at once (limit)'), p.max_workers || '—'],
|
|
106
105
|
[msg('Started'), localTime(p.started_at, true)],
|
|
107
106
|
];
|
|
@@ -29,12 +29,12 @@ export function graphStrings(up: boolean, functions: boolean): Omit<LayeredGraph
|
|
|
29
29
|
inspector: msg('Selected item'),
|
|
30
30
|
stubTip: msg('Outside this layer'),
|
|
31
31
|
more: (n) => msg(str`+${n}`),
|
|
32
|
-
badge: msg('
|
|
32
|
+
badge: msg('Passes'),
|
|
33
33
|
solidEdge: lineageWord('given_from'),
|
|
34
34
|
dottedEdge: lineageWord('after'),
|
|
35
35
|
dashedEdge: lineageWord('created_from'),
|
|
36
|
-
cycle: msg('
|
|
37
|
-
drill: msg('
|
|
36
|
+
cycle: msg('Next pass'),
|
|
37
|
+
drill: msg('Has a level below'),
|
|
38
38
|
open: msg('Show inside'),
|
|
39
39
|
close: msg('Hide inside'),
|
|
40
40
|
iconNames: { agent: msg('agent task'), python: msg('Python task') },
|
|
@@ -182,9 +182,8 @@ export class CaDefinition extends LitElement {
|
|
|
182
182
|
};
|
|
183
183
|
return html`<div class="df">
|
|
184
184
|
<div class="df-hd">
|
|
185
|
-
<button type="button" class="df-sum" aria-expanded=${isOpen ? 'true' : 'false'} @click=${toggle}>
|
|
185
|
+
<button type="button" class="df-sum" aria-expanded=${isOpen ? 'true' : 'false'} title=${isRole ? msg('Role of this kind') : nothing} @click=${toggle}>
|
|
186
186
|
<span class="tag">${f.part}</span><span class="jmono">${f.path}</span>
|
|
187
|
-
${isRole ? html`<span class="ct-chip">${msg('Role of this kind')}</span>` : nothing}
|
|
188
187
|
</button>
|
|
189
188
|
${isMd
|
|
190
189
|
? html`<button type="button" class="df-tog" @click=${flip}>${showSource ? msg('Show rendered') : msg('Show source')}</button>`
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { runRelative, type ContractSpec } from '@contraagent/api';
|
|
4
4
|
import { msg } from '@lit/localize';
|
|
5
5
|
import { html, nothing, type TemplateResult } from 'lit';
|
|
6
|
-
import {
|
|
6
|
+
import { correctionRoundTip, correctionRoundsLabel, notRunText, type Producer } from '../../words/contract.js';
|
|
7
7
|
import { contractChip, fieldCheckTable, fileConditions, inputChip } from './contract-parts.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -27,7 +27,7 @@ export function ioFileCard(
|
|
|
27
27
|
const stat =
|
|
28
28
|
role === 'output'
|
|
29
29
|
? html`${contractChip(o.status)}${(o.rounds ?? 0) > 1
|
|
30
|
-
? html` <span class="meta" title=${
|
|
30
|
+
? html` <span class="meta" title=${correctionRoundTip()}>${correctionRoundsLabel(o.rounds, o.status === 'valid')}</span>`
|
|
31
31
|
: nothing}`
|
|
32
32
|
: inputChip(o);
|
|
33
33
|
const head = html`<div class="io-hd">${opts.chip ?? stat}<span class="jmono ct-path" title=${o.path}>${runRelative(o.path, run)}</span></div>${opts.origin
|
|
@@ -77,8 +77,7 @@ export class CaHosts extends LitElement {
|
|
|
77
77
|
</section>
|
|
78
78
|
${quota.length
|
|
79
79
|
? html`<section class="panel c12 enter">
|
|
80
|
-
<h3 title=${msg('Account-wide | read at each agent session start')}>
|
|
81
|
-
${msg('Subscription usage')}<span class="r">${msg('Per account, first → last reading')}</span></h3>
|
|
80
|
+
<h3 title=${msg('Account-wide | first and last reading per account | read at each agent session start')}>${msg('Subscription usage')}</h3>
|
|
82
81
|
<ca-quota .accounts=${quota} .rests=${quota.flatMap((a) => a.rests ?? [])} live></ca-quota>
|
|
83
82
|
</section>`
|
|
84
83
|
: nothing}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
runActivity,
|
|
10
10
|
runIdOf,
|
|
11
11
|
runRow,
|
|
12
|
+
tryCounts,
|
|
12
13
|
type MonitorSnapshot,
|
|
13
14
|
type RunDerived,
|
|
14
15
|
} from '@contraagent/api';
|
|
@@ -24,7 +25,8 @@ import { ViewRouter, type ViewRouteCause, type ViewRouterMode } from '../../core
|
|
|
24
25
|
import { LocaleController } from '../../controllers/locale.js';
|
|
25
26
|
import { ShortcutsController, isShortcutScope, type ShortcutScope } from '../../controllers/shortcuts.js';
|
|
26
27
|
import { ThemeController } from '../../controllers/theme.js';
|
|
27
|
-
import { runLine, runLineAccounts,
|
|
28
|
+
import { runLine, runLineAccounts, shownTasksLine, shownTriesLine } from '../../words/index.js';
|
|
29
|
+
import { filterJournal, filterTasks } from '../../adapters/filters.js';
|
|
28
30
|
import { runMark } from '../../words/run-line.js';
|
|
29
31
|
import { exportTip, exportedLabel } from '../../words/export.js';
|
|
30
32
|
import { apiErrorLine } from '../../words/api-error.js';
|
|
@@ -477,9 +479,9 @@ export class CaMonitor extends LitElement {
|
|
|
477
479
|
<span class="rs" title=${summary ? accountsTip(runLineAccounts(snap.state, summary)) : ''}>${summary ? runLine(snap.state, summary, derived) : ''}</span>`;
|
|
478
480
|
}
|
|
479
481
|
|
|
480
|
-
/** The run button's label on the trends page: its name,
|
|
482
|
+
/** The run button's label on the trends page: its name, what it shows in its tooltip. */
|
|
481
483
|
private trendsLabel() {
|
|
482
|
-
return html`<span class="dot" data-tone="neutral" aria-hidden="true"></span><span class="rn"
|
|
484
|
+
return html`<span class="dot" data-tone="neutral" aria-hidden="true"></span><span class="rn" title=${trendsTip()}>${trendsTitle()}</span>`;
|
|
483
485
|
}
|
|
484
486
|
|
|
485
487
|
/** The run button's label on the hosts page: the hosts in one line, attention while a host has no report. */
|
|
@@ -514,8 +516,7 @@ export class CaMonitor extends LitElement {
|
|
|
514
516
|
private renderBar(d: RunDerived) {
|
|
515
517
|
const { viewRoute } = this;
|
|
516
518
|
if (viewRoute.tab !== 'tasks' && viewRoute.tab !== 'journal') return nothing;
|
|
517
|
-
const {
|
|
518
|
-
const total = counts.total;
|
|
519
|
+
const { kinds } = d;
|
|
519
520
|
return html`<div class="bar">
|
|
520
521
|
<select title=${msg('Kind')} aria-label=${msg('Kind')} @change=${(e: Event) => this.navigate({ kind: (e.target as HTMLSelectElement).value })}>
|
|
521
522
|
<option value="" ?selected=${!viewRoute.kind}>${msg('All kinds')}</option>
|
|
@@ -523,11 +524,21 @@ export class CaMonitor extends LitElement {
|
|
|
523
524
|
</select>
|
|
524
525
|
<input placeholder=${msg('Filter')} aria-label=${msg('Text filter')} size="22" title=${this.shortcutScope !== 'off' ? msg('Text filter (/)') : msg('Text filter')} .value=${this.qDraft ?? viewRoute.q}
|
|
525
526
|
@input=${(e: Event) => this.setQ((e.target as HTMLInputElement).value)} />
|
|
526
|
-
<span class="meta">${
|
|
527
|
-
? triesLine(d.tries)
|
|
528
|
-
: total === 1 ? msg('1 task') : msg(str`${total} tasks`)}</span>
|
|
527
|
+
<span class="meta" aria-live="polite">${this.shownLine(d)}</span>
|
|
529
528
|
</div>`;
|
|
530
529
|
}
|
|
530
|
+
|
|
531
|
+
/** While a filter is on, how many of the tab's rows it shows; the tab's badge counts them all. */
|
|
532
|
+
private shownLine(d: RunDerived): string {
|
|
533
|
+
const { viewRoute } = this;
|
|
534
|
+
const q = this.qDraft ?? viewRoute.q;
|
|
535
|
+
if (viewRoute.tab === 'journal') {
|
|
536
|
+
if (!viewRoute.kind && !q && !viewRoute.stop) return '';
|
|
537
|
+
return shownTriesLine(tryCounts(filterJournal(this.snap.state.journal, viewRoute.kind, viewRoute.stop, q)), d.tries.tries);
|
|
538
|
+
}
|
|
539
|
+
if (!viewRoute.kind && !q) return '';
|
|
540
|
+
return shownTasksLine(filterTasks(d.rows, viewRoute.kind, q).length, d.counts.total);
|
|
541
|
+
}
|
|
531
542
|
}
|
|
532
543
|
|
|
533
544
|
declare global {
|