@hyperdreamer/pi-webui 1.17.0 → 1.18.2

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.
@@ -8,11 +8,11 @@ export class SessionDaemonClient {
8
8
  this.baseUrl = sessiondHttpUrl();
9
9
  this.socketPath = sessiondSocketPath();
10
10
  }
11
- async request(method, path, body) {
11
+ async request(method, path, body, signal) {
12
12
  const payload = body === undefined ? undefined : JSON.stringify(body);
13
13
  if (this.baseUrl !== undefined && this.baseUrl !== "")
14
- return this.requestUrl(method, path, payload);
15
- return this.requestSocket(method, path, payload);
14
+ return this.requestUrl(method, path, payload, signal);
15
+ return this.requestSocket(method, path, payload, signal);
16
16
  }
17
17
  getActiveAgentProfile() {
18
18
  return getSessionDaemonActiveAgentProfile(this);
@@ -25,8 +25,8 @@ export class SessionDaemonClient {
25
25
  }
26
26
  return new WebSocket(`ws+unix:${this.socketPath}:${path}`);
27
27
  }
28
- async requestUrl(method, path, payload) {
29
- const init = { method };
28
+ async requestUrl(method, path, payload, signal) {
29
+ const init = { method, ...(signal === undefined ? {} : { signal }) };
30
30
  if (payload !== undefined && payload !== "") {
31
31
  init.headers = { "content-type": "application/json" };
32
32
  init.body = payload;
@@ -35,38 +35,124 @@ export class SessionDaemonClient {
35
35
  return {
36
36
  statusCode: response.status,
37
37
  headers: Object.fromEntries(response.headers.entries()),
38
- body: await response.text(),
38
+ body: await raceWithAbort(Promise.resolve().then(() => response.text()), signal),
39
39
  };
40
40
  }
41
- requestSocket(method, path, payload) {
41
+ requestSocket(method, path, payload, signal) {
42
42
  return new Promise((resolve, reject) => {
43
- const request = http.request({
44
- socketPath: this.socketPath,
45
- path,
46
- method,
47
- headers: payload !== undefined && payload !== ""
48
- ? { "content-type": "application/json", "content-length": Buffer.byteLength(payload) }
49
- : undefined,
50
- }, (response) => {
51
- const chunks = [];
52
- response.on("data", (chunk) => {
53
- chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
54
- });
55
- response.on("end", () => {
43
+ if (signal?.aborted === true) {
44
+ reject(abortError(signal));
45
+ return;
46
+ }
47
+ let settled = false;
48
+ let request;
49
+ let response;
50
+ let responseEnded = false;
51
+ const chunks = [];
52
+ const cleanup = () => {
53
+ request?.removeListener("error", onRequestError);
54
+ request?.removeListener("close", onRequestClose);
55
+ response?.removeListener("data", onData);
56
+ response?.removeListener("end", onEnd);
57
+ response?.removeListener("error", onResponseError);
58
+ response?.removeListener("aborted", onResponseAborted);
59
+ response?.removeListener("close", onResponseClose);
60
+ };
61
+ const settle = (callback) => {
62
+ if (settled)
63
+ return;
64
+ settled = true;
65
+ cleanup();
66
+ callback();
67
+ };
68
+ const fail = (error) => {
69
+ settle(() => { reject(asError(error)); });
70
+ };
71
+ const onData = (chunk) => {
72
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
73
+ };
74
+ const onEnd = () => {
75
+ responseEnded = true;
76
+ settle(() => {
56
77
  resolve({
57
- statusCode: response.statusCode ?? 500,
58
- headers: Object.fromEntries(Object.entries(response.headers).map(([key, value]) => [key, Array.isArray(value) ? value.join(", ") : value ?? ""])),
78
+ statusCode: response?.statusCode ?? 500,
79
+ headers: Object.fromEntries(Object.entries(response?.headers ?? {}).map(([key, value]) => [key, Array.isArray(value) ? value.join(", ") : value ?? ""])),
59
80
  body: Buffer.concat(chunks).toString("utf8"),
60
81
  });
61
82
  });
62
- });
63
- request.on("error", reject);
64
- if (payload !== undefined && payload !== "")
65
- request.write(payload);
66
- request.end();
83
+ };
84
+ const onResponseError = (error) => { fail(error); };
85
+ const onResponseAborted = () => { fail(new Error("Session daemon response was aborted.")); };
86
+ const onResponseClose = () => {
87
+ if (!responseEnded)
88
+ fail(new Error("Session daemon response closed before completion."));
89
+ };
90
+ const onRequestError = (error) => { fail(error); };
91
+ const onRequestClose = () => {
92
+ if (!settled && response === undefined)
93
+ fail(new Error("Session daemon request closed."));
94
+ };
95
+ const onResponse = (nextResponse) => {
96
+ response = nextResponse;
97
+ response.on("data", onData);
98
+ response.once("end", onEnd);
99
+ response.once("error", onResponseError);
100
+ response.once("aborted", onResponseAborted);
101
+ response.once("close", onResponseClose);
102
+ };
103
+ try {
104
+ request = http.request({
105
+ socketPath: this.socketPath,
106
+ path,
107
+ method,
108
+ ...(signal === undefined ? {} : { signal }),
109
+ headers: payload !== undefined && payload !== ""
110
+ ? { "content-type": "application/json", "content-length": Buffer.byteLength(payload) }
111
+ : undefined,
112
+ }, onResponse);
113
+ request.on("error", onRequestError);
114
+ request.once("close", onRequestClose);
115
+ if (payload !== undefined && payload !== "")
116
+ request.write(payload);
117
+ request.end();
118
+ }
119
+ catch (error) {
120
+ request?.destroy();
121
+ fail(error);
122
+ }
67
123
  });
68
124
  }
69
125
  }
126
+ function raceWithAbort(promise, signal) {
127
+ if (signal === undefined)
128
+ return promise;
129
+ return new Promise((resolve, reject) => {
130
+ let settled = false;
131
+ const cleanup = () => { signal.removeEventListener("abort", onAbort); };
132
+ const settle = (callback) => {
133
+ if (settled)
134
+ return;
135
+ settled = true;
136
+ cleanup();
137
+ callback();
138
+ };
139
+ const onAbort = () => {
140
+ settle(() => { reject(abortError(signal)); });
141
+ };
142
+ signal.addEventListener("abort", onAbort, { once: true });
143
+ promise.then((value) => { settle(() => { resolve(value); }); }, (error) => { settle(() => { reject(asError(error)); }); });
144
+ if (signal.aborted)
145
+ onAbort();
146
+ });
147
+ }
148
+ function abortError(signal) {
149
+ return signal.reason instanceof Error
150
+ ? signal.reason
151
+ : new DOMException("The operation was aborted", "AbortError");
152
+ }
153
+ function asError(error) {
154
+ return error instanceof Error ? error : new Error(String(error));
155
+ }
70
156
  export async function getSessionDaemonActiveAgentProfile(client) {
71
157
  let response;
72
158
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"sessionDaemonClient.js","sourceRoot":"","sources":["../../src/sessiond/sessionDaemonClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sessionDaemonClient.js","sourceRoot":"","sources":["../../src/sessiond/sessionDaemonClient.ts"],"names":[],"mappings":"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"}
@@ -348,6 +348,8 @@ export interface PiWebUiSpeechInputConfig {
348
348
  provider?: SpeechInputProviderPreference;
349
349
  /** Omitted means Auto. Stored as a canonical BCP 47 tag. */
350
350
  language?: string;
351
+ /** Default: true. */
352
+ polishVoiceInput?: boolean;
351
353
  cloud?: PiWebUiSpeechInputCloudConfig;
352
354
  }
353
355
  export interface SpeechInputCredentialStatus {
@@ -358,18 +360,40 @@ export interface SpeechInputCredentialStatus {
358
360
  export interface SpeechInputSettings {
359
361
  provider: SpeechInputProviderPreference;
360
362
  language?: string;
363
+ /** Always resolved from persisted configuration, defaulting to true. */
364
+ polishVoiceInput: boolean;
361
365
  cloud: {
362
366
  baseUrl: string;
363
367
  model: string;
364
368
  };
365
369
  }
366
- export interface SpeechInputSettingsResponse {
367
- contractVersion: 1;
370
+ /** Version-one wire settings allow the later polishing preference to be absent. */
371
+ export interface LegacySpeechInputSettings extends Omit<SpeechInputSettings, "polishVoiceInput"> {
372
+ polishVoiceInput?: boolean;
373
+ }
374
+ interface SpeechInputSettingsResponseFields<TSettings> {
368
375
  /** Canonical lowercase UUID; opaque to clients. */
369
376
  revision: string;
370
- settings: SpeechInputSettings;
377
+ settings: TSettings;
371
378
  credential: SpeechInputCredentialStatus;
372
379
  }
380
+ /** Compatibility shape accepted from gateways that predate transcript polishing. */
381
+ export interface LegacySpeechInputSettingsResponse extends SpeechInputSettingsResponseFields<LegacySpeechInputSettings> {
382
+ contractVersion: 1;
383
+ }
384
+ /** Current gateway response shape. */
385
+ export interface SpeechInputSettingsResponseV2 extends SpeechInputSettingsResponseFields<SpeechInputSettings> {
386
+ contractVersion: 2;
387
+ }
388
+ /**
389
+ * Consumer-facing response type. A version-one response may omit the setting;
390
+ * parsers project that omission to the effective enabled default.
391
+ */
392
+ export interface SpeechInputSettingsResponse extends Omit<LegacySpeechInputSettingsResponse, "contractVersion"> {
393
+ contractVersion: 1 | 2;
394
+ }
395
+ /** Browser updates may omit polishing while legacy clients roll forward. */
396
+ export type SpeechInputSettingsUpdateSettings = LegacySpeechInputSettings;
373
397
  export type SpeechInputCredentialMutation = {
374
398
  action: "preserve";
375
399
  } | {
@@ -380,7 +404,7 @@ export type SpeechInputCredentialMutation = {
380
404
  };
381
405
  export interface SpeechInputSettingsUpdate {
382
406
  expectedRevision: string;
383
- settings: SpeechInputSettings;
407
+ settings: SpeechInputSettingsUpdateSettings;
384
408
  credential: SpeechInputCredentialMutation;
385
409
  }
386
410
  export interface SpeechInputTranscribeResponse {
@@ -1 +1 @@
1
- {"version":3,"file":"apiTypes.js","sourceRoot":"","sources":["../../src/shared/apiTypes.ts"],"names":[],"mappings":"AAyFA,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,sBAAsB,EAAE,yBAAyB;IACjD,qBAAqB,EAAE,wBAAwB;IAC/C,eAAe,EAAE,kBAAkB;IACnC,cAAc,EAAE,iBAAiB;IACjC,kBAAkB,EAAE,qBAAqB;IACzC,sBAAsB,EAAE,yBAAyB;IACjD,oBAAoB,EAAE,uBAAuB;IAC7C,sBAAsB,EAAE,yBAAyB;IACjD,qBAAqB,EAAE,wBAAwB;IAC/C,cAAc,EAAE,iBAAiB;IACjC,iBAAiB,EAAE,oBAAoB;IACvC,wBAAwB,EAAE,2BAA2B;IACrD,gBAAgB,EAAE,mBAAmB;IACrC,uBAAuB,EAAE,0BAA0B;IACnD,kBAAkB,EAAE,uBAAuB;IAC3C,iBAAiB,EAAE,qBAAqB;IACxC,oBAAoB,EAAE,wBAAwB;IAC9C,mBAAmB,EAAE,sBAAsB;IAC3C,2BAA2B,EAAE,8BAA8B;IAC3D,mCAAmC,EAAE,sCAAsC;IAC3E,eAAe,EAAE,kBAAkB;IACnC,sBAAsB,EAAE,yBAAyB;CACzC,CAAC;AAsDX,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,CAAU,CAAC;AAQvG,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,aAAa,EAAE,SAAS,CAAU,CAAC;AAogBvE,gEAAgE;AAChE,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAwEvC,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAC3C,MAAM,CAAC,MAAM,qCAAqC,GAAG,GAAG,CAAC;AACzD,MAAM,CAAC,MAAM,8BAA8B,GAAG,EAAE,GAAG,IAAI,CAAC;AACxD,MAAM,CAAC,MAAM,sCAAsC,GAAG,EAAE,GAAG,IAAI,CAAC;AAkBhE,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAC1C,MAAM,CAAC,MAAM,oCAAoC,GAAG,GAAG,CAAC;AACxD,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,GAAG,IAAI,CAAC;AACvD,MAAM,CAAC,MAAM,oCAAoC,GAAG,GAAG,CAAC;AACxD,MAAM,CAAC,MAAM,sCAAsC,GAAG,EAAE,CAAC;AAqCzD,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAC9C,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,GAAG,IAAI,CAAC;AAiwB3D,MAAM,CAAC,MAAM,2CAA2C,GAAG,MAAM,CAAC"}
1
+ {"version":3,"file":"apiTypes.js","sourceRoot":"","sources":["../../src/shared/apiTypes.ts"],"names":[],"mappings":"AAyFA,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,sBAAsB,EAAE,yBAAyB;IACjD,qBAAqB,EAAE,wBAAwB;IAC/C,eAAe,EAAE,kBAAkB;IACnC,cAAc,EAAE,iBAAiB;IACjC,kBAAkB,EAAE,qBAAqB;IACzC,sBAAsB,EAAE,yBAAyB;IACjD,oBAAoB,EAAE,uBAAuB;IAC7C,sBAAsB,EAAE,yBAAyB;IACjD,qBAAqB,EAAE,wBAAwB;IAC/C,cAAc,EAAE,iBAAiB;IACjC,iBAAiB,EAAE,oBAAoB;IACvC,wBAAwB,EAAE,2BAA2B;IACrD,gBAAgB,EAAE,mBAAmB;IACrC,uBAAuB,EAAE,0BAA0B;IACnD,kBAAkB,EAAE,uBAAuB;IAC3C,iBAAiB,EAAE,qBAAqB;IACxC,oBAAoB,EAAE,wBAAwB;IAC9C,mBAAmB,EAAE,sBAAsB;IAC3C,2BAA2B,EAAE,8BAA8B;IAC3D,mCAAmC,EAAE,sCAAsC;IAC3E,eAAe,EAAE,kBAAkB;IACnC,sBAAsB,EAAE,yBAAyB;CACzC,CAAC;AAsDX,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,CAAU,CAAC;AAQvG,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,aAAa,EAAE,SAAS,CAAU,CAAC;AAoiBvE,gEAAgE;AAChE,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAwEvC,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAC3C,MAAM,CAAC,MAAM,qCAAqC,GAAG,GAAG,CAAC;AACzD,MAAM,CAAC,MAAM,8BAA8B,GAAG,EAAE,GAAG,IAAI,CAAC;AACxD,MAAM,CAAC,MAAM,sCAAsC,GAAG,EAAE,GAAG,IAAI,CAAC;AAkBhE,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAC1C,MAAM,CAAC,MAAM,oCAAoC,GAAG,GAAG,CAAC;AACxD,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,GAAG,IAAI,CAAC;AACvD,MAAM,CAAC,MAAM,oCAAoC,GAAG,GAAG,CAAC;AACxD,MAAM,CAAC,MAAM,sCAAsC,GAAG,EAAE,CAAC;AAqCzD,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAC9C,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,GAAG,IAAI,CAAC;AAiwB3D,MAAM,CAAC,MAAM,2CAA2C,GAAG,MAAM,CAAC"}
@@ -27,6 +27,7 @@ export function canonicalBcp47LanguageTag(value) {
27
27
  export function effectiveSpeechInputSettings(config) {
28
28
  return {
29
29
  provider: config?.provider ?? "auto",
30
+ polishVoiceInput: config?.polishVoiceInput ?? true,
30
31
  ...(config?.language === undefined ? {} : { language: config.language }),
31
32
  cloud: {
32
33
  baseUrl: config?.cloud?.baseUrl ?? SPEECH_INPUT_DEFAULT_BASE_URL,
@@ -1 +1 @@
1
- {"version":3,"file":"speechInput.js","sourceRoot":"","sources":["../../src/shared/speechInput.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,6BAA6B,GAAG,2BAA2B,CAAC;AACzE,MAAM,CAAC,MAAM,0BAA0B,GAAG,wBAAwB,CAAC;AAEnE,MAAM,gCAAgC,GAAG,wEAAwE,CAAC;AAElH;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAAa;IACpD,OAAO,gCAAgC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAAa;IACrD,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAClD,OAAO,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,4BAA4B,CAAC,MAA4C;IACvF,OAAO;QACL,QAAQ,EAAE,MAAM,EAAE,QAAQ,IAAI,MAAM;QACpC,GAAG,CAAC,MAAM,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxE,KAAK,EAAE;YACL,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,IAAI,6BAA6B;YAChE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,0BAA0B;SAC1D;KACF,CAAC;AACJ,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,wBAAwB,CAAC,QAA4B;IACnE,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC7C,IAAI,CAAC;QACH,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gCAAgC,CAAC,OAAe;IAC9D,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAC7F,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC5H,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACtG,IAAI,GAAG,CAAC,IAAI,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAChG,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/C,GAAG,CAAC,QAAQ,GAAG,GAAG,IAAI,uBAAuB,CAAC;IAC9C,OAAO,GAAG,CAAC,IAAI,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"speechInput.js","sourceRoot":"","sources":["../../src/shared/speechInput.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,6BAA6B,GAAG,2BAA2B,CAAC;AACzE,MAAM,CAAC,MAAM,0BAA0B,GAAG,wBAAwB,CAAC;AAEnE,MAAM,gCAAgC,GAAG,wEAAwE,CAAC;AAElH;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAAa;IACpD,OAAO,gCAAgC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAAa;IACrD,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAClD,OAAO,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,4BAA4B,CAAC,MAA4C;IACvF,OAAO;QACL,QAAQ,EAAE,MAAM,EAAE,QAAQ,IAAI,MAAM;QACpC,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,IAAI,IAAI;QAClD,GAAG,CAAC,MAAM,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxE,KAAK,EAAE;YACL,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,IAAI,6BAA6B;YAChE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,0BAA0B;SAC1D;KACF,CAAC;AACJ,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,wBAAwB,CAAC,QAA4B;IACnE,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC7C,IAAI,CAAC;QACH,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gCAAgC,CAAC,OAAe;IAC9D,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAC7F,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC5H,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACtG,IAAI,GAAG,CAAC,IAAI,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAChG,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/C,GAAG,CAAC,QAAQ,GAAG,GAAG,IAAI,uBAAuB,CAAC;IAC9C,OAAO,GAAG,CAAC,IAAI,CAAC;AAClB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export const SPEECH_INPUT_POLISHING_ROUTE_TIMEOUT_MS = 30_000;
2
+ // Reserve five seconds for abort propagation, cleanup, and the HTTP response after the provider deadline.
3
+ export const SPEECH_INPUT_POLISHING_MODEL_TIMEOUT_MS = 25_000;
4
+ //# sourceMappingURL=speechInputPolishing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speechInputPolishing.js","sourceRoot":"","sources":["../../src/shared/speechInputPolishing.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uCAAuC,GAAG,MAAM,CAAC;AAC9D,0GAA0G;AAC1G,MAAM,CAAC,MAAM,uCAAuC,GAAG,MAAM,CAAC"}
package/docs/config.md CHANGED
@@ -45,7 +45,7 @@ Process restarts depend on the key:
45
45
  - `modelTiers`: saved settings apply immediately in **Settings → Model tiers**; validates all six ladder rows atomically.
46
46
  - `utilityModels`: saved settings apply immediately in **Settings → Utility models**; existing sessions use updated values on their next utility operation.
47
47
  - `tts`: saved voice/rate settings apply to the next utterance; no service restart required.
48
- - `speechInput`: saved provider, language, and cloud settings apply to the next dictation run; no service restart required for saves. Installing or updating this feature requires one manual `pi-webui-sessiond.service` restart because both services adopt the shared config-mutation coordinator.
48
+ - `speechInput`: saved provider, language, transcript-polishing preference, and cloud settings apply to the next dictation run; no service restart required for saves. The already-committed transcript-polishing route and session-daemon service changes require one manual `pi-webui-sessiond.service` restart when this feature is installed or updated because both services adopt the shared config-mutation coordinator.
49
49
  - `pathAccess`: applies on the next request; existing file views may need a browser refresh.
50
50
  - `uploads.defaultFolder`: applies to newly opened Files upload dialogs and new direct drag/drop batches after config/workspace refresh.
51
51
  - `plugins`: reload the browser tab after changing PI WEBUI plugin enablement.
@@ -95,6 +95,7 @@ Process restarts depend on the key:
95
95
  "speechInput": {
96
96
  "provider": "auto",
97
97
  "language": "en-US",
98
+ "polishVoiceInput": true,
98
99
  "cloud": {
99
100
  "baseUrl": "https://api.openai.com/v1",
100
101
  "model": "gpt-4o-mini-transcribe",
@@ -335,13 +336,14 @@ Operational notes:
335
336
 
336
337
  PI WEBUI can turn spoken dictation into editable prompt text in the starter and active-session composers. Dictation only edits the prompt draft at the captured selection: it never sends, queues, steers, or starts anything on its own, and the inserted text is always editable before you act on it. The microphone action sits immediately before Send in both composers, and the agent-work Stop control remains independently available during dictation.
337
338
 
338
- `speechInput` is a gateway-only setting in `$PI_WEBUI_CONFIG` or `~/.config/pi-webui/config.json`. It is not a selected-machine key and never applies to remote machines, and project-local config does not support it. **Settings → General** shows the full-width **Speech input** card regardless of the selected coding machine; dictation and cloud transcription both run on the gateway that serves the browser UI.
339
+ `speechInput` is a gateway-only setting in `$PI_WEBUI_CONFIG` or `~/.config/pi-webui/config.json`. It is not a selected-machine key and never applies to remote machines, and project-local config does not support it. **Settings → General** shows the full-width **Speech input** card regardless of the selected coding machine; dictation and cloud transcription both run on the gateway that serves the browser UI, on the local WebUI/session-daemon machine.
339
340
 
340
341
  ```json
341
342
  {
342
343
  "speechInput": {
343
344
  "provider": "auto",
344
345
  "language": "en-US",
346
+ "polishVoiceInput": true,
345
347
  "cloud": {
346
348
  "baseUrl": "https://api.openai.com/v1",
347
349
  "model": "gpt-4o-mini-transcribe",
@@ -351,9 +353,11 @@ PI WEBUI can turn spoken dictation into editable prompt text in the starter and
351
353
  }
352
354
  ```
353
355
 
354
- The object accepts only `provider` (`auto`, `browser`, or `cloud`; default `auto`), `language` (a BCP 47 tag such as `en-US`; omitted means Auto), `cloud.baseUrl` (HTTPS only; default `https://api.openai.com/v1`), `cloud.model` (default `gpt-4o-mini-transcribe`), and `cloud.apiKey` (a Pi-compatible credential source). Unknown keys are rejected. Stored limits are: language tag 128 characters, base URL 2,048 characters, model 256 characters, and credential source 8 KiB of UTF-8 text. Language validation is syntactic only: it canonicalizes case and structure (`en-us` becomes `en-US`) but stores well-formed tags it cannot verify, so a tag such as `qq-ZZ` is saved and forwarded to the provider, which decides whether it is usable.
356
+ The object accepts only `provider` (`auto`, `browser`, or `cloud`; default `auto`), `language` (a BCP 47 tag such as `en-US`; omitted means Auto), `polishVoiceInput` (a boolean; default `true` when omitted; set it to `false` to disable transcript polishing), `cloud.baseUrl` (HTTPS only; default `https://api.openai.com/v1`), `cloud.model` (default `gpt-4o-mini-transcribe`), and `cloud.apiKey` (a Pi-compatible credential source). Unknown keys are rejected. Stored limits are: language tag 128 characters, base URL 2,048 characters, model 256 characters, and credential source 8 KiB of UTF-8 text. Language validation is syntactic only: it canonicalizes case and structure (`en-us` becomes `en-US`) but stores well-formed tags it cannot verify, so a tag such as `qq-ZZ` is saved and forwarded to the provider, which decides whether it is usable.
355
357
 
356
- The **Speech input** card exposes a Provider select (Auto, Browser, Cloud), a Language input (empty means Auto, which is never sent as a BCP 47 tag), **Cloud base URL**, **Cloud model**, a password-style **API key source** input with literal, `$ENV_VAR`, and `!command` placeholder guidance (never prepopulated; blank means preserve), the redacted credential status, a separate **Clear credential** action that clears only the saved credential, and **Save speech input settings**. Cloud fields stay editable in Auto because Cloud may be the selected fallback candidate.
358
+ The **Speech input** card exposes a Provider select (Auto, Browser, Cloud), a Language input (empty means Auto, which is never sent as a BCP 47 tag), a **Transcript polishing** checkbox (enabled by default; set `polishVoiceInput` to `false` to disable it), **Cloud base URL**, **Cloud model**, a password-style **API key source** input with literal, `$ENV_VAR`, and `!command` placeholder guidance (never prepopulated; blank means preserve), the redacted credential status, a separate **Clear credential** action that clears only the saved credential, and **Save speech input settings**. Cloud fields stay editable in Auto because Cloud may be the selected fallback candidate. When enabled, transcript polishing sends captured transcript text to the configured lightweight utility model for conservative cleanup; the utility model may use its configured provider.
359
+
360
+ Transcript polishing is a gateway operation on the local WebUI/session-daemon machine, not a selected-machine operation. It runs after the provider returns a transcript and before insertion; it never creates a Pi session and does not persist transcript or prompt text.
357
361
 
358
362
  **Provider selection.** The Settings card offers **Auto**, **Browser**, and **Cloud**.
359
363
 
@@ -377,7 +381,7 @@ A plain `OPENAI_API_KEY` (no `$`) is a literal, not an environment reference. Mi
377
381
 
378
382
  The settings card shows only a redacted status — **Credential missing**, **Literal credential configured**, **Environment credential resolved/unresolved**, or **Command credential configured; checked when used** — never the source text, the resolved key, an environment name, or command text. The API key field is never prepopulated; the browser holds a newly entered source only in the password input and the in-flight same-origin request, and clears it after a successful save (retaining it after a failure for correction).
379
383
 
380
- **Capture and transcription limits.** Every run is bounded:
384
+ **Capture, transcription, and polishing limits.** Every run is bounded:
381
385
 
382
386
  - Capture/listening is hard-limited to ten minutes from the provider's successful start.
383
387
  - Browser recognition is stopped and finalized at the limit; because a recognition instance may never emit its terminal `end` event, a Stop request starts a 2,000 ms settlement watchdog that finalizes accumulated text when it expires.
@@ -386,14 +390,19 @@ The settings card shows only a redacted status — **Credential missing**, **Lit
386
390
  - Cloud credential command resolution is bounded to ten seconds, the provider request to 120 seconds (one total budget each, never reset between stages), and the client owns a 130-second Transcribing watchdog covering upload, credential resolution, provider request, and response even if the gateway connection is lost. Combined with the capture limit, a cloud run ends at most 12 minutes 10 seconds after recording starts, excluding user-controlled permission time.
387
391
  - Accepted recording types are `audio/webm;codecs=opus`, `audio/ogg;codecs=opus`, `audio/mp4;codecs=mp4a.40.2`, and `audio/mp4`. Other codec/parameter combinations are rejected.
388
392
  - Every accepted transcript must be nonempty and at most 1 MiB of UTF-8 text.
393
+ - Transcript polishing accepts at most two concurrent requests.
394
+ - Each request has a 30-second client and route deadline; the utility-model provider has 25 seconds, leaving five seconds for cancellation, cleanup, and the HTTP response.
395
+ - Input and polished output are each limited to 1 MiB of UTF-8 text.
396
+ - If polishing times out or fails, PI WEBUI inserts the original transcript instead.
389
397
 
390
398
  **Settings concurrency.** Every speech mutation must match the latest opaque revision; a stale tab receives a `409` conflict and performs no write. Saving rotates the revision and tells other tabs (through a nonsecret channel containing only the new revision) to refetch; a burst of notifications requests one trailing refetch so no revision is lost. A dirty form preserves its draft and password, marks itself stale, and requires an explicit reload before retrying. Because a preserved credential cannot be silently redirected to a new endpoint, changing the cloud base URL while a credential is configured requires re-entering a replacement credential source in the same save, or clearing the saved credential first.
391
399
 
392
- **Shared persistence coordination.** Because the autoreloading web/API process and the long-lived session daemon both perform read-modify-write updates on the shared global config file, production config mutations run under a private SQLite transaction mutex. Its database lives at `$PI_WEBUI_DATA_DIR/config-mutations/<config-path-hash>.sqlite` (named by a SHA-256 digest of the resolved global config path), inside a `0700` directory, with the database file tightened to `0600`. It stores only a random opaque speech-input revision and a fingerprint of nonsecret config-file identity metadata — no config, credential, audio, or transcript bytes, and it never hashes file contents. Audio and transcription never touch SQLite. Lock acquisition uses one ten-second monotonic budget; exhaustion surfaces as a typed "config is busy" failure (HTTP `503`) rather than a hang. Selected-machine config patches are forwarded atomically to the target gateway, where that gateway's own coordinator merges them. Manual config-file edits while either service is running are unsupported: stop both services first, then edit, then start them again. Installing this change requires one manual `pi-webui-sessiond.service` restart because the daemon's existing config writes adopt the shared coordinator; ordinary web/UI autoreload does not load that daemon-side change.
400
+ **Shared persistence coordination.** Because the autoreloading web/API process and the long-lived session daemon both perform read-modify-write updates on the shared global config file, production config mutations run under a private SQLite transaction mutex. Its database lives at `$PI_WEBUI_DATA_DIR/config-mutations/<config-path-hash>.sqlite` (named by a SHA-256 digest of the resolved global config path), inside a `0700` directory, with the database file tightened to `0600`. It stores only a random opaque speech-input revision and a fingerprint of nonsecret config-file identity metadata — no config, credential, audio, or transcript bytes, and it never hashes file contents. Audio and transcription never touch SQLite. Lock acquisition uses one ten-second monotonic budget; exhaustion surfaces as a typed "config is busy" failure (HTTP `503`) rather than a hang. Selected-machine config patches are forwarded atomically to the target gateway, where that gateway's own coordinator merges them. Manual config-file edits while either service is running are unsupported: stop both services first, then edit, then start them again. The already-committed transcript-polishing route and session-daemon service changes require one manual `pi-webui-sessiond.service` restart when this feature is installed or updated because the daemon's existing config writes adopt the shared coordinator; ordinary web/UI autoreload does not load those daemon-side changes.
393
401
 
394
402
  **Privacy and security.**
395
403
 
396
- - PI WEBUI does not persist dictated audio, browser interim text, or cloud request bodies. Audio lives only in bounded process memory and browser buffers for the duration of a run; no object URL, download, attachment, workspace file, IndexedDB record, or session entry is created.
404
+ - PI WEBUI does not persist dictated audio, browser interim text, or cloud request bodies. Audio lives only in bounded process memory and browser buffers for the duration of a run; no object URL, download, attachment, workspace file, IndexedDB record, Pi session, prompt history, transcript record, or session entry is created.
405
+ - When transcript polishing is enabled, captured transcript text is sent to the configured lightweight utility model for conservative cleanup; the utility model may use its configured provider. PI WEBUI does not persist that text.
397
406
  - Browser-provider processing may leave the device under the browser vendor's implementation and policy.
398
407
  - Cloud audio leaves the gateway only for the explicitly configured endpoint, which must be HTTPS with no credentials, query, or fragment; redirects are rejected so audio and the resolved credential cannot be forwarded to another origin. No automatic provider fallback can change that boundary mid-run.
399
408
  - Audio, transcript text, credential sources, and resolved credentials are excluded from logs and error messages; provider error bodies are never forwarded to the browser.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperdreamer/pi-webui",
3
- "version": "1.17.0",
3
+ "version": "1.18.2",
4
4
  "description": "Web UI for persistent Pi Coding Agent sessions in real workspaces.",
5
5
  "license": "MIT",
6
6
  "author": "Federico Jaramillo Martinez and HyperDreamer",