portable-agent-layer 0.83.0 → 0.84.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/package.json
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -110,6 +110,16 @@ function checkCopilot(): ToolCheck {
|
|
|
110
110
|
return cli;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* The Cursor CLI installs `cursor-agent` (and `agent`) and no `cursor` command;
|
|
115
|
+
* `cursor` is the editor's shell command. Both read ~/.cursor, so either counts.
|
|
116
|
+
*/
|
|
117
|
+
function checkCursor(): ToolCheck {
|
|
118
|
+
const cli = checkTool("cursor-agent");
|
|
119
|
+
if (cli.available) return cli;
|
|
120
|
+
return checkTool("cursor");
|
|
121
|
+
}
|
|
122
|
+
|
|
113
123
|
async function session(sessionArgs: string[]) {
|
|
114
124
|
const agent = findSessionAgent();
|
|
115
125
|
if (!agent) {
|
|
@@ -759,7 +769,7 @@ function doctor(silent = false): DoctorResult {
|
|
|
759
769
|
const bun = { name: "bun", available: true, version: Bun.version };
|
|
760
770
|
const claude = checkTool("claude");
|
|
761
771
|
const opencode = checkTool("opencode");
|
|
762
|
-
const cursor =
|
|
772
|
+
const cursor = checkCursor();
|
|
763
773
|
const copilot = checkCopilot();
|
|
764
774
|
const codex = checkTool("codex");
|
|
765
775
|
const rtk = checkTool("rtk");
|
|
@@ -15,7 +15,8 @@ const HELP = `
|
|
|
15
15
|
PAL Interaction report
|
|
16
16
|
|
|
17
17
|
Reads the measured turns in memory/signals/interaction/ (features only, no
|
|
18
|
-
text) and prints turns, channels, reactions, the hints sent,
|
|
18
|
+
text) and prints turns, channels, reactions, the hints sent, per agent the
|
|
19
|
+
turns, replies filed and hints sent, and for each
|
|
19
20
|
label (short, long, fast, skimming, friction) how the replies written while
|
|
20
21
|
it was active compare with the replies written while none was.
|
|
21
22
|
|
|
@@ -22,10 +22,17 @@ interface ReplyStats {
|
|
|
22
22
|
correctedShare: number;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
interface AgentCounts {
|
|
26
|
+
turns: number;
|
|
27
|
+
replies: number;
|
|
28
|
+
hints: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
25
31
|
export interface InteractionSummary {
|
|
26
32
|
turns: number;
|
|
27
33
|
sessions: number;
|
|
28
34
|
channels: Record<string, number>;
|
|
35
|
+
agents: Record<string, AgentCounts>;
|
|
29
36
|
reactions: Record<string, number>;
|
|
30
37
|
hints: Record<string, number>;
|
|
31
38
|
unlogged: number;
|
|
@@ -70,6 +77,20 @@ function repliesUnderMood(events: TurnEvent[]): ReplyUnderMood[] {
|
|
|
70
77
|
return replies;
|
|
71
78
|
}
|
|
72
79
|
|
|
80
|
+
/** A turn carries the reply that answered the turn before it, so a filed reply shows up there. */
|
|
81
|
+
function byAgent(events: TurnEvent[]): Record<string, AgentCounts> {
|
|
82
|
+
const agents: Record<string, AgentCounts> = {};
|
|
83
|
+
for (const e of events) {
|
|
84
|
+
const agent = e.runtime ?? "unknown";
|
|
85
|
+
const counts = agents[agent] ?? { turns: 0, replies: 0, hints: 0 };
|
|
86
|
+
agents[agent] = counts;
|
|
87
|
+
counts.turns++;
|
|
88
|
+
if (e.reply) counts.replies++;
|
|
89
|
+
if (e.hinted) counts.hints++;
|
|
90
|
+
}
|
|
91
|
+
return agents;
|
|
92
|
+
}
|
|
93
|
+
|
|
73
94
|
export function summarize(events: TurnEvent[]): InteractionSummary {
|
|
74
95
|
const replies = repliesUnderMood(events);
|
|
75
96
|
const hinted = events.filter((e) => e.hinted);
|
|
@@ -77,6 +98,7 @@ export function summarize(events: TurnEvent[]): InteractionSummary {
|
|
|
77
98
|
turns: events.length,
|
|
78
99
|
sessions: new Set(events.map((e) => e.session)).size,
|
|
79
100
|
channels: tally(events.map((e) => e.channel ?? "unknown")),
|
|
101
|
+
agents: byAgent(events),
|
|
80
102
|
reactions: tally(events.flatMap((e) => (e.reaction ? [e.reaction] : []))),
|
|
81
103
|
hints: tally(hinted.map((e) => e.mood || "back to usual")),
|
|
82
104
|
unlogged: events.filter((e) => e.mood === undefined).length,
|
|
@@ -119,8 +141,20 @@ function labelLine(label: string, s: ReplyStats, usual: ReplyStats): string {
|
|
|
119
141
|
].join(" · ");
|
|
120
142
|
}
|
|
121
143
|
|
|
122
|
-
function plural(n: number, noun: string): string {
|
|
123
|
-
return `${n} ${
|
|
144
|
+
function plural(n: number, noun: string, nouns = `${noun}s`): string {
|
|
145
|
+
return `${n} ${n === 1 ? noun : nouns}`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function agentLines(agents: Record<string, AgentCounts>): string[] {
|
|
149
|
+
return Object.entries(agents)
|
|
150
|
+
.sort(([, a], [, b]) => b.turns - a.turns)
|
|
151
|
+
.map(([agent, c]) =>
|
|
152
|
+
[
|
|
153
|
+
` ${agent.padEnd(9)} ${plural(c.turns, "turn")}`,
|
|
154
|
+
`${plural(c.replies, "reply", "replies")} filed`,
|
|
155
|
+
`${plural(c.hints, "hint")} sent`,
|
|
156
|
+
].join(" · ")
|
|
157
|
+
);
|
|
124
158
|
}
|
|
125
159
|
|
|
126
160
|
export function reportLines(summary: InteractionSummary, days: number): string[] {
|
|
@@ -132,6 +166,9 @@ export function reportLines(summary: InteractionSummary, days: number): string[]
|
|
|
132
166
|
`Reactions: ${shares(summary.reactions)}`,
|
|
133
167
|
`Hints sent: ${counts(summary.hints)}`,
|
|
134
168
|
"",
|
|
169
|
+
"By agent:",
|
|
170
|
+
...agentLines(summary.agents),
|
|
171
|
+
"",
|
|
135
172
|
"Replies written while a label was active, against replies while none was:",
|
|
136
173
|
...LABELS.map((label) => labelLine(label, summary.byLabel[label], summary.usual)),
|
|
137
174
|
];
|