@henryqw/pi-prompt-creator 2.0.1 → 2.0.6

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Turn repeated requests or corrections in the current conversation into a reviewed global Pi prompt. A tool-free child drafts one candidate, while Main and the user control review and saving.
4
4
 
5
- Nothing is shown or saved until you choose it.
5
+ Automatic analysis only prepares a candidate; the extension never saves it without your approval.
6
6
 
7
7
  ## Install
8
8
 
@@ -29,13 +29,10 @@ Run `/promptor` in the interactive TUI after a repeated request or correction ap
29
29
 
30
30
  The prompt is created at `~/.pi/agent/prompts/<name>.md`, then Pi reloads its resources. No selection menu or name prompt is required.
31
31
 
32
- | Command | Action |
33
- | --- | --- |
34
- | `/promptor` | Start analysis, or show a candidate prepared by automatic analysis. |
35
- | `/promptor analyze` | Analyze again after a candidate has been reviewed or dismissed. |
36
- | `/promptor save [name]` | Save Main's newest completed review reply, using the suggested name by default. |
37
- | `/promptor dismiss` | Forget a candidate prepared by automatic analysis. |
38
- | `/promptor automatic <on\|off>` | Enable or disable automatic analysis. |
32
+ | Surface | Type | Purpose |
33
+ | --- | --- | --- |
34
+ | `/promptor [analyze|dismiss|save [name]|automatic <on\|off>]` | command | For users in the interactive TUI: start or show analysis, dismiss a pending candidate, save a reviewed prompt, or control automatic analysis. |
35
+ | Analysis status widget and candidate message | ui | Show analysis progress, readiness, or failure; a displayed candidate is marked as untrusted. |
39
36
 
40
37
  ## Flow
41
38
 
@@ -53,7 +50,7 @@ Branch changes reset the input counter. Automatic analysis and candidate widgets
53
50
 
54
51
  Only one analysis can run at a time. A pending candidate blocks another analysis.
55
52
 
56
- Automatic analysis sends the current conversation to the child model configured through `/task-models`.
53
+ Manual and automatic analysis send Pi's current model-visible session context to the child model configured through `/task-models`. Session context edits that omit or replace messages are honored; original text removed from model context is not sent to the child. Request-local `context` and `context_with_system` transformations are not included.
57
54
 
58
55
  Its payload includes the active compaction or branch summary, user text, successfully completed assistant text, and effective prompt names and descriptions.
59
56
 
@@ -65,23 +62,19 @@ New user input does not stop a running child. Branch navigation discards its old
65
62
 
66
63
  ### Review and save
67
64
 
68
- A manually requested analysis displays its completed candidate immediately. Automatic background analysis keeps its candidate behind the `Prompt ready — /promptor` widget until you run `/promptor` or `/promptor dismiss`, so background work never interrupts the conversation.
65
+ A manually requested analysis displays its completed candidate immediately. Automatic analysis shows a running widget, then keeps a completed candidate behind the `Prompt ready — /promptor` widget until you run `/promptor` or `/promptor dismiss`, so background work never interrupts the conversation.
69
66
 
70
67
  Displayed candidates are visible messages marked as untrusted.
71
68
 
72
69
  Refine the candidate with Main. Ask Main to return only the complete Final Prompt Draft before saving it with `/promptor save [name]`.
73
70
 
74
- The save item appears only after you show a candidate and Main then completes a valid Markdown review reply.
75
-
76
- Saving uses that latest retained Main reply as the entire file. Replies before the active compaction or branch summary cannot be saved.
71
+ Saving is allowed only after you show a candidate and Main then completes a valid Markdown review reply. Saving uses that latest retained Main reply as the entire file. Replies before the active compaction or branch summary cannot be saved.
77
72
 
78
73
  An interrupted, failed, empty, or tool-use reply cannot be saved. The extension never falls back to an older reply.
79
74
 
80
75
  A successful save ends that review. Show another candidate and complete another Main review reply before saving again.
81
76
 
82
- The menu asks for a lowercase kebab-case name. A candidate name appears only as a hint.
83
-
84
- Names start with a letter and contain at most 64 ASCII characters. Existing command names and prompt files are rejected.
77
+ `/promptor save` uses the suggested candidate name. Pass `/promptor save <name>` to choose another. Names must be lowercase kebab-case, start with a letter, and contain at most 64 ASCII characters. Existing command names and prompt files are rejected.
85
78
 
86
79
  A successful save reloads Pi resources. If reload fails, the prompt remains saved and `/reload` can load it.
87
80
 
@@ -106,7 +99,7 @@ A missing file quietly uses both defaults. Startup never creates or rewrites the
106
99
 
107
100
  Malformed config or unknown keys disable automatic analysis. Pi warns once and leaves the file unchanged.
108
101
 
109
- Only `Automatic On` or `Automatic Off` writes the config. Toggling preserves the configured threshold.
102
+ Only `/promptor automatic on` or `/promptor automatic off` writes the config. Toggling preserves the configured threshold.
110
103
 
111
104
  ## State and storage
112
105
 
@@ -3,6 +3,7 @@ import { tmpdir } from "node:os";
3
3
  import { dirname, join } from "node:path";
4
4
  import {
5
5
  BorderedLoader,
6
+ buildSessionContext,
6
7
  getAgentDir,
7
8
  type ExtensionAPI,
8
9
  type ExtensionCommandContext,
@@ -62,6 +63,7 @@ The object must have exactly these keys. name must start with a lowercase ASCII
62
63
  type Config = { automatic: boolean; inputThreshold: number };
63
64
  export type PromptCandidate = { name: string; markdown: string };
64
65
  type ConversationItem = { role: "summary" | "user" | "assistant"; text: string };
66
+ type ContextMessage = ReturnType<typeof buildSessionContext>["messages"][number];
65
67
  type ExistingPrompt = { name: string; description: string };
66
68
  type AnalysisPayload = { currentConversation: ConversationItem[]; existingPrompts: ExistingPrompt[] };
67
69
  type ActiveRun = { controller: AbortController; branchGeneration: number };
@@ -133,19 +135,19 @@ function messageText(content: unknown): string {
133
135
  .join("\n");
134
136
  }
135
137
 
136
- function conversationItem(entry: SessionEntry): ConversationItem | undefined {
137
- if (entry.type === "compaction" || entry.type === "branch_summary") {
138
- return entry.summary.trim() ? { role: "summary", text: entry.summary } : undefined;
138
+ function conversationItem(message: ContextMessage): ConversationItem | undefined {
139
+ if (message.role === "compactionSummary" || message.role === "branchSummary") {
140
+ return message.summary.trim() ? { role: "summary", text: message.summary } : undefined;
139
141
  }
140
- if (entry.type !== "message" || (entry.message.role !== "user" && entry.message.role !== "assistant")) return;
141
- if (entry.message.role === "assistant" && entry.message.stopReason !== "stop") return;
142
- const text = messageText(entry.message.content);
143
- return text.trim() ? { role: entry.message.role, text } : undefined;
142
+ if (message.role !== "user" && message.role !== "assistant") return;
143
+ if (message.role === "assistant" && message.stopReason !== "stop") return;
144
+ const text = messageText(message.content);
145
+ return text.trim() ? { role: message.role, text } : undefined;
144
146
  }
145
147
 
146
- function boundedConversation(entries: SessionEntry[], maxChars: number): ConversationItem[] {
147
- const items = entries.flatMap((entry, index) => {
148
- const item = conversationItem(entry);
148
+ function boundedConversation(messages: ContextMessage[], maxChars: number): ConversationItem[] {
149
+ const items = messages.flatMap((message, index) => {
150
+ const item = conversationItem(message);
149
151
  return item ? [{ index, item, chars: JSON.stringify(item).length }] : [];
150
152
  });
151
153
  let summaryIndex = -1;
@@ -178,7 +180,7 @@ function analysisPayload(pi: ExtensionAPI, ctx: ExtensionContext): AnalysisPaylo
178
180
  const payload: AnalysisPayload = { currentConversation: [], existingPrompts: [] };
179
181
  const envelopeChars = JSON.stringify(payload).length;
180
182
  payload.currentConversation = boundedConversation(
181
- ctx.sessionManager.buildContextEntries(),
183
+ buildSessionContext(ctx.sessionManager.getEntries(), ctx.sessionManager.getLeafId()).messages,
182
184
  MAX_PAYLOAD_CHARS - envelopeChars,
183
185
  );
184
186
  let used = JSON.stringify(payload).length;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@henryqw/pi-prompt-creator",
3
- "version": "2.0.1",
3
+ "version": "2.0.6",
4
4
  "description": "Turn current Pi conversation signals into user-approved prompt templates.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "dependencies": {
48
48
  "@henryqw/pi-config-store": "^2.0.0",
49
- "@henryqw/pi-subagent": "^18.0.0",
49
+ "@henryqw/pi-subagent": "^22.0.0",
50
50
  "@henryqw/pi-task-models": "^7.0.0"
51
51
  },
52
52
  "devDependencies": {