pi-voice-input 0.2.10 → 0.2.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.
@@ -40,7 +40,9 @@ Rules:
40
40
  - Preserve the user's information faithfully. Do not over-summarize or compress. Do not delete constraints, examples, numbers, filenames, errors, multiple requests, ordering, or emphasis.
41
41
  - Correct obvious ASR mistakes, homophones, segmentation, and punctuation. Preserve code identifiers, commands, paths, URLs, model names, package names, and proper nouns.
42
42
  - If the user self-corrects, keep only the corrected intent and remove the false start, correction process, filler, and chatter. Do not lose any other substantive information.
43
- - Make the output complete relative to the raw speech, logically clear, and actionable. Split into items or steps when helpful, but do not drop raw-speech information or repeat existing draft text.
43
+ - Make the output complete relative to the raw speech, logically clear, and actionable, but do not drop raw-speech information or repeat existing draft text.
44
+ - Preserve the raw speech layout. If the raw speech is a single line, output a single line unless the user explicitly dictates line breaks or another multiline layout, for example by saying "new line" or "换行".
45
+ - Do not introduce line breaks, bullets, numbered lists, tables, or code fences merely to improve style.
44
46
  - Do not invent requirements that the raw speech did not express. If uncertain, keep the original meaning and express it more clearly.
45
47
  - The output language must match the primary language of the raw speech, not the context language and not this English prompt. Do not translate just because the instructions are in English.`;
46
48
 
@@ -924,7 +926,18 @@ function resolvePostprocessModel(ctx: ExtensionContext, reference: string): Mode
924
926
  }
925
927
 
926
928
  function extractAssistantText(message: { content: unknown }): string {
927
- return textFromContent(message.content).trim();
929
+ const content = message.content;
930
+ if (typeof content === "string") return content.trim();
931
+ if (!Array.isArray(content)) return "";
932
+ return content
933
+ .map((part) => {
934
+ if (!part || typeof part !== "object") return "";
935
+ const block = part as { type?: unknown; text?: unknown };
936
+ if (block.type === "text" && typeof block.text === "string") return block.text;
937
+ return "";
938
+ })
939
+ .join("")
940
+ .trim();
928
941
  }
929
942
 
930
943
  function cleanPostprocessOutput(output: string): string {
@@ -935,6 +948,27 @@ function cleanPostprocessOutput(output: string): string {
935
948
  return text;
936
949
  }
937
950
 
951
+ function rawTextRequestsMultiline(rawText: string): boolean {
952
+ return (
953
+ /\r|\n/.test(rawText) ||
954
+ /\b(?:new\s*line|newline|line break|next line|new paragraph|paragraph break|carriage return|press enter|separate lines?|multi[- ]line|multiple lines)\b/i.test(rawText) ||
955
+ /(?:换行|新的一行|另起一行|下一行|回车|分行|多行|逐行|每行|空一行|新段落|另起一段|分段)/u.test(rawText)
956
+ );
957
+ }
958
+
959
+ function collapseUnexpectedLineBreaks(text: string): string {
960
+ return text
961
+ .replace(/\r\n?/g, "\n")
962
+ .replace(/[ \t\f\v]*\n+[ \t\f\v]*/g, " ")
963
+ .replace(/[ \t\f\v]{2,}/g, " ")
964
+ .trim();
965
+ }
966
+
967
+ function preserveExpectedPostprocessLayout(rawText: string, output: string): string {
968
+ if (rawTextRequestsMultiline(rawText)) return output.trim();
969
+ return collapseUnexpectedLineBreaks(output);
970
+ }
971
+
938
972
  function removeEditorDraftEcho(editorText: string, output: string): string {
939
973
  const draft = editorText.trim();
940
974
  const text = output.trim();
@@ -981,6 +1015,7 @@ function buildPostprocessPrompt(ctx: ExtensionContext, rawText: string, config:
981
1015
  "IMPORTANT: your output will be pasted verbatim at the current cursor position. It is not a replacement and not a rewrite of the whole editor draft.",
982
1016
  "The current editor draft is context only. Do not rewrite, repeat, complete, delete, or replace existing draft text. Do not output the full sentence after insertion.",
983
1017
  "The true cursor position is not marked in the draft shown here; the pi editor owns the actual insertion point. Do not guess the cursor and synthesize a full surrounding sentence.",
1018
+ "Preserve layout: if the raw ASR text is one line, output one line unless the user explicitly dictated line breaks or another multiline layout.",
984
1019
  "If the raw speech is an inline insertion, continuation, a few words, or a phrase, output only the newly spoken words or phrase.",
985
1020
  "Example: draft is `Please make this function async and [cursor].`, raw speech is `add error handling`, correct output is `add error handling`, not `Please make this function async and add error handling.`.",
986
1021
  "Example: draft is `This variable name is [cursor]unclear`, raw speech is `still`, correct output is `still`, not `This variable name is still unclear`.",
@@ -1038,7 +1073,9 @@ async function postprocessTranscript(ctx: ExtensionContext, rawText: string, con
1038
1073
  }
1039
1074
 
1040
1075
  const polished = cleanPostprocessOutput(extractAssistantText(response));
1041
- return polished ? removeEditorDraftEcho(getFullEditorText(ctx), polished) : rawText;
1076
+ if (!polished) return rawText;
1077
+ const insertion = removeEditorDraftEcho(getFullEditorText(ctx), polished);
1078
+ return preserveExpectedPostprocessLayout(raw, insertion) || rawText;
1042
1079
  }
1043
1080
 
1044
1081
  function insertIntoEditor(ctx: ExtensionContext, text: string) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-voice-input",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "description": "Press Ctrl+Shift+R to dictate prompts into Pi using VolcEngine ASR",
5
5
  "type": "module",
6
6
  "keywords": [