pi-advisor-flow 0.1.6 → 0.1.7
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 +1 -1
- package/src/commands.ts +7 -1
- package/src/herdr.ts +87 -0
- package/src/tools.ts +15 -9
package/package.json
CHANGED
package/src/commands.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
contextMaxCharsRef, loadConfig, saveConfig, parseArgs, splitRef,
|
|
9
9
|
} from "./config.js";
|
|
10
10
|
import { AdvisorSettingsSelector, SearchableModelSelector, type AdvisorSettings, type ContextPreset } from "./ui.js";
|
|
11
|
+
import { herdrAdvisorActivity } from "./herdr.js";
|
|
11
12
|
import { adviceForDisplay, consult, renderAdvisorCallBox, resolveAdvisorRequest } from "./tools.js";
|
|
12
13
|
|
|
13
14
|
const EFFORT_LEVELS = ["Default (Model Default)", "off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
@@ -44,6 +45,7 @@ export const registerCommands = (pi: ExtensionAPI, dependencies: { consult?: typ
|
|
|
44
45
|
pi.on("session_shutdown", () => {
|
|
45
46
|
for (const controller of manualConsultations) controller.abort();
|
|
46
47
|
manualConsultations.clear();
|
|
48
|
+
herdrAdvisorActivity.clear();
|
|
47
49
|
});
|
|
48
50
|
|
|
49
51
|
pi.registerCommand("advisor-manual", {
|
|
@@ -58,6 +60,7 @@ export const registerCommands = (pi: ExtensionAPI, dependencies: { consult?: typ
|
|
|
58
60
|
manualConsultations.add(controller);
|
|
59
61
|
pi.appendEntry?.("advisor-manual-call", { question });
|
|
60
62
|
|
|
63
|
+
herdrAdvisorActivity.start();
|
|
61
64
|
void requestAdvisor(ctx, question, controller.signal)
|
|
62
65
|
.then(({ advice }) => {
|
|
63
66
|
if (controller.signal.aborted) return;
|
|
@@ -78,7 +81,10 @@ export const registerCommands = (pi: ExtensionAPI, dependencies: { consult?: typ
|
|
|
78
81
|
const message = error instanceof Error ? error.message : String(error);
|
|
79
82
|
if (ctx.hasUI) ctx.ui.notify(`Advisor consultation failed: ${message}`, "error");
|
|
80
83
|
})
|
|
81
|
-
.finally(() =>
|
|
84
|
+
.finally(() => {
|
|
85
|
+
manualConsultations.delete(controller);
|
|
86
|
+
herdrAdvisorActivity.finish();
|
|
87
|
+
});
|
|
82
88
|
},
|
|
83
89
|
});
|
|
84
90
|
|
package/src/herdr.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import net from "node:net";
|
|
2
|
+
|
|
3
|
+
const SOURCE = "pi-advisor:advisor-activity";
|
|
4
|
+
const HERDR_PI_SOURCE = "herdr:pi";
|
|
5
|
+
let sequence = Date.now() * 1_000;
|
|
6
|
+
|
|
7
|
+
const nextSequence = () => ++sequence;
|
|
8
|
+
|
|
9
|
+
type HerdrRequest = {
|
|
10
|
+
id: string;
|
|
11
|
+
method: "pane.report_metadata";
|
|
12
|
+
params: {
|
|
13
|
+
pane_id: string;
|
|
14
|
+
source: string;
|
|
15
|
+
agent: "pi";
|
|
16
|
+
applies_to_source: string;
|
|
17
|
+
state_labels?: { working: string };
|
|
18
|
+
clear_state_labels?: true;
|
|
19
|
+
seq: number;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type Report = (request: HerdrRequest) => void;
|
|
24
|
+
|
|
25
|
+
const sendToHerdr: Report = (request) => {
|
|
26
|
+
if (process.env.HERDR_ENV !== "1") return;
|
|
27
|
+
const paneId = process.env.HERDR_PANE_ID;
|
|
28
|
+
const socketPath = process.env.HERDR_SOCKET_PATH;
|
|
29
|
+
if (!paneId || !socketPath) return;
|
|
30
|
+
|
|
31
|
+
const endpoint = process.platform === "win32" ? `\\\\.\\pipe\\${socketPath}` : socketPath;
|
|
32
|
+
const socket = net.createConnection(endpoint);
|
|
33
|
+
const timeout = setTimeout(() => socket.destroy(), 500);
|
|
34
|
+
timeout.unref?.();
|
|
35
|
+
socket.once("connect", () => socket.write(`${JSON.stringify(request)}\n`));
|
|
36
|
+
socket.once("data", () => socket.destroy());
|
|
37
|
+
socket.once("error", () => socket.destroy());
|
|
38
|
+
socket.once("close", () => clearTimeout(timeout));
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export class HerdrAdvisorActivity {
|
|
42
|
+
#activeConsultations = 0;
|
|
43
|
+
|
|
44
|
+
constructor(private readonly report: Report = sendToHerdr) {}
|
|
45
|
+
|
|
46
|
+
start() {
|
|
47
|
+
this.#activeConsultations += 1;
|
|
48
|
+
if (this.#activeConsultations === 1) this.safeReport(false);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
finish() {
|
|
52
|
+
if (this.#activeConsultations === 0) return;
|
|
53
|
+
this.#activeConsultations -= 1;
|
|
54
|
+
if (this.#activeConsultations === 0) this.safeReport(true);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
clear() {
|
|
58
|
+
if (this.#activeConsultations === 0) return;
|
|
59
|
+
this.#activeConsultations = 0;
|
|
60
|
+
this.safeReport(true);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private safeReport(clear: boolean) {
|
|
64
|
+
try {
|
|
65
|
+
this.report(this.request(clear));
|
|
66
|
+
} catch {
|
|
67
|
+
// Herdr is optional; an unavailable integration must never affect advice.
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private request(clear: boolean): HerdrRequest {
|
|
72
|
+
return {
|
|
73
|
+
id: `${SOURCE}:${nextSequence()}`,
|
|
74
|
+
method: "pane.report_metadata",
|
|
75
|
+
params: {
|
|
76
|
+
pane_id: process.env.HERDR_PANE_ID ?? "",
|
|
77
|
+
source: SOURCE,
|
|
78
|
+
agent: "pi",
|
|
79
|
+
applies_to_source: HERDR_PI_SOURCE,
|
|
80
|
+
...(clear ? { clear_state_labels: true } : { state_labels: { working: "seeking advice" } }),
|
|
81
|
+
seq: nextSequence(),
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const herdrAdvisorActivity = new HerdrAdvisorActivity();
|
package/src/tools.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
advisorRef, advisorEffortRef, contextMaxCharsRef, loadConfig, splitRef,
|
|
8
8
|
} from "./config.js";
|
|
9
9
|
import { recentConversation, textFrom } from "./conversation.js";
|
|
10
|
+
import { herdrAdvisorActivity } from "./herdr.js";
|
|
10
11
|
|
|
11
12
|
export const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
12
13
|
export const resolveAdvisorRequest = (question?: string) => question?.trim() || undefined;
|
|
@@ -159,16 +160,21 @@ export const registerAdvisorTool = (pi: ExtensionAPI) => {
|
|
|
159
160
|
},
|
|
160
161
|
async execute(_id, params, signal, onUpdate, ctx) {
|
|
161
162
|
const question = resolveAdvisorRequest(params.question);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
163
|
+
herdrAdvisorActivity.start();
|
|
164
|
+
try {
|
|
165
|
+
const { advice, thinkingText } = await consult(ctx, question, signal, (t, tx) => {
|
|
166
|
+
onUpdate?.({
|
|
167
|
+
content: [{ type: "text", text: tx }],
|
|
168
|
+
details: { thinking: t, text: tx, advisor: advisorRef, question },
|
|
169
|
+
});
|
|
166
170
|
});
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
171
|
+
return {
|
|
172
|
+
content: [{ type: "text", text: `Advisor (${advisorRef})\n\n${advice}` }],
|
|
173
|
+
details: { thinking: thinkingText, text: advice, advisor: advisorRef, question },
|
|
174
|
+
};
|
|
175
|
+
} finally {
|
|
176
|
+
herdrAdvisorActivity.finish();
|
|
177
|
+
}
|
|
172
178
|
},
|
|
173
179
|
});
|
|
174
180
|
};
|