Files
orca/src/shared/client-environment-info.ts
Jinjing ef56ca8b81 fix(feedback): pre-include Orca version and OS in errors and feedback (#13851)
* fix(feedback): pre-include Orca version and OS in errors and feedback

Make terminal errors and Send Feedback carry easy-to-copy client
environment details so bug reports include build and platform context
without a follow-up ask.

* fix(feedback): satisfy exhaustive-deps in environment prefill hook

Destructure hook params so useEffect/useLayoutEffect dependency lists
are complete and the changed-code quality gate passes.

* fix(preload): stop importing node:os in sandboxed preload

Sandboxed Electron preloads cannot require node:os. That import crashed
the whole preload script, leaving window.api undefined and taking down
App chrome (dock badge, preflight). Keep platform.get on process APIs
only, and guard best-effort badge/preflight callers when api is missing.

* fix(feedback): count text typed below the env footer

Strip only the prefilled Orca/OS/Shell block for Send validation so
users who click past the footer and type can still submit.
2026-08-11 11:49:44 -07:00

63 lines
2.3 KiB
TypeScript

/** Copy-pasteable client environment fields for bug reports and feedback. */
export type ClientEnvironmentInfo = {
appVersion: string
platform: string
osRelease: string
arch: string
/** Login/default shell path when known (e.g. SHELL / ComSpec / spawn shell). */
shell?: string
}
const FOOTER_MARKER = '---'
const ORCA_LINE_PREFIX = 'Orca:'
// Why: match the whole prefilled block (optional Shell line included) so strip
// keeps authored text both above and below — users who click past the footer
// and type must still be able to send.
const CLIENT_ENVIRONMENT_FOOTER_BLOCK =
/(^|\r?\n)---\r?\nOrca:[^\r\n]*\r?\nOS:[^\r\n]*(?:\r?\nShell:[^\r\n]*)?/
function normalizeEnvironmentValue(value: string): string {
return value.trim().replace(/[\r\n]+/g, ' ')
}
export function formatClientEnvironmentInfo(info: ClientEnvironmentInfo): string {
const version = normalizeEnvironmentValue(info.appVersion) || 'unknown'
const platform = normalizeEnvironmentValue(info.platform) || 'unknown'
const osRelease = normalizeEnvironmentValue(info.osRelease)
const arch = normalizeEnvironmentValue(info.arch)
const osParts = [platform, osRelease, arch ? `(${arch})` : ''].filter(Boolean)
const lines = [`${ORCA_LINE_PREFIX} ${version}`, `OS: ${osParts.join(' ')}`]
const shell = info.shell ? normalizeEnvironmentValue(info.shell) : ''
if (shell) {
lines.push(`Shell: ${shell}`)
}
return lines.join('\n')
}
/** Block appended under error/feedback bodies so reporters always paste env details. */
export function formatClientEnvironmentFooter(info: ClientEnvironmentInfo): string {
return `${FOOTER_MARKER}\n${formatClientEnvironmentInfo(info)}`
}
export function hasClientEnvironmentFooter(text: string): boolean {
return CLIENT_ENVIRONMENT_FOOTER_BLOCK.test(text)
}
/** Drop only the env footer block; keep user text above and below it. */
export function stripClientEnvironmentFooter(text: string): string {
return text.replace(CLIENT_ENVIRONMENT_FOOTER_BLOCK, '$1')
}
export function appendClientEnvironmentFooter(params: {
message: string
info: ClientEnvironmentInfo
}): string {
if (hasClientEnvironmentFooter(params.message)) {
return params.message
}
const footer = formatClientEnvironmentFooter(params.info)
const base = params.message.trimEnd()
return base.length > 0 ? `${base}\n\n${footer}` : footer
}