@howaboua/pi-ask 0.0.10 → 0.0.11
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 +4 -0
- package/ask/coordinator.ts +35 -7
- package/ask/pending.ts +8 -2
- package/ask/tool.ts +3 -1
- package/index.ts +14 -0
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
package/ask/coordinator.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import type { AskPrompt, PendingAsk } from "./contracts.js";
|
|
2
|
+
import type { AskPrompt, AskResponse, PendingAsk } from "./contracts.js";
|
|
3
3
|
import { normalizeResponses, summarizeResponses } from "./normalize.js";
|
|
4
4
|
import type { PendingAskUpdate } from "./pending.js";
|
|
5
5
|
import { askWithPiUi } from "./pi-ui.js";
|
|
@@ -14,6 +14,7 @@ export interface AskCoordinatorOptions {
|
|
|
14
14
|
askInComposer?: AskInComposer;
|
|
15
15
|
deliverSteer?: (message: string) => void;
|
|
16
16
|
onPendingChange?: (update: PendingAskUpdate) => void;
|
|
17
|
+
onSteerActiveChange?: (request: PendingAsk, active: boolean) => void;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
interface PresentAskOptions {
|
|
@@ -34,11 +35,13 @@ export function createAskCoordinator({
|
|
|
34
35
|
askInComposer,
|
|
35
36
|
deliverSteer,
|
|
36
37
|
onPendingChange,
|
|
38
|
+
onSteerActiveChange,
|
|
37
39
|
}: AskCoordinatorOptions = {}) {
|
|
38
40
|
let generation = 0;
|
|
39
41
|
let sessionAbort = new AbortController();
|
|
40
42
|
let presentationTail = Promise.resolve();
|
|
41
43
|
const activeSteers = new Set<string>();
|
|
44
|
+
let presentedSteer: PendingAsk | undefined;
|
|
42
45
|
|
|
43
46
|
const present = (
|
|
44
47
|
ctx: ExtensionContext,
|
|
@@ -95,10 +98,19 @@ export function createAskCoordinator({
|
|
|
95
98
|
}
|
|
96
99
|
};
|
|
97
100
|
|
|
98
|
-
const close = (
|
|
101
|
+
const close = (
|
|
102
|
+
ctx: ExtensionContext,
|
|
103
|
+
id: string,
|
|
104
|
+
responses?: AskResponse[],
|
|
105
|
+
) => {
|
|
99
106
|
activeSteers.delete(id);
|
|
100
107
|
try {
|
|
101
|
-
onPendingChange?.({
|
|
108
|
+
onPendingChange?.({
|
|
109
|
+
version: 1,
|
|
110
|
+
state: "closed",
|
|
111
|
+
id,
|
|
112
|
+
...(responses ? { responses } : { dismissed: true }),
|
|
113
|
+
});
|
|
102
114
|
} catch (error) {
|
|
103
115
|
notifyFailure(ctx, error);
|
|
104
116
|
}
|
|
@@ -123,12 +135,22 @@ export function createAskCoordinator({
|
|
|
123
135
|
void present(ctx, request.prompts, {
|
|
124
136
|
steering: true,
|
|
125
137
|
signal: sessionAbort.signal,
|
|
138
|
+
onActiveChange: (active) => {
|
|
139
|
+
if (requestGeneration === generation && !sessionAbort.signal.aborted) {
|
|
140
|
+
presentedSteer = active ? request : undefined;
|
|
141
|
+
onSteerActiveChange?.(request, active);
|
|
142
|
+
}
|
|
143
|
+
},
|
|
126
144
|
}).then(
|
|
127
145
|
(responses) => {
|
|
128
146
|
if (requestGeneration !== generation || sessionAbort.signal.aborted)
|
|
129
147
|
return;
|
|
130
148
|
if (deliver(ctx, steerResponse(request.prompts, responses)))
|
|
131
|
-
close(
|
|
149
|
+
close(
|
|
150
|
+
ctx,
|
|
151
|
+
request.id,
|
|
152
|
+
normalizeResponses(request.prompts, responses) ?? undefined,
|
|
153
|
+
);
|
|
132
154
|
},
|
|
133
155
|
(error: unknown) => {
|
|
134
156
|
if (requestGeneration !== generation || sessionAbort.signal.aborted)
|
|
@@ -153,6 +175,7 @@ export function createAskCoordinator({
|
|
|
153
175
|
},
|
|
154
176
|
restorePending(pending: readonly PendingAsk[], ctx: ExtensionContext) {
|
|
155
177
|
generation++;
|
|
178
|
+
presentedSteer = undefined;
|
|
156
179
|
sessionAbort.abort();
|
|
157
180
|
sessionAbort = new AbortController();
|
|
158
181
|
presentationTail = Promise.resolve();
|
|
@@ -161,9 +184,14 @@ export function createAskCoordinator({
|
|
|
161
184
|
for (const request of pending) startSteer(request, ctx, false);
|
|
162
185
|
},
|
|
163
186
|
shutdown() {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
187
|
+
try {
|
|
188
|
+
if (presentedSteer) onSteerActiveChange?.(presentedSteer, false);
|
|
189
|
+
} finally {
|
|
190
|
+
presentedSteer = undefined;
|
|
191
|
+
generation++;
|
|
192
|
+
sessionAbort.abort();
|
|
193
|
+
activeSteers.clear();
|
|
194
|
+
}
|
|
167
195
|
},
|
|
168
196
|
get sessionSignal(): AbortSignal {
|
|
169
197
|
return sessionAbort.signal;
|
package/ask/pending.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import type { SessionEntry } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import type { AskPrompt, PendingAsk } from "./contracts.js";
|
|
2
|
+
import type { AskPrompt, AskResponse, PendingAsk } from "./contracts.js";
|
|
3
3
|
import { normalizeAskInput } from "./normalize.js";
|
|
4
4
|
|
|
5
5
|
export const PENDING_ASK_ENTRY_TYPE = "pi-ask-pending";
|
|
6
6
|
|
|
7
7
|
export type PendingAskUpdate =
|
|
8
8
|
| { version: 1; state: "pending"; id: string; prompts: AskPrompt[] }
|
|
9
|
-
| {
|
|
9
|
+
| {
|
|
10
|
+
version: 1;
|
|
11
|
+
state: "closed";
|
|
12
|
+
id: string;
|
|
13
|
+
responses?: AskResponse[];
|
|
14
|
+
dismissed?: boolean;
|
|
15
|
+
};
|
|
10
16
|
|
|
11
17
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
12
18
|
return typeof value === "object" && value !== null;
|
package/ask/tool.ts
CHANGED
|
@@ -33,11 +33,13 @@ export function createAskRuntime({
|
|
|
33
33
|
deliverSteer,
|
|
34
34
|
onBlockedChange,
|
|
35
35
|
onPendingChange,
|
|
36
|
+
onSteerActiveChange,
|
|
36
37
|
}: AskToolOptions = {}) {
|
|
37
38
|
const coordinator = createAskCoordinator({
|
|
38
39
|
...(askInComposer ? { askInComposer } : {}),
|
|
39
40
|
...(deliverSteer ? { deliverSteer } : {}),
|
|
40
41
|
...(onPendingChange ? { onPendingChange } : {}),
|
|
42
|
+
...(onSteerActiveChange ? { onSteerActiveChange } : {}),
|
|
41
43
|
});
|
|
42
44
|
|
|
43
45
|
const tool = defineTool({
|
|
@@ -70,7 +72,7 @@ export function createAskRuntime({
|
|
|
70
72
|
return {
|
|
71
73
|
content: [
|
|
72
74
|
textContent(
|
|
73
|
-
"Question
|
|
75
|
+
"Question queued. Continue working; the response will arrive as steering.",
|
|
74
76
|
),
|
|
75
77
|
],
|
|
76
78
|
details: { kind: "prompt", pending: true, id: toolCallId },
|
package/index.ts
CHANGED
|
@@ -62,6 +62,20 @@ export default async function humanInTheLoop(pi: ExtensionAPI): Promise<void> {
|
|
|
62
62
|
onPendingChange: (update) => {
|
|
63
63
|
pi.appendEntry(PENDING_ASK_ENTRY_TYPE, update);
|
|
64
64
|
},
|
|
65
|
+
onSteerActiveChange: (request, active) => {
|
|
66
|
+
pi.appendEntry(
|
|
67
|
+
"pi-ask-active",
|
|
68
|
+
active
|
|
69
|
+
? {
|
|
70
|
+
version: 1,
|
|
71
|
+
state: "active",
|
|
72
|
+
id: request.id,
|
|
73
|
+
delivery: "steer",
|
|
74
|
+
prompts: request.prompts,
|
|
75
|
+
}
|
|
76
|
+
: { version: 1, state: "closed", id: request.id },
|
|
77
|
+
);
|
|
78
|
+
},
|
|
65
79
|
});
|
|
66
80
|
const ask = askRuntime.tool;
|
|
67
81
|
const restorePending = (ctx: ExtensionContext) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@howaboua/pi-ask",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"description": "Interactive decisions, review triage, and human handoffs for Pi.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
]
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"@howaboua/pi-codex-conversion": ">=3.0.
|
|
48
|
+
"@howaboua/pi-codex-conversion": ">=3.0.46",
|
|
49
49
|
"@earendil-works/pi-ai": ">=1.0.0",
|
|
50
50
|
"@earendil-works/pi-coding-agent": ">=1.0.0",
|
|
51
51
|
"@earendil-works/pi-tui": ">=1.0.0",
|
|
@@ -57,11 +57,11 @@
|
|
|
57
57
|
}
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@howaboua/pi-codex-conversion": "3.0.
|
|
60
|
+
"@howaboua/pi-codex-conversion": "3.0.46",
|
|
61
61
|
"@biomejs/biome": "^2.5.10",
|
|
62
|
-
"@earendil-works/pi-ai": "1.0.
|
|
63
|
-
"@earendil-works/pi-coding-agent": "1.0.
|
|
64
|
-
"@earendil-works/pi-tui": "1.0.
|
|
62
|
+
"@earendil-works/pi-ai": "1.0.4",
|
|
63
|
+
"@earendil-works/pi-coding-agent": "1.0.4",
|
|
64
|
+
"@earendil-works/pi-tui": "1.0.4",
|
|
65
65
|
"typebox": "1.3.18",
|
|
66
66
|
"typescript": "^7.0.2"
|
|
67
67
|
},
|