@molecule/app-ide-react 1.0.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.
Files changed (250) hide show
  1. package/LICENSE +115 -0
  2. package/dist/chatTimelineOrdering.d.ts +50 -0
  3. package/dist/chatTimelineOrdering.d.ts.map +1 -0
  4. package/dist/chatTimelineOrdering.js +46 -0
  5. package/dist/chatTimelineOrdering.js.map +1 -0
  6. package/dist/command-metadata.d.ts +78 -0
  7. package/dist/command-metadata.d.ts.map +1 -0
  8. package/dist/command-metadata.js +214 -0
  9. package/dist/command-metadata.js.map +1 -0
  10. package/dist/components/ActivityCard.d.ts +28 -0
  11. package/dist/components/ActivityCard.d.ts.map +1 -0
  12. package/dist/components/ActivityCard.js +62 -0
  13. package/dist/components/ActivityCard.js.map +1 -0
  14. package/dist/components/AutoCommitBadge.d.ts +58 -0
  15. package/dist/components/AutoCommitBadge.d.ts.map +1 -0
  16. package/dist/components/AutoCommitBadge.js +78 -0
  17. package/dist/components/AutoCommitBadge.js.map +1 -0
  18. package/dist/components/ChatPanel.d.ts +184 -0
  19. package/dist/components/ChatPanel.d.ts.map +1 -0
  20. package/dist/components/ChatPanel.js +6691 -0
  21. package/dist/components/ChatPanel.js.map +1 -0
  22. package/dist/components/CommandPalette.d.ts +18 -0
  23. package/dist/components/CommandPalette.d.ts.map +1 -0
  24. package/dist/components/CommandPalette.js +33 -0
  25. package/dist/components/CommandPalette.js.map +1 -0
  26. package/dist/components/DeviceFrameSelector.d.ts +60 -0
  27. package/dist/components/DeviceFrameSelector.d.ts.map +1 -0
  28. package/dist/components/DeviceFrameSelector.js +230 -0
  29. package/dist/components/DeviceFrameSelector.js.map +1 -0
  30. package/dist/components/EditorPanel.d.ts +17 -0
  31. package/dist/components/EditorPanel.d.ts.map +1 -0
  32. package/dist/components/EditorPanel.js +241 -0
  33. package/dist/components/EditorPanel.js.map +1 -0
  34. package/dist/components/FileExplorer.d.ts +64 -0
  35. package/dist/components/FileExplorer.d.ts.map +1 -0
  36. package/dist/components/FileExplorer.js +1111 -0
  37. package/dist/components/FileExplorer.js.map +1 -0
  38. package/dist/components/FileExplorerContextMenu.d.ts +37 -0
  39. package/dist/components/FileExplorerContextMenu.d.ts.map +1 -0
  40. package/dist/components/FileExplorerContextMenu.js +241 -0
  41. package/dist/components/FileExplorerContextMenu.js.map +1 -0
  42. package/dist/components/HelpCard.d.ts +34 -0
  43. package/dist/components/HelpCard.d.ts.map +1 -0
  44. package/dist/components/HelpCard.js +28 -0
  45. package/dist/components/HelpCard.js.map +1 -0
  46. package/dist/components/Icon.d.ts +50 -0
  47. package/dist/components/Icon.d.ts.map +1 -0
  48. package/dist/components/Icon.js +25 -0
  49. package/dist/components/Icon.js.map +1 -0
  50. package/dist/components/KeyboardShortcutsPanel.d.ts +19 -0
  51. package/dist/components/KeyboardShortcutsPanel.d.ts.map +1 -0
  52. package/dist/components/KeyboardShortcutsPanel.js +187 -0
  53. package/dist/components/KeyboardShortcutsPanel.js.map +1 -0
  54. package/dist/components/MarkdownContent.d.ts +52 -0
  55. package/dist/components/MarkdownContent.d.ts.map +1 -0
  56. package/dist/components/MarkdownContent.js +303 -0
  57. package/dist/components/MarkdownContent.js.map +1 -0
  58. package/dist/components/ModelsTable.d.ts +38 -0
  59. package/dist/components/ModelsTable.d.ts.map +1 -0
  60. package/dist/components/ModelsTable.js +96 -0
  61. package/dist/components/ModelsTable.js.map +1 -0
  62. package/dist/components/PreviewPanel.d.ts +66 -0
  63. package/dist/components/PreviewPanel.d.ts.map +1 -0
  64. package/dist/components/PreviewPanel.js +1752 -0
  65. package/dist/components/PreviewPanel.js.map +1 -0
  66. package/dist/components/QuickOpen.d.ts +20 -0
  67. package/dist/components/QuickOpen.d.ts.map +1 -0
  68. package/dist/components/QuickOpen.js +72 -0
  69. package/dist/components/QuickOpen.js.map +1 -0
  70. package/dist/components/QuickPicker.d.ts +21 -0
  71. package/dist/components/QuickPicker.d.ts.map +1 -0
  72. package/dist/components/QuickPicker.js +174 -0
  73. package/dist/components/QuickPicker.js.map +1 -0
  74. package/dist/components/RelevantSkillSuggestion.d.ts +41 -0
  75. package/dist/components/RelevantSkillSuggestion.d.ts.map +1 -0
  76. package/dist/components/RelevantSkillSuggestion.js +85 -0
  77. package/dist/components/RelevantSkillSuggestion.js.map +1 -0
  78. package/dist/components/ReportModal.d.ts +35 -0
  79. package/dist/components/ReportModal.d.ts.map +1 -0
  80. package/dist/components/ReportModal.js +112 -0
  81. package/dist/components/ReportModal.js.map +1 -0
  82. package/dist/components/ResizeHandle.d.ts +21 -0
  83. package/dist/components/ResizeHandle.d.ts.map +1 -0
  84. package/dist/components/ResizeHandle.js +109 -0
  85. package/dist/components/ResizeHandle.js.map +1 -0
  86. package/dist/components/ScriptsCard.d.ts +37 -0
  87. package/dist/components/ScriptsCard.d.ts.map +1 -0
  88. package/dist/components/ScriptsCard.js +177 -0
  89. package/dist/components/ScriptsCard.js.map +1 -0
  90. package/dist/components/SearchPanel.d.ts +18 -0
  91. package/dist/components/SearchPanel.d.ts.map +1 -0
  92. package/dist/components/SearchPanel.js +449 -0
  93. package/dist/components/SearchPanel.js.map +1 -0
  94. package/dist/components/SettingsCard.d.ts +49 -0
  95. package/dist/components/SettingsCard.d.ts.map +1 -0
  96. package/dist/components/SettingsCard.js +59 -0
  97. package/dist/components/SettingsCard.js.map +1 -0
  98. package/dist/components/ShareModal.d.ts +32 -0
  99. package/dist/components/ShareModal.d.ts.map +1 -0
  100. package/dist/components/ShareModal.js +126 -0
  101. package/dist/components/ShareModal.js.map +1 -0
  102. package/dist/components/SidebarTabs.d.ts +18 -0
  103. package/dist/components/SidebarTabs.d.ts.map +1 -0
  104. package/dist/components/SidebarTabs.js +20 -0
  105. package/dist/components/SidebarTabs.js.map +1 -0
  106. package/dist/components/SkillsCard.d.ts +86 -0
  107. package/dist/components/SkillsCard.d.ts.map +1 -0
  108. package/dist/components/SkillsCard.js +227 -0
  109. package/dist/components/SkillsCard.js.map +1 -0
  110. package/dist/components/StreamingIndicator.d.ts +50 -0
  111. package/dist/components/StreamingIndicator.d.ts.map +1 -0
  112. package/dist/components/StreamingIndicator.js +142 -0
  113. package/dist/components/StreamingIndicator.js.map +1 -0
  114. package/dist/components/TabBar.d.ts +37 -0
  115. package/dist/components/TabBar.d.ts.map +1 -0
  116. package/dist/components/TabBar.js +187 -0
  117. package/dist/components/TabBar.js.map +1 -0
  118. package/dist/components/TipCard.d.ts +22 -0
  119. package/dist/components/TipCard.d.ts.map +1 -0
  120. package/dist/components/TipCard.js +73 -0
  121. package/dist/components/TipCard.js.map +1 -0
  122. package/dist/components/ToolCallCard.d.ts +18 -0
  123. package/dist/components/ToolCallCard.d.ts.map +1 -0
  124. package/dist/components/ToolCallCard.js +716 -0
  125. package/dist/components/ToolCallCard.js.map +1 -0
  126. package/dist/components/UserAvatar.d.ts +45 -0
  127. package/dist/components/UserAvatar.d.ts.map +1 -0
  128. package/dist/components/UserAvatar.js +80 -0
  129. package/dist/components/UserAvatar.js.map +1 -0
  130. package/dist/components/WorkspaceLayout.d.ts +19 -0
  131. package/dist/components/WorkspaceLayout.d.ts.map +1 -0
  132. package/dist/components/WorkspaceLayout.js +56 -0
  133. package/dist/components/WorkspaceLayout.js.map +1 -0
  134. package/dist/components/activity-utilities.d.ts +107 -0
  135. package/dist/components/activity-utilities.d.ts.map +1 -0
  136. package/dist/components/activity-utilities.js +154 -0
  137. package/dist/components/activity-utilities.js.map +1 -0
  138. package/dist/components/chat-autocommit-utilities.d.ts +172 -0
  139. package/dist/components/chat-autocommit-utilities.d.ts.map +1 -0
  140. package/dist/components/chat-autocommit-utilities.js +185 -0
  141. package/dist/components/chat-autocommit-utilities.js.map +1 -0
  142. package/dist/components/chat-card-style.d.ts +64 -0
  143. package/dist/components/chat-card-style.d.ts.map +1 -0
  144. package/dist/components/chat-card-style.js +74 -0
  145. package/dist/components/chat-card-style.js.map +1 -0
  146. package/dist/components/chat-commands.d.ts +17 -0
  147. package/dist/components/chat-commands.d.ts.map +1 -0
  148. package/dist/components/chat-commands.js +17 -0
  149. package/dist/components/chat-commands.js.map +1 -0
  150. package/dist/components/chat-commit-utilities.d.ts +29 -0
  151. package/dist/components/chat-commit-utilities.d.ts.map +1 -0
  152. package/dist/components/chat-commit-utilities.js +31 -0
  153. package/dist/components/chat-commit-utilities.js.map +1 -0
  154. package/dist/components/chat-cost-utilities.d.ts +62 -0
  155. package/dist/components/chat-cost-utilities.d.ts.map +1 -0
  156. package/dist/components/chat-cost-utilities.js +66 -0
  157. package/dist/components/chat-cost-utilities.js.map +1 -0
  158. package/dist/components/chat-effort-utilities.d.ts +96 -0
  159. package/dist/components/chat-effort-utilities.d.ts.map +1 -0
  160. package/dist/components/chat-effort-utilities.js +97 -0
  161. package/dist/components/chat-effort-utilities.js.map +1 -0
  162. package/dist/components/chat-help-utilities.d.ts +89 -0
  163. package/dist/components/chat-help-utilities.d.ts.map +1 -0
  164. package/dist/components/chat-help-utilities.js +131 -0
  165. package/dist/components/chat-help-utilities.js.map +1 -0
  166. package/dist/components/chat-model-mode-utilities.d.ts +143 -0
  167. package/dist/components/chat-model-mode-utilities.d.ts.map +1 -0
  168. package/dist/components/chat-model-mode-utilities.js +191 -0
  169. package/dist/components/chat-model-mode-utilities.js.map +1 -0
  170. package/dist/components/chat-models-utilities.d.ts +98 -0
  171. package/dist/components/chat-models-utilities.d.ts.map +1 -0
  172. package/dist/components/chat-models-utilities.js +136 -0
  173. package/dist/components/chat-models-utilities.js.map +1 -0
  174. package/dist/components/chat-report-utilities.d.ts +149 -0
  175. package/dist/components/chat-report-utilities.d.ts.map +1 -0
  176. package/dist/components/chat-report-utilities.js +151 -0
  177. package/dist/components/chat-report-utilities.js.map +1 -0
  178. package/dist/components/chat-scripts-utilities.d.ts +140 -0
  179. package/dist/components/chat-scripts-utilities.d.ts.map +1 -0
  180. package/dist/components/chat-scripts-utilities.js +158 -0
  181. package/dist/components/chat-scripts-utilities.js.map +1 -0
  182. package/dist/components/chat-settings-utilities.d.ts +72 -0
  183. package/dist/components/chat-settings-utilities.d.ts.map +1 -0
  184. package/dist/components/chat-settings-utilities.js +56 -0
  185. package/dist/components/chat-settings-utilities.js.map +1 -0
  186. package/dist/components/chat-share-utilities.d.ts +104 -0
  187. package/dist/components/chat-share-utilities.d.ts.map +1 -0
  188. package/dist/components/chat-share-utilities.js +90 -0
  189. package/dist/components/chat-share-utilities.js.map +1 -0
  190. package/dist/components/chat-skills-utilities.d.ts +242 -0
  191. package/dist/components/chat-skills-utilities.d.ts.map +1 -0
  192. package/dist/components/chat-skills-utilities.js +433 -0
  193. package/dist/components/chat-skills-utilities.js.map +1 -0
  194. package/dist/components/chat-stream-utilities.d.ts +74 -0
  195. package/dist/components/chat-stream-utilities.d.ts.map +1 -0
  196. package/dist/components/chat-stream-utilities.js +103 -0
  197. package/dist/components/chat-stream-utilities.js.map +1 -0
  198. package/dist/components/chat-tips-utilities.d.ts +108 -0
  199. package/dist/components/chat-tips-utilities.d.ts.map +1 -0
  200. package/dist/components/chat-tips-utilities.js +137 -0
  201. package/dist/components/chat-tips-utilities.js.map +1 -0
  202. package/dist/components/device-cycle.d.ts +84 -0
  203. package/dist/components/device-cycle.d.ts.map +1 -0
  204. package/dist/components/device-cycle.js +77 -0
  205. package/dist/components/device-cycle.js.map +1 -0
  206. package/dist/components/index.d.ts +36 -0
  207. package/dist/components/index.d.ts.map +1 -0
  208. package/dist/components/index.js +33 -0
  209. package/dist/components/index.js.map +1 -0
  210. package/dist/components/tool-call-utilities.d.ts +69 -0
  211. package/dist/components/tool-call-utilities.d.ts.map +1 -0
  212. package/dist/components/tool-call-utilities.js +368 -0
  213. package/dist/components/tool-call-utilities.js.map +1 -0
  214. package/dist/components/user-avatar-utilities.d.ts +41 -0
  215. package/dist/components/user-avatar-utilities.d.ts.map +1 -0
  216. package/dist/components/user-avatar-utilities.js +56 -0
  217. package/dist/components/user-avatar-utilities.js.map +1 -0
  218. package/dist/components/workspace-layout-utilities.d.ts +37 -0
  219. package/dist/components/workspace-layout-utilities.d.ts.map +1 -0
  220. package/dist/components/workspace-layout-utilities.js +58 -0
  221. package/dist/components/workspace-layout-utilities.js.map +1 -0
  222. package/dist/customEventCards.d.ts +117 -0
  223. package/dist/customEventCards.d.ts.map +1 -0
  224. package/dist/customEventCards.js +36 -0
  225. package/dist/customEventCards.js.map +1 -0
  226. package/dist/hooks/index.d.ts +8 -0
  227. package/dist/hooks/index.d.ts.map +1 -0
  228. package/dist/hooks/index.js +8 -0
  229. package/dist/hooks/index.js.map +1 -0
  230. package/dist/hooks/useKeyboardShortcuts.d.ts +48 -0
  231. package/dist/hooks/useKeyboardShortcuts.d.ts.map +1 -0
  232. package/dist/hooks/useKeyboardShortcuts.js +112 -0
  233. package/dist/hooks/useKeyboardShortcuts.js.map +1 -0
  234. package/dist/hooks/useViewport.d.ts +42 -0
  235. package/dist/hooks/useViewport.d.ts.map +1 -0
  236. package/dist/hooks/useViewport.js +61 -0
  237. package/dist/hooks/useViewport.js.map +1 -0
  238. package/dist/index.d.ts +75 -0
  239. package/dist/index.d.ts.map +1 -0
  240. package/dist/index.js +74 -0
  241. package/dist/index.js.map +1 -0
  242. package/dist/settings-metadata.d.ts +78 -0
  243. package/dist/settings-metadata.d.ts.map +1 -0
  244. package/dist/settings-metadata.js +131 -0
  245. package/dist/settings-metadata.js.map +1 -0
  246. package/dist/types.d.ts +751 -0
  247. package/dist/types.d.ts.map +1 -0
  248. package/dist/types.js +25 -0
  249. package/dist/types.js.map +1 -0
  250. package/package.json +90 -0
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Pure helpers backing the `/report` (and `/bug` alias) command and the header
3
+ * bug-report button.
4
+ *
5
+ * The report modal collects a title, description, optional reproduction steps,
6
+ * and an "include recent chat" toggle, then POSTs to
7
+ * `POST /projects/:id/report { title, description, steps?, includeChat, clientInfo? }`.
8
+ * The backend files a GitHub issue when a report repo + token are configured
9
+ * (else records a DB row) and always persists a DB row tagged with
10
+ * projectId+userId, returning `{ ok, url?, id }`.
11
+ *
12
+ * The payload also carries an optional `clientInfo` block of client-side
13
+ * diagnostics — app version, browser/OS (user agent + platform), language,
14
+ * viewport + screen size, theme, and the current URL — collected by
15
+ * {@link collectClientInfo}. Every field is read defensively (each guarded for
16
+ * SSR / missing globals) so the report attaches whatever it can without ever
17
+ * throwing, giving triage real context without the user having to type it.
18
+ *
19
+ * These helpers parse the command, build the exact POST payload (omitting empty
20
+ * optional fields), validate the form, and produce a confirmation message. They
21
+ * are deterministic and side-effect free so they can be unit tested without
22
+ * rendering or a real backend. The confirmation/link rendering uses these values
23
+ * with `t()` in the component — the only translatable strings here are the
24
+ * confirmation defaults, kept i18n-ready by the caller.
25
+ *
26
+ * @module
27
+ */
28
+ /** The report modal's form state. */
29
+ export interface ReportFormState {
30
+ /** Short summary / issue title. */
31
+ title: string;
32
+ /** Detailed description of the problem or request. */
33
+ description: string;
34
+ /** Optional reproduction steps (free text). */
35
+ steps: string;
36
+ /** Whether to attach the recent conversation to the report. */
37
+ includeChat: boolean;
38
+ }
39
+ /**
40
+ * Client-side diagnostics attached to a report so triage can see the running
41
+ * environment without asking the user. Every field is optional — only what
42
+ * could be read in the current environment is present (see
43
+ * {@link collectClientInfo}).
44
+ */
45
+ export interface ClientInfo {
46
+ /** The running build version. */
47
+ appVersion?: string;
48
+ /** `navigator.userAgent` (browser + OS). */
49
+ userAgent?: string;
50
+ /** `navigator.platform`. */
51
+ platform?: string;
52
+ /** `navigator.language`. */
53
+ language?: string;
54
+ /** Inner viewport size, `${innerWidth}×${innerHeight}`. */
55
+ viewport?: string;
56
+ /** Physical screen size, `${screen.width}×${screen.height}`. */
57
+ screen?: string;
58
+ /** Active theme — `'light'` or `'dark'`. */
59
+ theme?: string;
60
+ /** The current page URL (`window.location.href`). */
61
+ url?: string;
62
+ }
63
+ /** The `POST /projects/:id/report` request body. */
64
+ export interface ReportPayload {
65
+ /** Short summary / issue title. */
66
+ title: string;
67
+ /** Detailed description. */
68
+ description: string;
69
+ /** Reproduction steps — omitted entirely when blank. */
70
+ steps?: string;
71
+ /** Whether the backend should attach the recent conversation. */
72
+ includeChat: boolean;
73
+ /** Client diagnostics — omitted entirely when none could be collected. */
74
+ clientInfo?: ClientInfo;
75
+ }
76
+ /** The `POST /projects/:id/report` response. */
77
+ export interface ReportResult {
78
+ /** Whether the report was recorded. */
79
+ ok: boolean;
80
+ /** Link to the created issue, when one was filed. */
81
+ url?: string;
82
+ /** The persisted DB row id. */
83
+ id?: string;
84
+ }
85
+ /** An empty report form (the modal's initial state). */
86
+ export declare const EMPTY_REPORT_FORM: ReportFormState;
87
+ /**
88
+ * Parses a `/report [title]` or `/bug [title]` command. Returns the (possibly
89
+ * empty) trimmed title used to seed the modal when the input is one of those
90
+ * commands, else `null`.
91
+ *
92
+ * @param input - The raw chat input.
93
+ * @returns `{ title }` when it's a `/report` or `/bug` command, else `null`.
94
+ */
95
+ export declare function parseReportCommand(input: string): {
96
+ title: string;
97
+ } | null;
98
+ /**
99
+ * Collects client-side diagnostics for a report. Reads `navigator`
100
+ * (userAgent/platform/language), `window` (inner viewport size, screen size,
101
+ * location href), plus the caller-supplied app version and theme. Every access
102
+ * is guarded (`typeof window/navigator !== 'undefined'` and per-property
103
+ * presence) so it is SSR-safe and never throws — it returns only the fields it
104
+ * could actually read, so the result may be partial or (in a headless
105
+ * environment) empty.
106
+ *
107
+ * @param opts - Caller-supplied context.
108
+ * @param opts.appVersion - The running build version, if known.
109
+ * @param opts.theme - The active theme (`'light'` | `'dark'`), if known.
110
+ * @returns The populated subset of {@link ClientInfo}.
111
+ */
112
+ export declare function collectClientInfo(opts?: {
113
+ appVersion?: string;
114
+ theme?: string;
115
+ }): ClientInfo;
116
+ /**
117
+ * Builds the `POST /projects/:id/report` body from the form state, trimming all
118
+ * text fields and omitting `steps` entirely when it is blank. When `clientInfo`
119
+ * is supplied and non-empty, it is attached; an `undefined` or empty diagnostics
120
+ * object is omitted from the payload.
121
+ *
122
+ * @param form - The report form state.
123
+ * @param clientInfo - Optional client diagnostics from {@link collectClientInfo}.
124
+ * @returns The normalized report payload.
125
+ */
126
+ export declare function buildReportPayload(form: ReportFormState, clientInfo?: ClientInfo): ReportPayload;
127
+ /**
128
+ * Whether the report form has the minimum required fields: a non-empty title
129
+ * and a non-empty description.
130
+ *
131
+ * @param form - The report form state.
132
+ * @returns `true` when the form can be submitted.
133
+ */
134
+ export declare function isReportFormValid(form: ReportFormState): boolean;
135
+ /**
136
+ * Builds the confirmation message shown after a report is submitted. Returns the
137
+ * English defaults; the component passes these through `t()` at render. The
138
+ * success `defaultValue` may contain the `{{productName}}` interpolation token,
139
+ * which the caller fills in from the host's product identity (neutral default:
140
+ * "the IDE"). When the result is not `ok`, returns the failure message.
141
+ *
142
+ * @param result - The `POST /projects/:id/report` response.
143
+ * @returns `{ key, defaultValue }` for the confirmation/failure message.
144
+ */
145
+ export declare function formatReportConfirmation(result: ReportResult): {
146
+ key: string;
147
+ defaultValue: string;
148
+ };
149
+ //# sourceMappingURL=chat-report-utilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-report-utilities.d.ts","sourceRoot":"","sources":["../../src/components/chat-report-utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,qCAAqC;AACrC,MAAM,WAAW,eAAe;IAC9B,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAA;IACnB,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAA;IACb,+DAA+D;IAC/D,WAAW,EAAE,OAAO,CAAA;CACrB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iEAAiE;IACjE,WAAW,EAAE,OAAO,CAAA;IACpB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB;AAED,gDAAgD;AAChD,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,EAAE,EAAE,OAAO,CAAA;IACX,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,+BAA+B;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ;AAED,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,EAAE,eAK/B,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAI1E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,UAAU,CAwBhG;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,aAAa,CAUhG;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAEhE;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,YAAY,GAAG;IAC9D,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,CAAA;CACrB,CAiBA"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Pure helpers backing the `/report` (and `/bug` alias) command and the header
3
+ * bug-report button.
4
+ *
5
+ * The report modal collects a title, description, optional reproduction steps,
6
+ * and an "include recent chat" toggle, then POSTs to
7
+ * `POST /projects/:id/report { title, description, steps?, includeChat, clientInfo? }`.
8
+ * The backend files a GitHub issue when a report repo + token are configured
9
+ * (else records a DB row) and always persists a DB row tagged with
10
+ * projectId+userId, returning `{ ok, url?, id }`.
11
+ *
12
+ * The payload also carries an optional `clientInfo` block of client-side
13
+ * diagnostics — app version, browser/OS (user agent + platform), language,
14
+ * viewport + screen size, theme, and the current URL — collected by
15
+ * {@link collectClientInfo}. Every field is read defensively (each guarded for
16
+ * SSR / missing globals) so the report attaches whatever it can without ever
17
+ * throwing, giving triage real context without the user having to type it.
18
+ *
19
+ * These helpers parse the command, build the exact POST payload (omitting empty
20
+ * optional fields), validate the form, and produce a confirmation message. They
21
+ * are deterministic and side-effect free so they can be unit tested without
22
+ * rendering or a real backend. The confirmation/link rendering uses these values
23
+ * with `t()` in the component — the only translatable strings here are the
24
+ * confirmation defaults, kept i18n-ready by the caller.
25
+ *
26
+ * @module
27
+ */
28
+ /** An empty report form (the modal's initial state). */
29
+ export const EMPTY_REPORT_FORM = {
30
+ title: '',
31
+ description: '',
32
+ steps: '',
33
+ includeChat: true,
34
+ };
35
+ /**
36
+ * Parses a `/report [title]` or `/bug [title]` command. Returns the (possibly
37
+ * empty) trimmed title used to seed the modal when the input is one of those
38
+ * commands, else `null`.
39
+ *
40
+ * @param input - The raw chat input.
41
+ * @returns `{ title }` when it's a `/report` or `/bug` command, else `null`.
42
+ */
43
+ export function parseReportCommand(input) {
44
+ const match = input.trim().match(/^\/(?:report|bug)(?:\s+(.*))?$/i);
45
+ if (!match)
46
+ return null;
47
+ return { title: (match[1] ?? '').trim() };
48
+ }
49
+ /**
50
+ * Collects client-side diagnostics for a report. Reads `navigator`
51
+ * (userAgent/platform/language), `window` (inner viewport size, screen size,
52
+ * location href), plus the caller-supplied app version and theme. Every access
53
+ * is guarded (`typeof window/navigator !== 'undefined'` and per-property
54
+ * presence) so it is SSR-safe and never throws — it returns only the fields it
55
+ * could actually read, so the result may be partial or (in a headless
56
+ * environment) empty.
57
+ *
58
+ * @param opts - Caller-supplied context.
59
+ * @param opts.appVersion - The running build version, if known.
60
+ * @param opts.theme - The active theme (`'light'` | `'dark'`), if known.
61
+ * @returns The populated subset of {@link ClientInfo}.
62
+ */
63
+ export function collectClientInfo(opts = {}) {
64
+ const info = {};
65
+ if (opts.appVersion)
66
+ info.appVersion = opts.appVersion;
67
+ if (opts.theme)
68
+ info.theme = opts.theme;
69
+ if (typeof navigator !== 'undefined') {
70
+ if (navigator.userAgent)
71
+ info.userAgent = navigator.userAgent;
72
+ if (navigator.platform)
73
+ info.platform = navigator.platform;
74
+ if (navigator.language)
75
+ info.language = navigator.language;
76
+ }
77
+ if (typeof window !== 'undefined') {
78
+ if (typeof window.innerWidth === 'number' && typeof window.innerHeight === 'number') {
79
+ info.viewport = `${window.innerWidth}×${window.innerHeight}`;
80
+ }
81
+ if (window.screen) {
82
+ info.screen = `${window.screen.width}×${window.screen.height}`;
83
+ }
84
+ if (window.location?.href) {
85
+ info.url = window.location.href;
86
+ }
87
+ }
88
+ return info;
89
+ }
90
+ /**
91
+ * Builds the `POST /projects/:id/report` body from the form state, trimming all
92
+ * text fields and omitting `steps` entirely when it is blank. When `clientInfo`
93
+ * is supplied and non-empty, it is attached; an `undefined` or empty diagnostics
94
+ * object is omitted from the payload.
95
+ *
96
+ * @param form - The report form state.
97
+ * @param clientInfo - Optional client diagnostics from {@link collectClientInfo}.
98
+ * @returns The normalized report payload.
99
+ */
100
+ export function buildReportPayload(form, clientInfo) {
101
+ const steps = form.steps.trim();
102
+ const payload = {
103
+ title: form.title.trim(),
104
+ description: form.description.trim(),
105
+ includeChat: form.includeChat,
106
+ };
107
+ if (steps)
108
+ payload.steps = steps;
109
+ if (clientInfo && Object.keys(clientInfo).length > 0)
110
+ payload.clientInfo = clientInfo;
111
+ return payload;
112
+ }
113
+ /**
114
+ * Whether the report form has the minimum required fields: a non-empty title
115
+ * and a non-empty description.
116
+ *
117
+ * @param form - The report form state.
118
+ * @returns `true` when the form can be submitted.
119
+ */
120
+ export function isReportFormValid(form) {
121
+ return form.title.trim().length > 0 && form.description.trim().length > 0;
122
+ }
123
+ /**
124
+ * Builds the confirmation message shown after a report is submitted. Returns the
125
+ * English defaults; the component passes these through `t()` at render. The
126
+ * success `defaultValue` may contain the `{{productName}}` interpolation token,
127
+ * which the caller fills in from the host's product identity (neutral default:
128
+ * "the IDE"). When the result is not `ok`, returns the failure message.
129
+ *
130
+ * @param result - The `POST /projects/:id/report` response.
131
+ * @returns `{ key, defaultValue }` for the confirmation/failure message.
132
+ */
133
+ export function formatReportConfirmation(result) {
134
+ if (!result.ok) {
135
+ return {
136
+ key: 'ide.chat.report.failed',
137
+ defaultValue: 'Could not submit your report. Please try again.',
138
+ };
139
+ }
140
+ if (result.url) {
141
+ return {
142
+ key: 'ide.chat.report.submittedWithLink',
143
+ defaultValue: 'Thanks! Your report was submitted — track it on the linked issue.',
144
+ };
145
+ }
146
+ return {
147
+ key: 'ide.chat.report.submitted',
148
+ defaultValue: "Thanks! Your report was submitted to {{productName}}'s team.",
149
+ };
150
+ }
151
+ //# sourceMappingURL=chat-report-utilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-report-utilities.js","sourceRoot":"","sources":["../../src/components/chat-report-utilities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Pure helpers backing the `/scripts` browser and the `/run <name>` command.
3
+ *
4
+ * Scripts are saved shell files under the project's `.agents/scripts/` tree
5
+ * (`.agents/scripts/<name>.sh`) carrying a YAML frontmatter header (`name`,
6
+ * `description`, `createdAt`). The UI lists them via `GET /projects/:id/scripts`,
7
+ * runs one via `POST /projects/:id/scripts/:name/run`, and saves a new one (e.g.
8
+ * one the agent just generated) via `POST /projects/:id/scripts`.
9
+ *
10
+ * These helpers parse the slash commands, normalize a script name into the safe
11
+ * filename base the backend expects, resolve a typed `/run` argument against the
12
+ * known scripts, filter the list for the browser, and assemble a run's raw
13
+ * output for display. They are deterministic and side-effect free so they can be
14
+ * unit tested without rendering or a real backend. Any user-facing prose
15
+ * (status labels, empty states) lives in the components via `t()`, never here —
16
+ * `formatRunOutput` returns only the command's own (untranslatable) stdout/stderr.
17
+ *
18
+ * @module
19
+ */
20
+ /** A saved project script's metadata (the body lives in the sandbox file). */
21
+ export interface ScriptInfo {
22
+ /** Script name — the `<name>` in `.agents/scripts/<name>.sh` (no extension). */
23
+ name: string;
24
+ /** One-line description (from the script's YAML frontmatter `description`). */
25
+ description: string;
26
+ /** ISO 8601 creation timestamp (frontmatter `createdAt`). */
27
+ createdAt: string;
28
+ }
29
+ /** The result of running a script via the sandbox `exec`. */
30
+ export interface ScriptRunResult {
31
+ /** Captured standard output. */
32
+ stdout: string;
33
+ /** Captured standard error. */
34
+ stderr: string;
35
+ /** Process exit code (`0` = success). */
36
+ exitCode: number;
37
+ }
38
+ /** The `POST /projects/:id/scripts` request body for saving a script. */
39
+ export interface SaveScriptPayload {
40
+ /** Normalized script name (the filename base, no `.sh`). */
41
+ name: string;
42
+ /** One-line description stored in the frontmatter header. */
43
+ description: string;
44
+ /** The shell script body. */
45
+ body: string;
46
+ }
47
+ /**
48
+ * Normalizes a raw, possibly user- or AI-supplied script name into the safe
49
+ * filename base the backend writes as `.agents/scripts/<name>.sh`: lowercased,
50
+ * a trailing `.sh` dropped, every run of disallowed characters collapsed to a
51
+ * single `-`, and leading/trailing `-` trimmed. Returns `''` when nothing usable
52
+ * remains (the caller should treat that as invalid).
53
+ *
54
+ * @param raw - The raw script name (e.g. `'Run Tests.sh'`).
55
+ * @returns The normalized base name (e.g. `'run-tests'`), or `''`.
56
+ */
57
+ export declare function normalizeScriptName(raw: string): string;
58
+ /**
59
+ * Parses a `/scripts [query]` command. Returns the (possibly empty) trimmed
60
+ * filter query when the input is the `/scripts` command, else `null`.
61
+ *
62
+ * @param input - The raw chat input.
63
+ * @returns `{ query }` when it's a `/scripts` command, else `null`.
64
+ */
65
+ export declare function parseScriptsCommand(input: string): {
66
+ query: string;
67
+ } | null;
68
+ /**
69
+ * Parses a `/run [name]` command. Returns the (possibly empty) trimmed script
70
+ * name when the input is the `/run` command, else `null`. An empty `name`
71
+ * signals `/run` was typed without an argument.
72
+ *
73
+ * @param input - The raw chat input.
74
+ * @returns `{ name }` when it's a `/run` command, else `null`.
75
+ */
76
+ export declare function parseRunCommand(input: string): {
77
+ name: string;
78
+ } | null;
79
+ /**
80
+ * Resolves a `/run` name argument against the known scripts. Tries, in order:
81
+ * exact (case-insensitive, `.sh`-insensitive) match, then a unique prefix match,
82
+ * then a unique substring match. Returns `undefined` when there is no match or
83
+ * the match is ambiguous (more than one prefix/substring candidate).
84
+ *
85
+ * @param scripts - The known scripts.
86
+ * @param name - The raw name argument (may include a `.sh` suffix).
87
+ * @returns The single matching script, or `undefined`.
88
+ */
89
+ export declare function findScriptByName(scripts: readonly ScriptInfo[], name: string): ScriptInfo | undefined;
90
+ /**
91
+ * Filters scripts by a free-text query, matching (case-insensitively) against
92
+ * the name and description. An empty/blank query returns all scripts in input
93
+ * order.
94
+ *
95
+ * @param scripts - The scripts to filter.
96
+ * @param query - The search query.
97
+ * @returns The matching scripts, in input order.
98
+ */
99
+ export declare function filterScripts(scripts: readonly ScriptInfo[], query: string): ScriptInfo[];
100
+ /**
101
+ * Assembles a run's raw output for display: stdout followed by stderr (each
102
+ * trimmed of trailing whitespace), joined by a blank line when both are present.
103
+ * Returns `''` when the run produced no output — the component decides how to
104
+ * render an empty result. Contains no translatable prose; the exit-status label
105
+ * is rendered separately by the component via `t()`.
106
+ *
107
+ * @param result - The script run result.
108
+ * @returns The combined stdout/stderr text (possibly empty).
109
+ */
110
+ export declare function formatRunOutput(result: ScriptRunResult): string;
111
+ /**
112
+ * Whether a run succeeded (exit code `0`).
113
+ *
114
+ * @param result - The script run result.
115
+ * @returns `true` when `exitCode === 0`.
116
+ */
117
+ export declare function runSucceeded(result: ScriptRunResult): boolean;
118
+ /**
119
+ * Builds the `POST /projects/:id/scripts` body from raw form/AI input,
120
+ * normalizing the name and trimming the description and body. The backend adds
121
+ * the YAML frontmatter header (`name`, `description`, `createdAt`); the body
122
+ * here is the script content only.
123
+ *
124
+ * @param input - The raw `{ name, description, body }` to save.
125
+ * @returns The normalized save payload.
126
+ */
127
+ export declare function buildSaveScriptPayload(input: {
128
+ name: string;
129
+ description: string;
130
+ body: string;
131
+ }): SaveScriptPayload;
132
+ /**
133
+ * Whether a save payload has the minimum required fields: a non-empty
134
+ * normalized name and a non-empty body.
135
+ *
136
+ * @param payload - The save payload to validate.
137
+ * @returns `true` when the payload can be saved.
138
+ */
139
+ export declare function isSaveScriptValid(payload: SaveScriptPayload): boolean;
140
+ //# sourceMappingURL=chat-scripts-utilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-scripts-utilities.d.ts","sourceRoot":"","sources":["../../src/components/chat-scripts-utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAA;IACZ,+EAA+E;IAC/E,WAAW,EAAE,MAAM,CAAA;IACnB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,yEAAyE;AACzE,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAA;IACnB,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAI3E;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAItE;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,IAAI,EAAE,MAAM,GACX,UAAU,GAAG,SAAS,CAUxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAMzF;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAK/D;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAE7D;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,iBAAiB,CAMpB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAErE"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Pure helpers backing the `/scripts` browser and the `/run <name>` command.
3
+ *
4
+ * Scripts are saved shell files under the project's `.agents/scripts/` tree
5
+ * (`.agents/scripts/<name>.sh`) carrying a YAML frontmatter header (`name`,
6
+ * `description`, `createdAt`). The UI lists them via `GET /projects/:id/scripts`,
7
+ * runs one via `POST /projects/:id/scripts/:name/run`, and saves a new one (e.g.
8
+ * one the agent just generated) via `POST /projects/:id/scripts`.
9
+ *
10
+ * These helpers parse the slash commands, normalize a script name into the safe
11
+ * filename base the backend expects, resolve a typed `/run` argument against the
12
+ * known scripts, filter the list for the browser, and assemble a run's raw
13
+ * output for display. They are deterministic and side-effect free so they can be
14
+ * unit tested without rendering or a real backend. Any user-facing prose
15
+ * (status labels, empty states) lives in the components via `t()`, never here —
16
+ * `formatRunOutput` returns only the command's own (untranslatable) stdout/stderr.
17
+ *
18
+ * @module
19
+ */
20
+ /**
21
+ * Normalizes a raw, possibly user- or AI-supplied script name into the safe
22
+ * filename base the backend writes as `.agents/scripts/<name>.sh`: lowercased,
23
+ * a trailing `.sh` dropped, every run of disallowed characters collapsed to a
24
+ * single `-`, and leading/trailing `-` trimmed. Returns `''` when nothing usable
25
+ * remains (the caller should treat that as invalid).
26
+ *
27
+ * @param raw - The raw script name (e.g. `'Run Tests.sh'`).
28
+ * @returns The normalized base name (e.g. `'run-tests'`), or `''`.
29
+ */
30
+ export function normalizeScriptName(raw) {
31
+ return raw
32
+ .trim()
33
+ .replace(/\.sh$/i, '')
34
+ .toLowerCase()
35
+ .replace(/[^a-z0-9_-]+/g, '-')
36
+ .replace(/-+/g, '-')
37
+ .replace(/^-+|-+$/g, '');
38
+ }
39
+ /**
40
+ * Parses a `/scripts [query]` command. Returns the (possibly empty) trimmed
41
+ * filter query when the input is the `/scripts` command, else `null`.
42
+ *
43
+ * @param input - The raw chat input.
44
+ * @returns `{ query }` when it's a `/scripts` command, else `null`.
45
+ */
46
+ export function parseScriptsCommand(input) {
47
+ const match = input.trim().match(/^\/scripts(?:\s+(.*))?$/i);
48
+ if (!match)
49
+ return null;
50
+ return { query: (match[1] ?? '').trim() };
51
+ }
52
+ /**
53
+ * Parses a `/run [name]` command. Returns the (possibly empty) trimmed script
54
+ * name when the input is the `/run` command, else `null`. An empty `name`
55
+ * signals `/run` was typed without an argument.
56
+ *
57
+ * @param input - The raw chat input.
58
+ * @returns `{ name }` when it's a `/run` command, else `null`.
59
+ */
60
+ export function parseRunCommand(input) {
61
+ const match = input.trim().match(/^\/run(?:\s+(.*))?$/i);
62
+ if (!match)
63
+ return null;
64
+ return { name: (match[1] ?? '').trim() };
65
+ }
66
+ /**
67
+ * Resolves a `/run` name argument against the known scripts. Tries, in order:
68
+ * exact (case-insensitive, `.sh`-insensitive) match, then a unique prefix match,
69
+ * then a unique substring match. Returns `undefined` when there is no match or
70
+ * the match is ambiguous (more than one prefix/substring candidate).
71
+ *
72
+ * @param scripts - The known scripts.
73
+ * @param name - The raw name argument (may include a `.sh` suffix).
74
+ * @returns The single matching script, or `undefined`.
75
+ */
76
+ export function findScriptByName(scripts, name) {
77
+ const q = normalizeScriptName(name);
78
+ if (!q)
79
+ return undefined;
80
+ const exact = scripts.find((s) => normalizeScriptName(s.name) === q);
81
+ if (exact)
82
+ return exact;
83
+ const prefix = scripts.filter((s) => normalizeScriptName(s.name).startsWith(q));
84
+ if (prefix.length === 1)
85
+ return prefix[0];
86
+ if (prefix.length > 1)
87
+ return undefined;
88
+ const substring = scripts.filter((s) => normalizeScriptName(s.name).includes(q));
89
+ return substring.length === 1 ? substring[0] : undefined;
90
+ }
91
+ /**
92
+ * Filters scripts by a free-text query, matching (case-insensitively) against
93
+ * the name and description. An empty/blank query returns all scripts in input
94
+ * order.
95
+ *
96
+ * @param scripts - The scripts to filter.
97
+ * @param query - The search query.
98
+ * @returns The matching scripts, in input order.
99
+ */
100
+ export function filterScripts(scripts, query) {
101
+ const q = query.trim().toLowerCase();
102
+ if (!q)
103
+ return [...scripts];
104
+ return scripts.filter((s) => s.name.toLowerCase().includes(q) || s.description.toLowerCase().includes(q));
105
+ }
106
+ /**
107
+ * Assembles a run's raw output for display: stdout followed by stderr (each
108
+ * trimmed of trailing whitespace), joined by a blank line when both are present.
109
+ * Returns `''` when the run produced no output — the component decides how to
110
+ * render an empty result. Contains no translatable prose; the exit-status label
111
+ * is rendered separately by the component via `t()`.
112
+ *
113
+ * @param result - The script run result.
114
+ * @returns The combined stdout/stderr text (possibly empty).
115
+ */
116
+ export function formatRunOutput(result) {
117
+ const out = (result.stdout ?? '').replace(/\s+$/, '');
118
+ const err = (result.stderr ?? '').replace(/\s+$/, '');
119
+ if (out && err)
120
+ return `${out}\n\n${err}`;
121
+ return out || err;
122
+ }
123
+ /**
124
+ * Whether a run succeeded (exit code `0`).
125
+ *
126
+ * @param result - The script run result.
127
+ * @returns `true` when `exitCode === 0`.
128
+ */
129
+ export function runSucceeded(result) {
130
+ return result.exitCode === 0;
131
+ }
132
+ /**
133
+ * Builds the `POST /projects/:id/scripts` body from raw form/AI input,
134
+ * normalizing the name and trimming the description and body. The backend adds
135
+ * the YAML frontmatter header (`name`, `description`, `createdAt`); the body
136
+ * here is the script content only.
137
+ *
138
+ * @param input - The raw `{ name, description, body }` to save.
139
+ * @returns The normalized save payload.
140
+ */
141
+ export function buildSaveScriptPayload(input) {
142
+ return {
143
+ name: normalizeScriptName(input.name),
144
+ description: input.description.trim(),
145
+ body: input.body.replace(/\s+$/, ''),
146
+ };
147
+ }
148
+ /**
149
+ * Whether a save payload has the minimum required fields: a non-empty
150
+ * normalized name and a non-empty body.
151
+ *
152
+ * @param payload - The save payload to validate.
153
+ * @returns `true` when the payload can be saved.
154
+ */
155
+ export function isSaveScriptValid(payload) {
156
+ return payload.name.length > 0 && payload.body.trim().length > 0;
157
+ }
158
+ //# sourceMappingURL=chat-scripts-utilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-scripts-utilities.js","sourceRoot":"","sources":["../../src/components/chat-scripts-utilities.ts"],"names":[],"mappings":"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"}