@howaboua/pi-ask 0.0.7 → 0.0.8

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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # @howaboua/pi-ask
2
2
 
3
+ ## 0.0.8
4
+
5
+ - Shepherdr now discovers and answers waiting questions invoked inside Code and Notebook Mode.
6
+
3
7
  ## 0.0.7
4
8
 
5
9
  - The `ask` tool now supports steering questions that return immediately, preserve the full response panel, and deliver answers at the next safe boundary using the developer role under active Pi Codex Responses.
@@ -17,6 +17,7 @@ export interface AskCoordinatorOptions {
17
17
  }
18
18
 
19
19
  interface PresentAskOptions {
20
+ onActiveChange?: (active: boolean) => void;
20
21
  handoff?: boolean;
21
22
  steering?: boolean;
22
23
  signal?: AbortSignal;
@@ -42,23 +43,33 @@ export function createAskCoordinator({
42
43
  const present = (
43
44
  ctx: ExtensionContext,
44
45
  prompts: AskPrompt[],
45
- { handoff = false, steering = false, signal }: PresentAskOptions = {},
46
+ {
47
+ handoff = false,
48
+ steering = false,
49
+ signal,
50
+ onActiveChange,
51
+ }: PresentAskOptions = {},
46
52
  ): Promise<unknown> => {
47
53
  const run = async () => {
48
54
  if (signal?.aborted) return null;
49
- return askInComposer
50
- ? await askInComposer(prompts, signal)
51
- : ctx.mode === "tui"
52
- ? await askInTui(ctx, prompts, {
53
- handoff,
54
- steering,
55
- ...(signal ? { signal } : {}),
56
- })
57
- : await askWithPiUi(ctx, prompts, {
58
- handoff,
59
- steering,
60
- ...(signal ? { signal } : {}),
61
- });
55
+ try {
56
+ onActiveChange?.(true);
57
+ return askInComposer
58
+ ? await askInComposer(prompts, signal)
59
+ : ctx.mode === "tui"
60
+ ? await askInTui(ctx, prompts, {
61
+ handoff,
62
+ steering,
63
+ ...(signal ? { signal } : {}),
64
+ })
65
+ : await askWithPiUi(ctx, prompts, {
66
+ handoff,
67
+ steering,
68
+ ...(signal ? { signal } : {}),
69
+ });
70
+ } finally {
71
+ onActiveChange?.(false);
72
+ }
62
73
  };
63
74
  const result = presentationTail.then(run, run);
64
75
  presentationTail = result.then(
package/ask/tool.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { defineTool } from "@earendil-works/pi-coding-agent";
2
2
  import { Text } from "@earendil-works/pi-tui";
3
- import { AskParameters } from "./contracts.js";
3
+ import { AskParameters, type AskPrompt } from "./contracts.js";
4
4
  import {
5
5
  type AskCoordinatorOptions,
6
6
  createAskCoordinator,
@@ -18,6 +18,8 @@ interface BlockedState {
18
18
  active: boolean;
19
19
  label: string;
20
20
  prompt: string;
21
+ handoff: boolean;
22
+ prompts: AskPrompt[];
21
23
  }
22
24
 
23
25
  type OnBlockedChange = (state: BlockedState) => void;
@@ -79,24 +81,22 @@ export function createAskRuntime({
79
81
  const blockedState = {
80
82
  id: toolCallId,
81
83
  active: true,
84
+ handoff,
85
+ prompts,
82
86
  label: handoff ? "Human action needed" : "Waiting for input",
83
87
  prompt: handoff
84
88
  ? "The user needs to complete an action before the active work can continue. Please announce this briefly in your natural voice."
85
89
  : "User input is required before the active work can continue. Please announce this briefly in your natural voice.",
86
90
  };
87
- onBlockedChange?.(blockedState);
88
- let rawResponses: unknown;
89
- try {
90
- const presentationSignal = signal
91
- ? AbortSignal.any([signal, coordinator.sessionSignal])
92
- : coordinator.sessionSignal;
93
- rawResponses = await coordinator.present(ctx, prompts, {
94
- handoff,
95
- signal: presentationSignal,
96
- });
97
- } finally {
98
- onBlockedChange?.({ ...blockedState, active: false });
99
- }
91
+ const presentationSignal = signal
92
+ ? AbortSignal.any([signal, coordinator.sessionSignal])
93
+ : coordinator.sessionSignal;
94
+ const rawResponses = await coordinator.present(ctx, prompts, {
95
+ handoff,
96
+ signal: presentationSignal,
97
+ onActiveChange: (active) =>
98
+ onBlockedChange?.({ ...blockedState, active }),
99
+ });
100
100
  const responses = normalizeResponses(prompts, rawResponses);
101
101
  if (!responses) {
102
102
  return {
package/index.ts CHANGED
@@ -29,15 +29,35 @@ export default async function humanInTheLoop(pi: ExtensionAPI): Promise<void> {
29
29
  const askRuntime = createAskRuntime({
30
30
  deliverSteer: createSteerDelivery(pi, trySendCodexDeveloperMessage),
31
31
  onBlockedChange: (state) => {
32
- pi.events.emit(REALTIME_VOICE_PROMPT_CHANNEL, {
33
- id: state.id,
34
- active: state.active,
35
- prompt: state.prompt,
36
- });
37
- pi.events.emit("herdr:blocked", {
38
- active: state.active,
39
- label: state.label,
40
- });
32
+ const notify = () => {
33
+ pi.events.emit(REALTIME_VOICE_PROMPT_CHANNEL, {
34
+ id: state.id,
35
+ active: state.active,
36
+ prompt: state.prompt,
37
+ });
38
+ pi.events.emit("herdr:blocked", {
39
+ active: state.active,
40
+ label: state.label,
41
+ });
42
+ };
43
+ // Publish before Herdr reports blocked, including calls nested inside exec.
44
+ try {
45
+ pi.appendEntry(
46
+ "pi-ask-active",
47
+ state.active
48
+ ? {
49
+ version: 1,
50
+ state: "active",
51
+ id: state.id,
52
+ handoff: state.handoff,
53
+ prompts: state.prompts,
54
+ }
55
+ : { version: 1, state: "closed", id: state.id },
56
+ );
57
+ } finally {
58
+ if (!state.active) notify();
59
+ }
60
+ if (state.active) notify();
41
61
  },
42
62
  onPendingChange: (update) => {
43
63
  pi.appendEntry(PENDING_ASK_ENTRY_TYPE, update);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@howaboua/pi-ask",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
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.26",
48
+ "@howaboua/pi-codex-conversion": ">=3.0.30",
49
49
  "@earendil-works/pi-ai": ">=0.84.3",
50
50
  "@earendil-works/pi-coding-agent": ">=0.84.3",
51
51
  "@earendil-works/pi-tui": ">=0.84.3",
@@ -57,11 +57,11 @@
57
57
  }
58
58
  },
59
59
  "devDependencies": {
60
- "@howaboua/pi-codex-conversion": "3.0.26",
60
+ "@howaboua/pi-codex-conversion": "3.0.30",
61
61
  "@biomejs/biome": "^2.5.10",
62
- "@earendil-works/pi-ai": "0.85.0",
63
- "@earendil-works/pi-coding-agent": "0.85.0",
64
- "@earendil-works/pi-tui": "0.85.0",
62
+ "@earendil-works/pi-ai": "0.85.1",
63
+ "@earendil-works/pi-coding-agent": "0.85.1",
64
+ "@earendil-works/pi-tui": "0.85.1",
65
65
  "typebox": "1.3.18",
66
66
  "typescript": "^7.0.2"
67
67
  },