pi-advisor-flow 0.10.0 → 0.11.0
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/CHANGELOG.md +10 -1
- package/README.md +31 -0
- package/dist/index.js +70 -31
- package/package.json +2 -1
- package/src/tools/advisor-output.ts +28 -0
- package/src/tools/register-ask-advisor.ts +25 -9
- package/src/tools/register-lifecycle.ts +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,16 @@ All notable changes to this project are documented here.
|
|
|
4
4
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0/).
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 0.11.0 - 2026-10-03
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Native Pi Codemode composition for `ask_advisor`: scripts receive structured advice, IDs, normalized usage, and existing skip metadata, while interactive responses remain unchanged. Documented deterministic-check composition and explicit draft disclosure limits.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Advisor invocation guidelines no longer replace the whole system prompt, so prompt sections from other extensions, such as the list of MCP servers, still reach the model.
|
|
16
|
+
- Braces Vulnerability patched (CVE-2026-93687)
|
|
8
17
|
|
|
9
18
|
## 0.10.0 - 2026-10-02
|
|
10
19
|
|
package/README.md
CHANGED
|
@@ -89,6 +89,37 @@ In the Settings, enable Simple Mode for a quick start.
|
|
|
89
89
|
|
|
90
90
|
Unknown fields in `advisor.json` are preserved for forward compatibility and reported as non-blocking warnings. Invalid recognized values fail their own Advisor call with a clear message instead of blocking every tool call.
|
|
91
91
|
|
|
92
|
+
## Pi Codemode
|
|
93
|
+
|
|
94
|
+
With Pi Codemode enabled and the Advisor flow active, call the existing tool through `tools.ask_advisor`; no separate review tool or workflow is needed:
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
const commands = ["bun test", "bun run typecheck"];
|
|
98
|
+
const checks = await Promise.all(
|
|
99
|
+
commands.map(async (command) => {
|
|
100
|
+
const result = await tools.bash({ command });
|
|
101
|
+
return {
|
|
102
|
+
command,
|
|
103
|
+
exit_code: result.exit_code,
|
|
104
|
+
truncated: result.truncated,
|
|
105
|
+
};
|
|
106
|
+
})
|
|
107
|
+
);
|
|
108
|
+
return await tools.ask_advisor({
|
|
109
|
+
draft: JSON.stringify({
|
|
110
|
+
checks,
|
|
111
|
+
remainingRisk: "Runtime behavior needs review.",
|
|
112
|
+
}),
|
|
113
|
+
gitContext: "full",
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Gather and filter deterministic results before paying for Advisor reasoning. Nested results are not transcript entries, so they are not automatically available to reconstructed Advisor context. Use the existing `draft` for permitted, concise summaries (8 KiB after optional redaction); these remain untrusted Executor claims, not independently verified evidence. `question` can focus a specific decision; omit it for general reviews. Use `gitContext` for patches so the user's configured disclosure ceiling applies, rather than copying a diff into the draft.
|
|
118
|
+
|
|
119
|
+
Codemode receives `{ text, adviceId?, advisor?, followUp?, usage?, jev?, skipReason? }`. `text` preserves Advisor Markdown or the existing skip notice; `usage` is the same normalized snapshot shown in response details. Skipped calls have no new `adviceId`. Provider failures and blocked calls reject. Regular consultations never become loop-gate decisions. Interactive responses and usage accounting are unchanged.
|
|
120
|
+
|
|
121
|
+
Draft text is explicit disclosure: it does **not** inherit the policies of the tools that produced it. Do not copy excluded tool output, secrets, or unconsented file bodies into `draft` or `question`. Jev may also receive the draft when screening is enabled. See [Privacy and data handling](docs/privacy.md).
|
|
122
|
+
|
|
92
123
|
## Usage and accounting
|
|
93
124
|
|
|
94
125
|
Advisor responses show provider-reported input, output, cache, and cost details when available. Successful `ask_advisor` calls also carry normalized usage into Pi's built-in `/cost` totals. Manual consultations and automatic gates keep their own session-local accounting instead, so nothing is double-counted. Missing or partial provider usage is shown as unavailable rather than fabricated as zero. `/advisor-settings` controls both the per-response details and the optional cumulative footer independently. Configure `advisorFallbackModel` or choose **Fallback Advisor model** in the model/settings pickers to retry one failed primary request; the final response is labelled with the model that answered, and both failures are shown together.
|
package/dist/index.js
CHANGED
|
@@ -8399,7 +8399,32 @@ var registerJevTurnGate = (on, registration) => {
|
|
|
8399
8399
|
};
|
|
8400
8400
|
|
|
8401
8401
|
// src/tools/register-ask-advisor.ts
|
|
8402
|
+
import { Type as Type2 } from "typebox";
|
|
8403
|
+
|
|
8404
|
+
// src/tools/advisor-output.ts
|
|
8402
8405
|
import { Type } from "typebox";
|
|
8406
|
+
var advisorOutputSchema = Type.Object({
|
|
8407
|
+
adviceId: Type.Optional(Type.String()),
|
|
8408
|
+
advisor: Type.Optional(Type.String()),
|
|
8409
|
+
followUp: Type.Optional(Type.Boolean()),
|
|
8410
|
+
jev: Type.Optional(Type.Object({
|
|
8411
|
+
kind: Type.Union([Type.Literal("screened"), Type.Literal("repeat")]),
|
|
8412
|
+
reason: Type.String(),
|
|
8413
|
+
skipped: Type.Boolean()
|
|
8414
|
+
})),
|
|
8415
|
+
skipReason: Type.Optional(Type.String()),
|
|
8416
|
+
text: Type.String({
|
|
8417
|
+
description: "Advisor Markdown or consultation skip notice."
|
|
8418
|
+
}),
|
|
8419
|
+
usage: Type.Optional(Type.Object({
|
|
8420
|
+
cacheRead: Type.Optional(Type.Number()),
|
|
8421
|
+
cacheWrite: Type.Optional(Type.Number()),
|
|
8422
|
+
cost: Type.Optional(Type.Number()),
|
|
8423
|
+
input: Type.Optional(Type.Number()),
|
|
8424
|
+
output: Type.Optional(Type.Number()),
|
|
8425
|
+
totalTokens: Type.Optional(Type.Number())
|
|
8426
|
+
}))
|
|
8427
|
+
});
|
|
8403
8428
|
|
|
8404
8429
|
// src/tools/render-advisor-result.ts
|
|
8405
8430
|
import { getMarkdownTheme as getMarkdownTheme4 } from "@earendil-works/pi-coding-agent";
|
|
@@ -8580,7 +8605,8 @@ var skippedSameModelResult = (id, notice, reservedCalls, session) => {
|
|
|
8580
8605
|
details: {
|
|
8581
8606
|
skipReason: notice,
|
|
8582
8607
|
text: notice
|
|
8583
|
-
}
|
|
8608
|
+
},
|
|
8609
|
+
structuredContent: { skipReason: notice, text: notice }
|
|
8584
8610
|
};
|
|
8585
8611
|
};
|
|
8586
8612
|
var claimTrackedHandoff = (session, includeTrackedFiles) => {
|
|
@@ -8603,7 +8629,7 @@ var registerAskAdvisorTool = ({
|
|
|
8603
8629
|
session
|
|
8604
8630
|
}) => {
|
|
8605
8631
|
pi.registerTool({
|
|
8606
|
-
description: "Consult the on-demand Advisor model for strategic guidance. Call with an empty object for a contextual review; attach an optional draft for concrete plan or completion review. Use followUpTo with a new question to continue one cached consultation without rebuilding its redacted context. If the Advisor explicitly names a missing file, you may make a sequential fresh consultation with includeTrackedFiles when enabled and relevant.",
|
|
8632
|
+
description: "Consult the on-demand Advisor model for strategic guidance. Call with an empty object for a contextual review; attach an optional draft for concrete plan or completion review. Use followUpTo with a new question to continue one cached consultation without rebuilding its redacted context. If the Advisor explicitly names a missing file, you may make a sequential fresh consultation with includeTrackedFiles when enabled and relevant. In Pi Codemode, gather and filter deterministic tool results first, then call tools.ask_advisor. Nested results are not automatically reconstructed: pass only permitted, concise summaries in draft (untrusted, capped at 8 KiB, not independently verified). Draft does not inherit source-tool disclosure policies; use gitContext for patches within the user's allowance.",
|
|
8607
8633
|
async execute(_id, params, signal, onUpdate, ctx) {
|
|
8608
8634
|
let followUp;
|
|
8609
8635
|
try {
|
|
@@ -8648,16 +8674,18 @@ var registerAskAdvisorTool = ({
|
|
|
8648
8674
|
const skipText = screeningSkipText(screening);
|
|
8649
8675
|
session.releaseCall(_id);
|
|
8650
8676
|
reservedCalls.delete(_id);
|
|
8677
|
+
const skipped = {
|
|
8678
|
+
jev: {
|
|
8679
|
+
kind: screening.kind,
|
|
8680
|
+
reason: screening.reason,
|
|
8681
|
+
skipped: true
|
|
8682
|
+
},
|
|
8683
|
+
text: skipText
|
|
8684
|
+
};
|
|
8651
8685
|
return {
|
|
8652
8686
|
content: [{ text: skipText, type: "text" }],
|
|
8653
|
-
details:
|
|
8654
|
-
|
|
8655
|
-
kind: screening.kind,
|
|
8656
|
-
reason: screening.reason,
|
|
8657
|
-
skipped: true
|
|
8658
|
-
},
|
|
8659
|
-
text: skipText
|
|
8660
|
-
}
|
|
8687
|
+
details: skipped,
|
|
8688
|
+
structuredContent: skipped
|
|
8661
8689
|
};
|
|
8662
8690
|
}
|
|
8663
8691
|
if (sameModelAdvisorDisabled(ctx, ctx.model, followUp?.payload.model)) {
|
|
@@ -8745,6 +8773,15 @@ var registerAskAdvisorTool = ({
|
|
|
8745
8773
|
if (usage) {
|
|
8746
8774
|
details.usage = usage;
|
|
8747
8775
|
}
|
|
8776
|
+
const structuredContent = {
|
|
8777
|
+
adviceId: result.adviceId,
|
|
8778
|
+
advisor: result.model,
|
|
8779
|
+
followUp: Boolean(result.followUp),
|
|
8780
|
+
text: result.markdown
|
|
8781
|
+
};
|
|
8782
|
+
if (usage) {
|
|
8783
|
+
structuredContent.usage = usage;
|
|
8784
|
+
}
|
|
8748
8785
|
const response = {
|
|
8749
8786
|
content: [
|
|
8750
8787
|
{
|
|
@@ -8754,7 +8791,8 @@ ${result.markdown}`,
|
|
|
8754
8791
|
type: "text"
|
|
8755
8792
|
}
|
|
8756
8793
|
],
|
|
8757
|
-
details
|
|
8794
|
+
details,
|
|
8795
|
+
structuredContent
|
|
8758
8796
|
};
|
|
8759
8797
|
if (piUsage) {
|
|
8760
8798
|
response.usage = piUsage;
|
|
@@ -8783,26 +8821,27 @@ ${result.markdown}`,
|
|
|
8783
8821
|
},
|
|
8784
8822
|
label: "Ask Advisor",
|
|
8785
8823
|
name: "ask_advisor",
|
|
8786
|
-
|
|
8787
|
-
|
|
8824
|
+
outputSchema: advisorOutputSchema,
|
|
8825
|
+
parameters: Type2.Object({
|
|
8826
|
+
draft: Type2.Optional(Type2.String({
|
|
8788
8827
|
description: "Concise untrusted draft for plan or completion review; claims are not verification evidence."
|
|
8789
8828
|
})),
|
|
8790
|
-
followUpTo:
|
|
8829
|
+
followUpTo: Type2.Optional(Type2.String({
|
|
8791
8830
|
description: "Opaque adviceId from a prior successful consultation. Requires a new non-empty question and reuses that consultation's redacted payload; do not combine with draft, Git context, or file attachments."
|
|
8792
8831
|
})),
|
|
8793
|
-
force:
|
|
8832
|
+
force: Type2.Optional(Type2.Boolean({
|
|
8794
8833
|
description: "Set true only when you judge a decision genuinely material after a consultation was screened out; bypasses screening."
|
|
8795
8834
|
})),
|
|
8796
|
-
gitContext:
|
|
8835
|
+
gitContext: Type2.Optional(Type2.Union([Type2.Literal("none"), Type2.Literal("summary"), Type2.Literal("full")], {
|
|
8797
8836
|
description: "How much of the working tree to include. Use full when the review depends on the exact code changes, such as a completion review. Use summary for changed file names only, or none when the question is not about the current changes. The user's configured allowance is the ceiling and a larger request is narrowed to it."
|
|
8798
8837
|
})),
|
|
8799
|
-
includeTrackedFiles:
|
|
8838
|
+
includeTrackedFiles: Type2.Optional(Type2.Array(Type2.String({
|
|
8800
8839
|
description: "Exact tracked repository-relative files to attach after the Advisor explicitly names a file it cannot review. Requires global advisorTrackedFileContent consent; current working-tree contents are sent as untrusted data."
|
|
8801
8840
|
}))),
|
|
8802
|
-
includeUntracked:
|
|
8841
|
+
includeUntracked: Type2.Optional(Type2.Array(Type2.String({
|
|
8803
8842
|
description: "Exact new repository-relative files to include only when user configuration allows it."
|
|
8804
8843
|
}))),
|
|
8805
|
-
question:
|
|
8844
|
+
question: Type2.Optional(Type2.String({
|
|
8806
8845
|
description: "The specific question or decision to get advice on. Omit this for normal reviews: the Advisor already has the conversation context."
|
|
8807
8846
|
}))
|
|
8808
8847
|
}),
|
|
@@ -8986,7 +9025,9 @@ var registerToolLifecycle = ({
|
|
|
8986
9025
|
ctx.ui.setStatus("advisor-usage", undefined);
|
|
8987
9026
|
}
|
|
8988
9027
|
});
|
|
8989
|
-
pi.on("before_agent_start", (
|
|
9028
|
+
pi.on("before_agent_start", (event, ctx) => {
|
|
9029
|
+
const { sections } = event.systemPromptOptions;
|
|
9030
|
+
delete sections.advisor_invocation_settings;
|
|
8990
9031
|
if (!pi.getActiveTools().includes("ask_advisor")) {
|
|
8991
9032
|
return;
|
|
8992
9033
|
}
|
|
@@ -9000,13 +9041,11 @@ var registerToolLifecycle = ({
|
|
|
9000
9041
|
guidelines.push(`Advisor calls remaining this session: ${budget}.
|
|
9001
9042
|
Reserve calls for material decisions, repeated failures, or final review.`);
|
|
9002
9043
|
}
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
Advisor invocation settings:
|
|
9044
|
+
if (guidelines.length > 0) {
|
|
9045
|
+
sections.advisor_invocation_settings = `Advisor invocation settings:
|
|
9007
9046
|
${guidelines.map((rule) => `- ${rule}`).join(`
|
|
9008
|
-
`)}
|
|
9009
|
-
}
|
|
9047
|
+
`)}`;
|
|
9048
|
+
}
|
|
9010
9049
|
});
|
|
9011
9050
|
pi.on("input", () => {
|
|
9012
9051
|
session.clearFollowUps();
|
|
@@ -9067,7 +9106,7 @@ ${guidelines.map((rule) => `- ${rule}`).join(`
|
|
|
9067
9106
|
|
|
9068
9107
|
// src/tools/register-outcome.ts
|
|
9069
9108
|
import { Text as Text6 } from "@earendil-works/pi-tui";
|
|
9070
|
-
import { Type as
|
|
9109
|
+
import { Type as Type3 } from "typebox";
|
|
9071
9110
|
var registerOutcomeTool = ({
|
|
9072
9111
|
appendOutcome: appendAdvisorOutcome,
|
|
9073
9112
|
pi,
|
|
@@ -9121,10 +9160,10 @@ var registerOutcomeTool = ({
|
|
|
9121
9160
|
},
|
|
9122
9161
|
label: "Record Advisor Outcome",
|
|
9123
9162
|
name: "record_advisor_outcome",
|
|
9124
|
-
parameters:
|
|
9125
|
-
adoption:
|
|
9126
|
-
adviceId:
|
|
9127
|
-
validationStatus:
|
|
9163
|
+
parameters: Type3.Object({
|
|
9164
|
+
adoption: Type3.String({ enum: ADOPTIONS }),
|
|
9165
|
+
adviceId: Type3.String(),
|
|
9166
|
+
validationStatus: Type3.String({ enum: VALIDATIONS })
|
|
9128
9167
|
}),
|
|
9129
9168
|
renderCall: () => new Text6("[advisor] Record outcome", 0, 0),
|
|
9130
9169
|
renderResult: (result) => new Text6(textFrom(result.content), 0, 0)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-advisor-flow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Advanced Executor/Advisor flow for Pi, fully configurable and extendable.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"advisor",
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
},
|
|
94
94
|
"overrides": {
|
|
95
95
|
"brace-expansion": "5.0.12",
|
|
96
|
+
"braces": "github:micromatch/braces#d0d575e55e74a4e0218e5248fafb79efc3e54ebb",
|
|
96
97
|
"is-unicode-supported": "npm:@socketregistry/is-unicode-supported@1.0.5",
|
|
97
98
|
"safe-buffer": "npm:@socketregistry/safe-buffer@1.0.9",
|
|
98
99
|
"undici": "8.11.2"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
|
|
3
|
+
export const advisorOutputSchema = Type.Object({
|
|
4
|
+
adviceId: Type.Optional(Type.String()),
|
|
5
|
+
advisor: Type.Optional(Type.String()),
|
|
6
|
+
followUp: Type.Optional(Type.Boolean()),
|
|
7
|
+
jev: Type.Optional(
|
|
8
|
+
Type.Object({
|
|
9
|
+
kind: Type.Union([Type.Literal("screened"), Type.Literal("repeat")]),
|
|
10
|
+
reason: Type.String(),
|
|
11
|
+
skipped: Type.Boolean(),
|
|
12
|
+
})
|
|
13
|
+
),
|
|
14
|
+
skipReason: Type.Optional(Type.String()),
|
|
15
|
+
text: Type.String({
|
|
16
|
+
description: "Advisor Markdown or consultation skip notice.",
|
|
17
|
+
}),
|
|
18
|
+
usage: Type.Optional(
|
|
19
|
+
Type.Object({
|
|
20
|
+
cacheRead: Type.Optional(Type.Number()),
|
|
21
|
+
cacheWrite: Type.Optional(Type.Number()),
|
|
22
|
+
cost: Type.Optional(Type.Number()),
|
|
23
|
+
input: Type.Optional(Type.Number()),
|
|
24
|
+
output: Type.Optional(Type.Number()),
|
|
25
|
+
totalTokens: Type.Optional(Type.Number()),
|
|
26
|
+
})
|
|
27
|
+
),
|
|
28
|
+
});
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
ExtensionContext,
|
|
4
4
|
} from "@earendil-works/pi-coding-agent";
|
|
5
5
|
import { Type } from "typebox";
|
|
6
|
+
import type { Static } from "typebox";
|
|
6
7
|
|
|
7
8
|
import {
|
|
8
9
|
advisorRef,
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
advisorUsageForPi,
|
|
23
24
|
snapshotAdvisorUsage,
|
|
24
25
|
} from "../usage.ts";
|
|
26
|
+
import { advisorOutputSchema } from "./advisor-output.ts";
|
|
25
27
|
import { assertAdvisorFollowUpPrivacy } from "./consultation.ts";
|
|
26
28
|
import { notifyLocalFailure, updateAdvisorUsageStatus } from "./gate-policy.ts";
|
|
27
29
|
import { normalizeScreeningQuestion, screeningSkipText } from "./jev-filter.ts";
|
|
@@ -106,6 +108,7 @@ const skippedSameModelResult = (
|
|
|
106
108
|
skipReason: notice,
|
|
107
109
|
text: notice,
|
|
108
110
|
},
|
|
111
|
+
structuredContent: { skipReason: notice, text: notice },
|
|
109
112
|
};
|
|
110
113
|
};
|
|
111
114
|
|
|
@@ -138,7 +141,7 @@ export const registerAskAdvisorTool = ({
|
|
|
138
141
|
}: ToolRegistrationContext): void => {
|
|
139
142
|
pi.registerTool({
|
|
140
143
|
description:
|
|
141
|
-
"Consult the on-demand Advisor model for strategic guidance. Call with an empty object for a contextual review; attach an optional draft for concrete plan or completion review. Use followUpTo with a new question to continue one cached consultation without rebuilding its redacted context. If the Advisor explicitly names a missing file, you may make a sequential fresh consultation with includeTrackedFiles when enabled and relevant.",
|
|
144
|
+
"Consult the on-demand Advisor model for strategic guidance. Call with an empty object for a contextual review; attach an optional draft for concrete plan or completion review. Use followUpTo with a new question to continue one cached consultation without rebuilding its redacted context. If the Advisor explicitly names a missing file, you may make a sequential fresh consultation with includeTrackedFiles when enabled and relevant. In Pi Codemode, gather and filter deterministic tool results first, then call tools.ask_advisor. Nested results are not automatically reconstructed: pass only permitted, concise summaries in draft (untrusted, capped at 8 KiB, not independently verified). Draft does not inherit source-tool disclosure policies; use gitContext for patches within the user's allowance.",
|
|
142
145
|
async execute(_id, params, signal, onUpdate, ctx) {
|
|
143
146
|
let followUp:
|
|
144
147
|
| { adviceId: string; payload: AdvisorFollowUpPayload }
|
|
@@ -200,16 +203,18 @@ export const registerAskAdvisorTool = ({
|
|
|
200
203
|
const skipText = screeningSkipText(screening);
|
|
201
204
|
session.releaseCall(_id);
|
|
202
205
|
reservedCalls.delete(_id);
|
|
206
|
+
const skipped = {
|
|
207
|
+
jev: {
|
|
208
|
+
kind: screening.kind,
|
|
209
|
+
reason: screening.reason,
|
|
210
|
+
skipped: true,
|
|
211
|
+
},
|
|
212
|
+
text: skipText,
|
|
213
|
+
};
|
|
203
214
|
return {
|
|
204
215
|
content: [{ text: skipText, type: "text" }],
|
|
205
|
-
details:
|
|
206
|
-
|
|
207
|
-
kind: screening.kind,
|
|
208
|
-
reason: screening.reason,
|
|
209
|
-
skipped: true,
|
|
210
|
-
},
|
|
211
|
-
text: skipText,
|
|
212
|
-
},
|
|
216
|
+
details: skipped,
|
|
217
|
+
structuredContent: skipped,
|
|
213
218
|
};
|
|
214
219
|
}
|
|
215
220
|
if (sameModelAdvisorDisabled(ctx, ctx.model, followUp?.payload.model)) {
|
|
@@ -332,6 +337,15 @@ export const registerAskAdvisorTool = ({
|
|
|
332
337
|
if (usage) {
|
|
333
338
|
details.usage = usage;
|
|
334
339
|
}
|
|
340
|
+
const structuredContent: Static<typeof advisorOutputSchema> = {
|
|
341
|
+
adviceId: result.adviceId,
|
|
342
|
+
advisor: result.model,
|
|
343
|
+
followUp: Boolean(result.followUp),
|
|
344
|
+
text: result.markdown,
|
|
345
|
+
};
|
|
346
|
+
if (usage) {
|
|
347
|
+
structuredContent.usage = usage;
|
|
348
|
+
}
|
|
335
349
|
const response: AgentToolResult<AdvisorToolDetails> = {
|
|
336
350
|
content: [
|
|
337
351
|
{
|
|
@@ -340,6 +354,7 @@ export const registerAskAdvisorTool = ({
|
|
|
340
354
|
},
|
|
341
355
|
],
|
|
342
356
|
details,
|
|
357
|
+
structuredContent,
|
|
343
358
|
};
|
|
344
359
|
if (piUsage) {
|
|
345
360
|
response.usage = piUsage;
|
|
@@ -372,6 +387,7 @@ export const registerAskAdvisorTool = ({
|
|
|
372
387
|
},
|
|
373
388
|
label: "Ask Advisor",
|
|
374
389
|
name: "ask_advisor",
|
|
390
|
+
outputSchema: advisorOutputSchema,
|
|
375
391
|
parameters: Type.Object({
|
|
376
392
|
draft: Type.Optional(
|
|
377
393
|
Type.String({
|
|
@@ -71,7 +71,9 @@ export const registerToolLifecycle = ({
|
|
|
71
71
|
}
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
pi.on("before_agent_start", (
|
|
74
|
+
pi.on("before_agent_start", (event, ctx) => {
|
|
75
|
+
const { sections } = event.systemPromptOptions;
|
|
76
|
+
delete sections.advisor_invocation_settings;
|
|
75
77
|
if (!pi.getActiveTools().includes("ask_advisor")) {
|
|
76
78
|
return;
|
|
77
79
|
}
|
|
@@ -88,11 +90,9 @@ export const registerToolLifecycle = ({
|
|
|
88
90
|
`Advisor calls remaining this session: ${budget}.\nReserve calls for material decisions, repeated failures, or final review.`
|
|
89
91
|
);
|
|
90
92
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
: undefined;
|
|
93
|
+
if (guidelines.length > 0) {
|
|
94
|
+
sections.advisor_invocation_settings = `Advisor invocation settings:\n${guidelines.map((rule) => `- ${rule}`).join("\n")}`;
|
|
95
|
+
}
|
|
96
96
|
});
|
|
97
97
|
|
|
98
98
|
pi.on("input", () => {
|