@haywoodmarx/agent-pager 0.2.0 → 0.2.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 +2 -2
- package/dist/src/broker/broker.d.ts +21 -1
- package/dist/src/broker/broker.js +101 -11
- package/dist/src/broker/operator-projection.d.ts +22 -0
- package/dist/src/broker/operator-projection.js +40 -0
- package/dist/src/broker/protocol.d.ts +1 -1
- package/dist/src/broker/protocol.js +1 -1
- package/dist/src/broker/schema.d.ts +2 -2
- package/dist/src/broker/schema.js +12 -3
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/operator/commands.d.ts +2 -0
- package/dist/src/operator/commands.js +57 -21
- package/dist/src/operator/protocol.d.ts +32 -0
- package/dist/src/operator/protocol.js +9 -0
- package/dist/src/operator/transport.js +10 -5
- package/dist/src/operator/updates.js +7 -1
- package/dist/src/operator/validation.js +35 -1
- package/dist/src/tui/agent-tree.d.ts +8 -5
- package/dist/src/tui/agent-tree.js +193 -20
- package/dist/src/tui/app.js +6 -2
- package/dist/src/tui/message-views.js +4 -3
- package/dist/src/tui/model.d.ts +25 -1
- package/dist/src/tui/model.js +33 -9
- package/dist/src/tui/presentation.d.ts +11 -2
- package/dist/src/tui/presentation.js +26 -4
- package/package.json +1 -1
package/dist/src/tui/model.js
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
|
-
import { archivedOperatorRepositoryIds, selectOperatorAgentHealth, } from "../operator/agent-projection.js";
|
|
1
|
+
import { archivedOperatorRepositoryIds, isOperatorAgentArchived, selectOperatorAgentHealth, } from "../operator/agent-projection.js";
|
|
2
2
|
import { OPERATOR_PROTOCOL_VERSION, } from "../operator/protocol.js";
|
|
3
3
|
import { classifyOperatorEvent, validateOperatorSnapshot } from "../operator/validation.js";
|
|
4
4
|
import { isTuiExpirable } from "../operator/agent-projection.js";
|
|
5
|
+
/**
|
|
6
|
+
* List the agents a purge confirmation still deletes.
|
|
7
|
+
* @param target - What the confirmation names.
|
|
8
|
+
* @param agents - Agents the current projection holds.
|
|
9
|
+
* @returns - The named agent while it is projected, or those the archive section held when the
|
|
10
|
+
* confirmation opened that are still archived in that workspace.
|
|
11
|
+
*/
|
|
12
|
+
export function selectTuiPurgeableAgents(target, agents) {
|
|
13
|
+
if (target.kind === "agent")
|
|
14
|
+
return agents.filter((agent) => agent.id === target.agentId);
|
|
15
|
+
const named = new Set(target.agentIds);
|
|
16
|
+
return agents.filter((agent) => named.has(agent.id) && agent.repository.repositoryId === target.repositoryId && isOperatorAgentArchived(agent));
|
|
17
|
+
}
|
|
5
18
|
/* eslint-enable jsdoc/require-jsdoc -- The state field declarations end here. */
|
|
6
19
|
/** Entries the diagnostics log keeps before discarding its oldest. */
|
|
7
20
|
const TUI_DIAGNOSTIC_LIMIT = 200;
|
|
@@ -657,14 +670,19 @@ function reconcileView(view, snapshot, previous) {
|
|
|
657
670
|
const messageIds = acceptedIds(snapshot.traffic);
|
|
658
671
|
const trafficIds = new Set(snapshot.traffic.map((traffic) => traffic.trafficId));
|
|
659
672
|
const hiddenRepositories = new Set([...view.hiddenRepositories].filter((id) => repositoryIds.has(id)));
|
|
660
|
-
|
|
673
|
+
// A repository with no agent keeps its view state but has no row to select.
|
|
674
|
+
const occupied = new Set(snapshot.agents.map((agent) => agent.repository.repositoryId));
|
|
675
|
+
const sections = new Set(snapshot.agents.filter(isOperatorAgentArchived).map((agent) => agent.repository.repositoryId));
|
|
676
|
+
const selection = selectionSurviving(view.selection, occupied, sections, agentIds, new Set([...hiddenRepositories].filter((id) => occupied.has(id))));
|
|
661
677
|
const trafficId = view.trafficId !== null && !trafficIds.has(view.trafficId) ? null : view.trafficId;
|
|
662
678
|
return {
|
|
663
679
|
...view,
|
|
664
680
|
selection,
|
|
665
681
|
trafficId,
|
|
666
|
-
overlay: reconcileOverlay(view.overlay,
|
|
667
|
-
|
|
682
|
+
overlay: reconcileOverlay(view.overlay, snapshot.agents, agentIds, occupied, sections, messageIds, expirableIds(snapshot.traffic)),
|
|
683
|
+
// An empty workspace's collapse is dropped, so one that was collapsed for being archived opens for
|
|
684
|
+
// the agent that next starts in it.
|
|
685
|
+
collapsedRepositories: new Set([...collapsedRepositories].filter((id) => occupied.has(id))),
|
|
668
686
|
hiddenRepositories,
|
|
669
687
|
archivedSections: new Map([...view.archivedSections].filter(([id]) => repositoryIds.has(id))),
|
|
670
688
|
};
|
|
@@ -672,16 +690,18 @@ function reconcileView(view, snapshot, previous) {
|
|
|
672
690
|
/**
|
|
673
691
|
* Keep a tree selection only while the row it names can still be shown.
|
|
674
692
|
* @param selection - Selection held before the projection changed.
|
|
675
|
-
* @param repositoryIds - Repositories the new projection
|
|
693
|
+
* @param repositoryIds - Repositories the new projection shows a row for.
|
|
694
|
+
* @param archivedSections - Repositories the new projection shows an archive section for.
|
|
676
695
|
* @param agentIds - Agents the new projection holds.
|
|
677
|
-
* @param hiddenRepositories - Hidden repositories
|
|
696
|
+
* @param hiddenRepositories - Hidden repositories the new projection shows; the hidden section exists only while any do.
|
|
678
697
|
* @returns The same selection, or null when its row is gone.
|
|
679
698
|
*/
|
|
680
|
-
function selectionSurviving(selection, repositoryIds, agentIds, hiddenRepositories) {
|
|
699
|
+
function selectionSurviving(selection, repositoryIds, archivedSections, agentIds, hiddenRepositories) {
|
|
681
700
|
switch (selection?.kind) {
|
|
682
701
|
case "workspace":
|
|
683
|
-
case "archived":
|
|
684
702
|
return repositoryIds.has(selection.repositoryId) ? selection : null;
|
|
703
|
+
case "archived":
|
|
704
|
+
return archivedSections.has(selection.repositoryId) ? selection : null;
|
|
685
705
|
case "agent":
|
|
686
706
|
return agentIds.has(selection.agentId) ? selection : null;
|
|
687
707
|
case "hidden":
|
|
@@ -693,13 +713,15 @@ function selectionSurviving(selection, repositoryIds, agentIds, hiddenRepositori
|
|
|
693
713
|
function expirableIds(traffic) {
|
|
694
714
|
return new Set(traffic.flatMap((entry) => (entry.kind === "accepted_delivery" && isTuiExpirable(entry) ? [entry.messageId] : [])));
|
|
695
715
|
}
|
|
696
|
-
function reconcileOverlay(overlay,
|
|
716
|
+
function reconcileOverlay(overlay, agents, agentIds, repositoryIds, archivedSections, messageIds, expirable) {
|
|
697
717
|
const closed = { kind: "none" };
|
|
698
718
|
switch (overlay.kind) {
|
|
699
719
|
case "agent_identity":
|
|
700
720
|
return agentIds.has(overlay.agentId) ? overlay : closed;
|
|
701
721
|
case "archive_confirm":
|
|
702
722
|
return agentIds.has(overlay.agentId) ? overlay : closed;
|
|
723
|
+
case "purge_confirm":
|
|
724
|
+
return selectTuiPurgeableAgents(overlay.target, agents).length > 0 ? overlay : closed;
|
|
703
725
|
case "full_message":
|
|
704
726
|
return messageIds.has(overlay.messageId) ? overlay : closed;
|
|
705
727
|
case "expire_confirm":
|
|
@@ -710,6 +732,8 @@ function reconcileOverlay(overlay, repositoryIds, agentIds, messageIds, expirabl
|
|
|
710
732
|
return agentIds.has(overlay.agentId) ? overlay : closed;
|
|
711
733
|
if (overlay.target === "message")
|
|
712
734
|
return messageIds.has(overlay.messageId) ? overlay : closed;
|
|
735
|
+
if (overlay.target === "archived")
|
|
736
|
+
return archivedSections.has(overlay.repositoryId) ? overlay : closed;
|
|
713
737
|
return repositoryIds.has(overlay.repositoryId) ? overlay : closed;
|
|
714
738
|
case "none":
|
|
715
739
|
case "actions":
|
|
@@ -119,12 +119,21 @@ export declare function formatDiagnostic(diagnostic: OperatorDiagnostic, width:
|
|
|
119
119
|
* An answer is admission, not the resulting state change, so an accepted command is worded as
|
|
120
120
|
* accepted. A command that got no answer at all is worded as unknown, because the broker may have
|
|
121
121
|
* applied it.
|
|
122
|
-
* @param
|
|
122
|
+
* @param target - What the command acted on, as `describeCommandTarget` named it when the command was submitted.
|
|
123
123
|
* @param command - Command the operator submitted.
|
|
124
124
|
* @param result - The broker's admission answer, or null when none came back.
|
|
125
125
|
* @returns Severity and content-free summary for the log row.
|
|
126
126
|
*/
|
|
127
|
-
export declare function describeCommandOutcome(
|
|
127
|
+
export declare function describeCommandOutcome(target: string, command: OperatorCommand, result: OperatorCommandResult | null): Pick<OperatorDiagnostic, "severity" | "summary">;
|
|
128
|
+
/**
|
|
129
|
+
* Name what one operator command acts on, in the words the diagnostics log uses.
|
|
130
|
+
*
|
|
131
|
+
* Read at submission: a purge removes its agents from the projection before its answer arrives.
|
|
132
|
+
* @param state - Current projection, which names the agents a command targets while they remain in it.
|
|
133
|
+
* @param command - Command the operator is submitting.
|
|
134
|
+
* @returns - The message id, the agent handle, or the number of agents a multi-agent purge names.
|
|
135
|
+
*/
|
|
136
|
+
export declare function describeCommandTarget(state: TuiOperatorModelState, command: OperatorCommand): string;
|
|
128
137
|
/**
|
|
129
138
|
* Select the colour role one diagnostic severity carries.
|
|
130
139
|
* @param severity - Attention the condition asks for.
|
|
@@ -135,20 +135,42 @@ export function formatDiagnostic(diagnostic, width) {
|
|
|
135
135
|
* An answer is admission, not the resulting state change, so an accepted command is worded as
|
|
136
136
|
* accepted. A command that got no answer at all is worded as unknown, because the broker may have
|
|
137
137
|
* applied it.
|
|
138
|
-
* @param
|
|
138
|
+
* @param target - What the command acted on, as `describeCommandTarget` named it when the command was submitted.
|
|
139
139
|
* @param command - Command the operator submitted.
|
|
140
140
|
* @param result - The broker's admission answer, or null when none came back.
|
|
141
141
|
* @returns Severity and content-free summary for the log row.
|
|
142
142
|
*/
|
|
143
|
-
export function describeCommandOutcome(
|
|
144
|
-
const verb = { ping_agent: "ping", archive_agent: "archive", expire_message: "expire" }[command.type];
|
|
143
|
+
export function describeCommandOutcome(target, command, result) {
|
|
144
|
+
const verb = { ping_agent: "ping", archive_agent: "archive", expire_message: "expire", purge_agents: "purge" }[command.type];
|
|
145
145
|
if (result === null)
|
|
146
146
|
return { severity: "error", summary: `${verb} outcome unknown: no answer came back from the broker` };
|
|
147
147
|
if (result.status === "rejected")
|
|
148
148
|
return { severity: "warning", summary: `${verb} refused: ${result.reason}` };
|
|
149
|
-
const target = command.type === "expire_message" ? command.messageId : agentHandle(state, command.targetAgentId);
|
|
150
149
|
return { severity: "info", summary: `${verb} accepted for ${target}` };
|
|
151
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Name what one operator command acts on, in the words the diagnostics log uses.
|
|
153
|
+
*
|
|
154
|
+
* Read at submission: a purge removes its agents from the projection before its answer arrives.
|
|
155
|
+
* @param state - Current projection, which names the agents a command targets while they remain in it.
|
|
156
|
+
* @param command - Command the operator is submitting.
|
|
157
|
+
* @returns - The message id, the agent handle, or the number of agents a multi-agent purge names.
|
|
158
|
+
*/
|
|
159
|
+
export function describeCommandTarget(state, command) {
|
|
160
|
+
switch (command.type) {
|
|
161
|
+
case "expire_message":
|
|
162
|
+
return command.messageId;
|
|
163
|
+
case "ping_agent":
|
|
164
|
+
case "archive_agent":
|
|
165
|
+
return agentHandle(state, command.targetAgentId);
|
|
166
|
+
case "purge_agents": {
|
|
167
|
+
const [only] = command.targetAgentIds;
|
|
168
|
+
return command.targetAgentIds.length === 1 && only !== undefined
|
|
169
|
+
? agentHandle(state, only)
|
|
170
|
+
: `${String(command.targetAgentIds.length)} agents`;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
152
174
|
/**
|
|
153
175
|
* Select the colour role one diagnostic severity carries.
|
|
154
176
|
* @param severity - Attention the condition asks for.
|