@jwilger/pi-development-system 0.38.2 → 0.40.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/package.json
CHANGED
|
@@ -15,10 +15,15 @@ export function registerCompactionResync(deps: { pi: ExtensionAPI; state: Sessio
|
|
|
15
15
|
deps.pi.on("session_compact", () => {
|
|
16
16
|
const state = deps.state.get();
|
|
17
17
|
if (state.phase === "idle" && state.openDepartures.length === 0) return;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
// triggerTurn:false: while a run is active pi would otherwise steer the message, and the queued
|
|
19
|
+
// message would force an extra model turn after automatic compaction.
|
|
20
|
+
deps.pi.sendMessage(
|
|
21
|
+
{
|
|
22
|
+
customType: RESYNC_ENTRY_TYPE,
|
|
23
|
+
content: `[devsys resync] Context was compacted. Current working state:\n\n${renderStateBlock(state)}`,
|
|
24
|
+
display: true,
|
|
25
|
+
},
|
|
26
|
+
{ triggerTurn: false },
|
|
27
|
+
);
|
|
23
28
|
});
|
|
24
29
|
}
|
|
@@ -39,7 +39,10 @@ export function registerModelAdvice(deps: ModelAdviceDeps): void {
|
|
|
39
39
|
});
|
|
40
40
|
if (advice === undefined) return;
|
|
41
41
|
told.add(key);
|
|
42
|
-
deps.pi.sendMessage(
|
|
42
|
+
deps.pi.sendMessage(
|
|
43
|
+
{ customType: ADVICE_ENTRY_TYPE, content: advice, display: true },
|
|
44
|
+
{ triggerTurn: false },
|
|
45
|
+
);
|
|
43
46
|
};
|
|
44
47
|
|
|
45
48
|
deps.pi.on("session_start", (_event, ctx) => {
|
|
@@ -31,17 +31,27 @@ export function assistantParts(message: AgentMessage): Parts | undefined {
|
|
|
31
31
|
|
|
32
32
|
const LIST_ITEM = /^(?:\d+[.)]|[-*+])\s/;
|
|
33
33
|
|
|
34
|
+
const QUESTION_END = /\?(?:\s*\([^()]{0,40}\))?[\s)"'*_`]*$/;
|
|
35
|
+
/** A lead-in that asks for a choice ("Want me to:", "Which next:"), not a status summary ("Changes:"). */
|
|
36
|
+
const CHOICE_LEAD_IN =
|
|
37
|
+
/\b(?:want me to|would you like|should i|shall i|which|do you want|let me know|choose|pick)\b[^\n]*:\s*$/i;
|
|
38
|
+
|
|
34
39
|
/**
|
|
35
|
-
* True when the message ends by asking the user something: the last non-empty line
|
|
36
|
-
* option
|
|
40
|
+
* True when the message ends by asking the user something: the last non-empty line, or the last line
|
|
41
|
+
* before an option list, ends with a question mark (optionally followed by a short parenthetical
|
|
42
|
+
* like "(y/n)"), or a bare option list follows a lead-in that asks for a choice. A plain "Summary:" list is not a question.
|
|
37
43
|
*/
|
|
38
44
|
export function asksUser(text: string): boolean {
|
|
39
|
-
const
|
|
45
|
+
const lines = text
|
|
40
46
|
.split("\n")
|
|
41
47
|
.map((l) => l.trim())
|
|
42
|
-
.filter((l) => l !== ""
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
.filter((l) => l !== "");
|
|
49
|
+
const last = lines.at(-1);
|
|
50
|
+
if (last === undefined) return false;
|
|
51
|
+
if (QUESTION_END.test(last)) return true;
|
|
52
|
+
const lead = lines.filter((l) => !LIST_ITEM.test(l)).at(-1);
|
|
53
|
+
if (lead === undefined) return false;
|
|
54
|
+
return QUESTION_END.test(lead) || (LIST_ITEM.test(last) && CHOICE_LEAD_IN.test(lead));
|
|
45
55
|
}
|
|
46
56
|
|
|
47
57
|
/** True when a scope.expansion departure already covers the slice: the remedy the note asks for exists. */
|