pi-all-notification 1.0.4 → 1.0.5
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/extensions/index.ts +2 -2
- package/extensions/settle.ts +26 -0
- package/package.json +1 -1
- package/tests/settle.test.ts +33 -1
package/extensions/index.ts
CHANGED
|
@@ -18,7 +18,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
18
18
|
import { join, dirname } from "node:path";
|
|
19
19
|
import { homedir } from "node:os";
|
|
20
20
|
import { execSync } from "node:child_process";
|
|
21
|
-
import {
|
|
21
|
+
import { describeBeforeAgentStart, settleNotification } from "./settle.ts";
|
|
22
22
|
|
|
23
23
|
// ─── Types ────────────────────────────────────────────────────
|
|
24
24
|
|
|
@@ -763,7 +763,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
763
763
|
// Capture the prompt for the completion notification: `agent_settled` carries
|
|
764
764
|
// no messages, and this is the last point the prompt text is available.
|
|
765
765
|
pi.on("before_agent_start", (event, _ctx) => {
|
|
766
|
-
lastTaskDescription =
|
|
766
|
+
lastTaskDescription = describeBeforeAgentStart(event);
|
|
767
767
|
});
|
|
768
768
|
|
|
769
769
|
pi.on("agent_start", (_event, ctx) => {
|
package/extensions/settle.ts
CHANGED
|
@@ -22,6 +22,32 @@ export function describeTask(prompt: unknown): string | null {
|
|
|
22
22
|
return firstLine.length > 40 ? `${firstLine.slice(0, 37)}...` : firstLine;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Task text from `before_agent_start`.
|
|
27
|
+
*
|
|
28
|
+
* Pi 1.3 also fires this event for runs started by a custom message, where the
|
|
29
|
+
* event carries `message` instead of `prompt`.
|
|
30
|
+
*/
|
|
31
|
+
export function describeBeforeAgentStart(event: unknown): string | null {
|
|
32
|
+
if (!event || typeof event !== "object") return null;
|
|
33
|
+
const { prompt, message } = event as { prompt?: unknown; message?: unknown };
|
|
34
|
+
const fromPrompt = describeTask(prompt);
|
|
35
|
+
if (fromPrompt) return fromPrompt;
|
|
36
|
+
if (!message || typeof message !== "object") return null;
|
|
37
|
+
const content = (message as { content?: unknown }).content;
|
|
38
|
+
if (typeof content === "string") return describeTask(content);
|
|
39
|
+
if (!Array.isArray(content)) return null;
|
|
40
|
+
const text = content
|
|
41
|
+
.map((item) =>
|
|
42
|
+
item && typeof item === "object" && (item as { type?: unknown }).type === "text"
|
|
43
|
+
? (item as { text?: unknown }).text
|
|
44
|
+
: undefined,
|
|
45
|
+
)
|
|
46
|
+
.filter((item): item is string => typeof item === "string")
|
|
47
|
+
.join("\n");
|
|
48
|
+
return describeTask(text);
|
|
49
|
+
}
|
|
50
|
+
|
|
25
51
|
/**
|
|
26
52
|
* The notification for a settled run.
|
|
27
53
|
*
|
package/package.json
CHANGED
package/tests/settle.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it } from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import { describeTask, settleNotification } from "../extensions/settle.ts";
|
|
3
|
+
import { describeBeforeAgentStart, describeTask, settleNotification } from "../extensions/settle.ts";
|
|
4
4
|
|
|
5
5
|
describe("describeTask", () => {
|
|
6
6
|
it("takes the first line of the prompt", () => {
|
|
@@ -22,6 +22,38 @@ describe("describeTask", () => {
|
|
|
22
22
|
});
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
+
describe("describeBeforeAgentStart", () => {
|
|
26
|
+
it("reads the prompt from a user run", () => {
|
|
27
|
+
assert.equal(describeBeforeAgentStart({ messageType: "user", prompt: "Fix the build" }), "Fix the build");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("reads text content from a custom-message run", () => {
|
|
31
|
+
const event = {
|
|
32
|
+
messageType: "custom",
|
|
33
|
+
message: { role: "custom", content: [{ type: "text", text: "Review the release\nand tag it" }] },
|
|
34
|
+
};
|
|
35
|
+
assert.equal(describeBeforeAgentStart(event), "Review the release");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("reads string content from a custom-message run", () => {
|
|
39
|
+
const event = {
|
|
40
|
+
messageType: "custom",
|
|
41
|
+
message: { role: "custom", content: "Review the release" },
|
|
42
|
+
};
|
|
43
|
+
assert.equal(describeBeforeAgentStart(event), "Review the release");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("ignores non-text custom content", () => {
|
|
47
|
+
assert.equal(
|
|
48
|
+
describeBeforeAgentStart({
|
|
49
|
+
messageType: "custom",
|
|
50
|
+
message: { role: "custom", content: [{ type: "image", data: "..." }] },
|
|
51
|
+
}),
|
|
52
|
+
null,
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
25
57
|
describe("settleNotification", () => {
|
|
26
58
|
it("reports a natural finish as complete", () => {
|
|
27
59
|
const note = settleNotification({ aborted: false }, "pi-plugins", "Run the tests");
|