@howaboua/pi-ask 0.0.9 → 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 +10 -0
- package/ask/coordinator.ts +35 -7
- package/ask/pending.ts +8 -2
- package/ask/tool.ts +3 -1
- package/ask/tui.ts +7 -0
- package/index.ts +14 -0
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @howaboua/pi-ask
|
|
2
2
|
|
|
3
|
+
## 0.0.11
|
|
4
|
+
|
|
5
|
+
- Parents can receive and answer asynchronous questions through Shepherdr while workers continue.
|
|
6
|
+
|
|
7
|
+
## 0.0.10
|
|
8
|
+
|
|
9
|
+
- Requires Pi 1.0.0 or later.
|
|
10
|
+
|
|
11
|
+
Fixed Ask text cursor and input-method candidate window placement in Pi's fullscreen interface.
|
|
12
|
+
|
|
3
13
|
## 0.0.9
|
|
4
14
|
|
|
5
15
|
- Removed redundant tool guidance from Ask, Shepherdr, Skills and Browser. Code and Notebook Mode now show one callable contract per tool, with detailed Browser and agent rules in help.
|
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/ask/tui.ts
CHANGED
|
@@ -217,6 +217,13 @@ export async function askInTui(
|
|
|
217
217
|
return lines;
|
|
218
218
|
};
|
|
219
219
|
return {
|
|
220
|
+
get focused() {
|
|
221
|
+
return editor.focused;
|
|
222
|
+
},
|
|
223
|
+
set focused(value: boolean) {
|
|
224
|
+
editor.focused = value;
|
|
225
|
+
cached = undefined;
|
|
226
|
+
},
|
|
220
227
|
render,
|
|
221
228
|
handleInput,
|
|
222
229
|
dispose: () => signal?.removeEventListener("abort", abort),
|
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,10 +45,10 @@
|
|
|
45
45
|
]
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"@howaboua/pi-codex-conversion": ">=3.0.
|
|
49
|
-
"@earendil-works/pi-ai": ">=0.
|
|
50
|
-
"@earendil-works/pi-coding-agent": ">=0.
|
|
51
|
-
"@earendil-works/pi-tui": ">=0.
|
|
48
|
+
"@howaboua/pi-codex-conversion": ">=3.0.46",
|
|
49
|
+
"@earendil-works/pi-ai": ">=1.0.0",
|
|
50
|
+
"@earendil-works/pi-coding-agent": ">=1.0.0",
|
|
51
|
+
"@earendil-works/pi-tui": ">=1.0.0",
|
|
52
52
|
"typebox": "*"
|
|
53
53
|
},
|
|
54
54
|
"peerDependenciesMeta": {
|
|
@@ -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": "0.
|
|
63
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
64
|
-
"@earendil-works/pi-tui": "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
|
},
|