@narumitw/pi-plan-mode 0.20.0 → 0.24.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@narumitw/pi-plan-mode",
3
- "version": "0.20.0",
3
+ "version": "0.24.0",
4
4
  "description": "Pi extension that adds a Codex-like read-only /plan collaboration mode.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -2,8 +2,12 @@ import { PLAN_MODE_COMPLETE_TOOL_NAME } from "./completion-tool.js";
2
2
 
3
3
  const PLAN_CONTEXT_MESSAGE_TYPE = "plan-mode-context";
4
4
  const PROPOSED_PLAN_MESSAGE_TYPE = "proposed-plan";
5
- const PROPOSED_PLAN_PATTERN = /^<proposed_plan>[\t ]*\r?\n([\s\S]*?)\r?\n<\/proposed_plan>[\t ]*$/gm;
6
- const PROPOSED_PLAN_BLOCK_PATTERN = /^<proposed_plan>[\t ]*\r?\n[\s\S]*?\r?\n<\/proposed_plan>[\t ]*$/gm;
5
+ const PLAN_IMPLEMENTATION_HANDOFF_PREFIX =
6
+ "Plan mode is now disabled. Full tool access is restored. Implement this proposed plan now:";
7
+ const PROPOSED_PLAN_PATTERN =
8
+ /^<proposed_plan>[\t ]*\r?\n([\s\S]*?)\r?\n<\/proposed_plan>[\t ]*$/gm;
9
+ const PROPOSED_PLAN_BLOCK_PATTERN =
10
+ /^<proposed_plan>[\t ]*\r?\n[\s\S]*?\r?\n<\/proposed_plan>[\t ]*$/gm;
7
11
 
8
12
  export type ProposedPlanParseResult =
9
13
  | { kind: "absent" }
@@ -65,6 +69,14 @@ export function messageContainsInactivePlanModeArtifact(message: unknown) {
65
69
  );
66
70
  }
67
71
 
72
+ export function messageContainsPlanModeImplementationHandoff(message: unknown) {
73
+ const candidate = unwrapSessionMessage(message);
74
+ return (
75
+ candidate.role === "user" &&
76
+ contentText(candidate.content).trimStart().startsWith(PLAN_IMPLEMENTATION_HANDOFF_PREFIX)
77
+ );
78
+ }
79
+
68
80
  export function stripProposedPlanBlocksFromMessage<T>(message: T): T {
69
81
  return replaceAssistantContent(message, stripProposedPlanBlocksFromContent);
70
82
  }
@@ -74,9 +86,7 @@ export function stripPlanModeCompletionCallsFromMessage<T>(message: T): T {
74
86
  if (!Array.isArray(content)) return content;
75
87
  const nextContent = content.filter((block) => {
76
88
  const candidate = block as { type?: string; name?: string };
77
- return !(
78
- candidate.type === "toolCall" && candidate.name === PLAN_MODE_COMPLETE_TOOL_NAME
79
- );
89
+ return !(candidate.type === "toolCall" && candidate.name === PLAN_MODE_COMPLETE_TOOL_NAME);
80
90
  });
81
91
  return nextContent.length === content.length ? content : nextContent;
82
92
  });
@@ -91,10 +101,7 @@ export function isEmptyAssistantMessage(message: unknown) {
91
101
  );
92
102
  }
93
103
 
94
- function replaceAssistantContent<T>(
95
- message: T,
96
- transform: (content: unknown) => unknown,
97
- ): T {
104
+ function replaceAssistantContent<T>(message: T, transform: (content: unknown) => unknown): T {
98
105
  const candidate = unwrapSessionMessage(message);
99
106
  if (candidate.role !== "assistant") return message;
100
107
 
package/src/plan-mode.ts CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  latestAssistantText,
11
11
  messageContainsInactivePlanModeArtifact,
12
12
  messageContainsLegacyPlanModeContextArtifact,
13
+ messageContainsPlanModeImplementationHandoff,
13
14
  parseProposedPlan,
14
15
  stripPlanModeCompletionCallsFromMessage,
15
16
  stripProposedPlanBlocksFromMessage,
@@ -292,7 +293,13 @@ export default function planMode(pi: ExtensionAPI) {
292
293
  const messagesWithoutLegacyPlanContext = event.messages.filter(
293
294
  (message: unknown) => !messageContainsLegacyPlanModeContextArtifact(message),
294
295
  );
295
- if (state.enabled) return { messages: messagesWithoutLegacyPlanContext };
296
+ if (state.enabled) {
297
+ return {
298
+ messages: messagesWithoutLegacyPlanContext.filter(
299
+ (message: unknown) => !messageContainsPlanModeImplementationHandoff(message),
300
+ ),
301
+ };
302
+ }
296
303
  return {
297
304
  messages: messagesWithoutLegacyPlanContext
298
305
  .filter((message: unknown) => !messageContainsInactivePlanModeArtifact(message))