@postxl/generators 1.12.2 → 1.13.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 (126) hide show
  1. package/dist/backend-ai/ai.generator.d.ts +18 -0
  2. package/dist/backend-ai/ai.generator.js +174 -0
  3. package/dist/backend-ai/ai.generator.js.map +1 -0
  4. package/dist/backend-ai/generators/ai-agent-service.generator.d.ts +4 -0
  5. package/dist/backend-ai/generators/ai-agent-service.generator.js +264 -0
  6. package/dist/backend-ai/generators/ai-agent-service.generator.js.map +1 -0
  7. package/dist/backend-ai/generators/ai-cache-service.generator.d.ts +1 -0
  8. package/dist/backend-ai/generators/ai-cache-service.generator.js +110 -0
  9. package/dist/backend-ai/generators/ai-cache-service.generator.js.map +1 -0
  10. package/dist/backend-ai/generators/ai-config.generator.d.ts +1 -0
  11. package/dist/backend-ai/generators/ai-config.generator.js +27 -0
  12. package/dist/backend-ai/generators/ai-config.generator.js.map +1 -0
  13. package/dist/backend-ai/generators/ai-module.generator.d.ts +2 -0
  14. package/dist/backend-ai/generators/ai-module.generator.js +89 -0
  15. package/dist/backend-ai/generators/ai-module.generator.js.map +1 -0
  16. package/dist/backend-ai/generators/ai-route.generator.d.ts +1 -0
  17. package/dist/backend-ai/generators/ai-route.generator.js +29 -0
  18. package/dist/backend-ai/generators/ai-route.generator.js.map +1 -0
  19. package/dist/backend-ai/generators/ai-tools-service.generator.d.ts +4 -0
  20. package/dist/backend-ai/generators/ai-tools-service.generator.js +222 -0
  21. package/dist/backend-ai/generators/ai-tools-service.generator.js.map +1 -0
  22. package/dist/backend-ai/generators/model-provider-interface.generator.d.ts +1 -0
  23. package/dist/backend-ai/generators/model-provider-interface.generator.js +48 -0
  24. package/dist/backend-ai/generators/model-provider-interface.generator.js.map +1 -0
  25. package/dist/backend-ai/generators/openai-model-provider-service.generator.d.ts +1 -0
  26. package/dist/backend-ai/generators/openai-model-provider-service.generator.js +128 -0
  27. package/dist/backend-ai/generators/openai-model-provider-service.generator.js.map +1 -0
  28. package/dist/backend-ai/index.d.ts +4 -0
  29. package/dist/backend-ai/index.js +40 -0
  30. package/dist/backend-ai/index.js.map +1 -0
  31. package/dist/backend-core/generators/main.generator.js +4 -3
  32. package/dist/backend-core/generators/main.generator.js.map +1 -1
  33. package/dist/backend-e2e/backend-e2e.generator.js +4 -4
  34. package/dist/backend-e2e/backend-e2e.generator.js.map +1 -1
  35. package/dist/backend-import/generators/detect-delta/detect-delta-functions.generator.js +1 -1
  36. package/dist/backend-router-trpc/generators/app-routes.generator.js +3 -1
  37. package/dist/backend-router-trpc/generators/app-routes.generator.js.map +1 -1
  38. package/dist/backend-router-trpc/generators/trpc-plugin.generator.js +3 -0
  39. package/dist/backend-router-trpc/generators/trpc-plugin.generator.js.map +1 -1
  40. package/dist/backend-router-trpc/generators/trpc-router-module.generator.js +2 -1
  41. package/dist/backend-router-trpc/generators/trpc-router-module.generator.js.map +1 -1
  42. package/dist/backend-router-trpc/generators/trpc-shared.generator.js +7 -1
  43. package/dist/backend-router-trpc/generators/trpc-shared.generator.js.map +1 -1
  44. package/dist/backend-router-trpc/router-trpc.generator.d.ts +2 -1
  45. package/dist/backend-router-trpc/router-trpc.generator.js +2 -0
  46. package/dist/backend-router-trpc/router-trpc.generator.js.map +1 -1
  47. package/dist/backend-seed/seed.generator.js +10 -1
  48. package/dist/backend-seed/seed.generator.js.map +1 -1
  49. package/dist/base/template/scripts/setup.sh +9 -4
  50. package/dist/base/template/sonar-project.properties +9 -1
  51. package/dist/devops/generators/bitbucket-pipelines-yml.generator.js +1 -0
  52. package/dist/devops/generators/bitbucket-pipelines-yml.generator.js.map +1 -1
  53. package/dist/devops/generators/e2e-yml.generator.js +35 -10
  54. package/dist/devops/generators/e2e-yml.generator.js.map +1 -1
  55. package/dist/devops/generators/jenkinsfile.generator.js +25 -1
  56. package/dist/devops/generators/jenkinsfile.generator.js.map +1 -1
  57. package/dist/e2e/template/e2e/specs/example.spec.ts-snapshots/Navigate-to-homepage-and-take-snapshot-1-chromium-linux.png +0 -0
  58. package/dist/frontend-actions/actions.generator.d.ts +9 -0
  59. package/dist/frontend-actions/actions.generator.js +111 -0
  60. package/dist/frontend-actions/actions.generator.js.map +1 -0
  61. package/dist/frontend-actions/generators/ai-action-text.utils.generator.d.ts +1 -0
  62. package/dist/frontend-actions/generators/ai-action-text.utils.generator.js +52 -0
  63. package/dist/frontend-actions/generators/ai-action-text.utils.generator.js.map +1 -0
  64. package/dist/frontend-actions/generators/ai-assistant-store.generator.d.ts +1 -0
  65. package/dist/frontend-actions/generators/ai-assistant-store.generator.js +230 -0
  66. package/dist/frontend-actions/generators/ai-assistant-store.generator.js.map +1 -0
  67. package/dist/frontend-actions/generators/ai-sidebar-content.generator.d.ts +1 -0
  68. package/dist/frontend-actions/generators/ai-sidebar-content.generator.js +139 -0
  69. package/dist/frontend-actions/generators/ai-sidebar-content.generator.js.map +1 -0
  70. package/dist/frontend-actions/generators/ai-sidepane.generator.d.ts +1 -0
  71. package/dist/frontend-actions/generators/ai-sidepane.generator.js +98 -0
  72. package/dist/frontend-actions/generators/ai-sidepane.generator.js.map +1 -0
  73. package/dist/frontend-actions/generators/base-global-actions.generator.d.ts +1 -0
  74. package/dist/frontend-actions/generators/base-global-actions.generator.js +405 -0
  75. package/dist/frontend-actions/generators/base-global-actions.generator.js.map +1 -0
  76. package/dist/frontend-actions/generators/command-palette-action.generator.d.ts +1 -0
  77. package/dist/frontend-actions/generators/command-palette-action.generator.js +87 -0
  78. package/dist/frontend-actions/generators/command-palette-action.generator.js.map +1 -0
  79. package/dist/frontend-actions/generators/command-palette-store.generator.d.ts +1 -0
  80. package/dist/frontend-actions/generators/command-palette-store.generator.js +288 -0
  81. package/dist/frontend-actions/generators/command-palette-store.generator.js.map +1 -0
  82. package/dist/frontend-actions/generators/command-palette.generator.d.ts +5 -0
  83. package/dist/frontend-actions/generators/command-palette.generator.js +332 -0
  84. package/dist/frontend-actions/generators/command-palette.generator.js.map +1 -0
  85. package/dist/frontend-actions/generators/filter-utils.generator.d.ts +1 -0
  86. package/dist/frontend-actions/generators/filter-utils.generator.js +50 -0
  87. package/dist/frontend-actions/generators/filter-utils.generator.js.map +1 -0
  88. package/dist/frontend-actions/generators/sidepanel-toggle.generator.d.ts +1 -0
  89. package/dist/frontend-actions/generators/sidepanel-toggle.generator.js +37 -0
  90. package/dist/frontend-actions/generators/sidepanel-toggle.generator.js.map +1 -0
  91. package/dist/frontend-actions/index.d.ts +4 -0
  92. package/dist/frontend-actions/index.js +40 -0
  93. package/dist/frontend-actions/index.js.map +1 -0
  94. package/dist/frontend-admin/admin.generator.d.ts +3 -1
  95. package/dist/frontend-admin/admin.generator.js +8 -1
  96. package/dist/frontend-admin/admin.generator.js.map +1 -1
  97. package/dist/frontend-admin/generators/admin-global-actions.generator.d.ts +4 -0
  98. package/dist/frontend-admin/generators/admin-global-actions.generator.js +152 -0
  99. package/dist/frontend-admin/generators/admin-global-actions.generator.js.map +1 -0
  100. package/dist/frontend-admin/generators/comment-sidebar.generator.js +5 -3
  101. package/dist/frontend-admin/generators/comment-sidebar.generator.js.map +1 -1
  102. package/dist/frontend-admin/generators/detail-sidebar.generator.js +40 -24
  103. package/dist/frontend-admin/generators/detail-sidebar.generator.js.map +1 -1
  104. package/dist/frontend-admin/generators/model-admin-page.generator.js +172 -11
  105. package/dist/frontend-admin/generators/model-admin-page.generator.js.map +1 -1
  106. package/dist/frontend-admin/utils.d.ts +1 -0
  107. package/dist/frontend-admin/utils.js +1 -0
  108. package/dist/frontend-admin/utils.js.map +1 -1
  109. package/dist/frontend-core/generators/tsconfig.generator.js +1 -0
  110. package/dist/frontend-core/generators/tsconfig.generator.js.map +1 -1
  111. package/dist/frontend-core/template/.env.example +3 -0
  112. package/dist/frontend-core/template/src/components/admin/table-view-panel.tsx +22 -4
  113. package/dist/frontend-core/template/src/components/ui/color-mode-toggle/color-mode-toggle.tsx +1 -1
  114. package/dist/frontend-core/template/src/lib/color.ts +6 -3
  115. package/dist/frontend-core/template/src/lib/config.ts +3 -1
  116. package/dist/frontend-tables/generators/model-table.generator.js +13 -0
  117. package/dist/frontend-tables/generators/model-table.generator.js.map +1 -1
  118. package/dist/generators.js +4 -0
  119. package/dist/generators.js.map +1 -1
  120. package/dist/index.d.ts +2 -0
  121. package/dist/index.js +8 -2
  122. package/dist/index.js.map +1 -1
  123. package/dist/types/template/ai.types.ts +34 -0
  124. package/dist/types/types.generator.js +1 -0
  125. package/dist/types/types.generator.js.map +1 -1
  126. package/package.json +4 -4
@@ -0,0 +1,405 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateBaseGlobalActions = generateBaseGlobalActions;
4
+ function generateBaseGlobalActions() {
5
+ return `import { useAuth } from '@context-providers/auth-context-provider'
6
+ import { useTheme } from '@context-providers/theme-context-provider'
7
+ import { useMutation } from '@tanstack/react-query'
8
+ import { useNavigate } from '@tanstack/react-router'
9
+
10
+ import { useEffect } from 'react'
11
+
12
+ import { APP_CONFIG } from '@lib/config'
13
+ import { useTRPC } from '@lib/trpc'
14
+
15
+ import { formatInputValue, humanizeToken, toTitle } from './ai-action-text.utils'
16
+ import { command, waitForNextFrame } from './command-palette-action'
17
+ import { useAiAssistantActions } from './ai-assistant-store'
18
+ import { useCommandPaletteActions } from './command-palette-store'
19
+
20
+ export const useBaseGlobalActions = () => {
21
+ useNavigationActions()
22
+ useThemeActions()
23
+ useAiAssistantExecutor()
24
+ }
25
+
26
+ type DoneInput = { summary?: string }
27
+ type AskUserInput = { question?: string }
28
+ type BackendLogEntry = { text: string; status: 'done' | 'error' }
29
+
30
+ const toActionProgressText = ({
31
+ key,
32
+ label,
33
+ input,
34
+ }: {
35
+ key: string
36
+ label: string
37
+ input: unknown
38
+ }): string => {
39
+ const adminModelMatch = /^admin-([a-z0-9-]+)-/.exec(key)
40
+ const adminModel = adminModelMatch ? toTitle(humanizeToken(adminModelMatch[1])) : ''
41
+ const details = formatInputValue(input)
42
+
43
+ if (key.endsWith('-clear-all-filters')) {
44
+ return adminModel ? 'Cleaning all filters on ' + adminModel + ' table' : 'Cleaning all filters'
45
+ }
46
+
47
+ if (key.endsWith('-query-filters')) {
48
+ return adminModel ? 'Checking active filters on ' + adminModel + ' table' : 'Checking active filters'
49
+ }
50
+
51
+ if (key.endsWith('-search')) {
52
+ const base = adminModel ? 'Searching in ' + adminModel + ' table' : 'Searching'
53
+ return details ? base + ' with ' + details : base
54
+ }
55
+
56
+ if (key === 'ask-user') {
57
+ if (typeof input === 'object' && input && typeof (input as Record<string, unknown>).question === 'string') {
58
+ return 'Asking you: ' + String((input as Record<string, unknown>).question)
59
+ }
60
+ return 'Asking you for additional input'
61
+ }
62
+
63
+ if (label.toLowerCase().startsWith('filter by ')) {
64
+ const base = 'Applying ' + label.toLowerCase()
65
+ return details ? base + ' with ' + details : base
66
+ }
67
+
68
+ if (label.toLowerCase().startsWith('open ')) {
69
+ return 'Opening ' + label.slice('open '.length)
70
+ }
71
+
72
+ if (label.toLowerCase().startsWith('switch to ')) {
73
+ return 'Switching to ' + label.slice('switch to '.length)
74
+ }
75
+
76
+ if (label.toLowerCase().startsWith('use ')) {
77
+ return 'Using ' + label.slice('use '.length)
78
+ }
79
+
80
+ const base = 'Running ' + label.toLowerCase()
81
+ return details ? base + ' with ' + details : base
82
+ }
83
+
84
+ const toActionDoneText = ({
85
+ key,
86
+ label,
87
+ input,
88
+ }: {
89
+ key: string
90
+ label: string
91
+ input: unknown
92
+ }): string => {
93
+ const details = formatInputValue(input)
94
+ if (key.endsWith('-clear-all-filters')) {
95
+ return 'Filters cleared'
96
+ }
97
+ if (key.endsWith('-query-filters')) {
98
+ return 'Active filters checked'
99
+ }
100
+
101
+ const base = 'Completed: ' + label
102
+ return details ? base + ' (' + details + ')' : base
103
+ }
104
+
105
+ const extractSummary = (input: unknown): string | undefined => {
106
+ if (!isRecord(input)) {
107
+ return undefined
108
+ }
109
+
110
+ const value = input.summary
111
+ return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined
112
+ }
113
+
114
+ const parseDoneInput = (input: unknown): DoneInput | undefined => {
115
+ if (!isRecord(input)) {
116
+ return undefined
117
+ }
118
+
119
+ return input as DoneInput
120
+ }
121
+
122
+ const parseAskUserInput = (input: unknown): AskUserInput | undefined => {
123
+ if (!isRecord(input)) {
124
+ return undefined
125
+ }
126
+
127
+ return input as AskUserInput
128
+ }
129
+
130
+ const parseBackendLogEntries = (payload: unknown): BackendLogEntry[] => {
131
+ if (!isRecord(payload)) {
132
+ return []
133
+ }
134
+
135
+ const raw = payload.backendLogs
136
+ if (!Array.isArray(raw)) {
137
+ return []
138
+ }
139
+
140
+ return raw
141
+ .filter((entry): entry is Record<string, unknown> => isRecord(entry))
142
+ .map((entry) => {
143
+ const status: BackendLogEntry['status'] = entry.status === 'error' ? 'error' : 'done'
144
+ const normalized: BackendLogEntry = {
145
+ text: typeof entry.text === 'string' ? entry.text : '',
146
+ status,
147
+ }
148
+ return normalized
149
+ })
150
+ .filter((entry): entry is BackendLogEntry => entry.text.length > 0)
151
+ }
152
+
153
+ const isRecord = (value: unknown): value is Record<string, unknown> =>
154
+ typeof value === 'object' && value !== null && !Array.isArray(value)
155
+
156
+ const appendBackendLogs = (
157
+ payload: unknown,
158
+ addEvent: (entry: { kind: 'system'; text: string; status: 'done' | 'error' }) => string,
159
+ ) => {
160
+ for (const entry of parseBackendLogEntries(payload)) {
161
+ addEvent({
162
+ kind: 'system',
163
+ text: entry.text,
164
+ status: entry.status,
165
+ })
166
+ }
167
+ }
168
+
169
+ const useNavigationActions = () => {
170
+ const navigate = useNavigate()
171
+ const { registerGlobalActions } = useCommandPaletteActions()
172
+ const { setOpen } = useAiAssistantActions()
173
+
174
+ useEffect(() => {
175
+ const actions = [
176
+ command({
177
+ key: 'navigate-dashboard',
178
+ visibility: 'visible',
179
+ group: 'Navigate',
180
+ label: 'Dashboard',
181
+ run: async () => {
182
+ await navigate({ to: '/dashboard' })
183
+ await waitForNextFrame()
184
+ return { kind: 'close' }
185
+ },
186
+ }),
187
+ ]
188
+
189
+ if (APP_CONFIG.enableAI) {
190
+ actions.push(
191
+ command({
192
+ key: 'open-ai-assistant',
193
+ visibility: 'visible',
194
+ group: 'Navigate',
195
+ label: 'Open AI assistant',
196
+ run: async () => {
197
+ setOpen(true)
198
+ await waitForNextFrame()
199
+ return { kind: 'close' }
200
+ },
201
+ }),
202
+ )
203
+ }
204
+
205
+ registerGlobalActions(...actions)
206
+ }, [navigate, registerGlobalActions, setOpen])
207
+ }
208
+
209
+ const useThemeActions = () => {
210
+ const { setColorMode } = useTheme()
211
+ const { registerGlobalActions } = useCommandPaletteActions()
212
+
213
+ useEffect(() => {
214
+ registerGlobalActions(
215
+ command({
216
+ key: 'set-theme-dark',
217
+ visibility: 'visible',
218
+ group: 'Appearance',
219
+ label: 'Switch to dark mode',
220
+ run: async () => {
221
+ setColorMode('dark')
222
+ await waitForNextFrame()
223
+ return { kind: 'close' }
224
+ },
225
+ }),
226
+ command({
227
+ key: 'set-theme-light',
228
+ visibility: 'visible',
229
+ group: 'Appearance',
230
+ label: 'Switch to light mode',
231
+ run: async () => {
232
+ setColorMode('light')
233
+ await waitForNextFrame()
234
+ return { kind: 'close' }
235
+ },
236
+ }),
237
+ command({
238
+ key: 'set-theme-system',
239
+ visibility: 'visible',
240
+ group: 'Appearance',
241
+ label: 'Use system theme',
242
+ run: async () => {
243
+ setColorMode('system')
244
+ await waitForNextFrame()
245
+ return { kind: 'close' }
246
+ },
247
+ }),
248
+ )
249
+ }, [registerGlobalActions, setColorMode])
250
+ }
251
+
252
+ const useAiAssistantExecutor = () => {
253
+ const trpc = useTRPC()
254
+ const { mutateAsync: startAiExecution } = useMutation(trpc.ai.ask.mutationOptions())
255
+ const { mutateAsync: nextAiExecution } = useMutation(trpc.ai.step.mutationOptions())
256
+ const { mutateAsync: cancelAiExecution } = useMutation(trpc.ai.cancel.mutationOptions())
257
+
258
+ const { loginState } = useAuth()
259
+ const { calculateAvailableLLMActions, reset, select } = useCommandPaletteActions()
260
+ const { setExecutor } = useAiAssistantActions()
261
+
262
+ useEffect(() => {
263
+ if (!APP_CONFIG.enableAI || loginState !== 'loggedIn') {
264
+ setExecutor(null)
265
+ return
266
+ }
267
+
268
+ setExecutor(async (task, { signal, addEvent, patchEvent, requestUserInput }) => {
269
+ signal.throwIfAborted()
270
+
271
+ const askUserToolKey = 'ask-user'
272
+ const lookupAction = (key: string) =>
273
+ key === askUserToolKey ? { key: askUserToolKey, label: 'Ask user for input' } : calculateAvailableLLMActions().find((action) => action.key === key)
274
+
275
+ const availableTools = () =>
276
+ [
277
+ ...calculateAvailableLLMActions().map((action) => ({
278
+ key: action.key,
279
+ kind: action.kind,
280
+ label: action.label,
281
+ target: 'frontend' as const,
282
+ inputSchema: action.inputSchema?.toJSONSchema(),
283
+ })),
284
+ {
285
+ key: askUserToolKey,
286
+ kind: 'input' as const,
287
+ label: 'Ask user for input',
288
+ target: 'frontend' as const,
289
+ inputSchema: {
290
+ type: 'object',
291
+ properties: {
292
+ question: { type: 'string' },
293
+ },
294
+ required: ['question'],
295
+ },
296
+ },
297
+ ].map((action) => ({
298
+ key: action.key,
299
+ kind: action.kind,
300
+ label: action.label,
301
+ inputSchema: action.inputSchema,
302
+ }))
303
+
304
+ const first = await startAiExecution({ task, tools: availableTools() })
305
+ let current = first
306
+ appendBackendLogs(first, addEvent)
307
+
308
+ while (current && current.key !== 'done') {
309
+ signal.throwIfAborted()
310
+
311
+ const matchedAction = lookupAction(current.key)
312
+ const actionLabel = matchedAction?.label ?? humanizeToken(current.key)
313
+ const runningText = toActionProgressText({
314
+ key: current.key,
315
+ label: actionLabel,
316
+ input: current.input,
317
+ })
318
+
319
+ const actionEventId = addEvent({
320
+ kind: 'action',
321
+ status: 'running',
322
+ text: runningText,
323
+ })
324
+
325
+ try {
326
+ if (current.key === askUserToolKey) {
327
+ const askUserInput = parseAskUserInput(current.input)
328
+ const question =
329
+ typeof askUserInput?.question === 'string' && askUserInput.question.trim().length > 0
330
+ ? askUserInput.question.trim()
331
+ : 'Please provide more details so I can continue.'
332
+ patchEvent(actionEventId, {
333
+ status: 'running',
334
+ text: 'Waiting for your input: ' + question,
335
+ })
336
+
337
+ const answer = await requestUserInput(question)
338
+ patchEvent(actionEventId, {
339
+ status: 'done',
340
+ text: 'Received your input',
341
+ })
342
+
343
+ current = await nextAiExecution({
344
+ conversation: current.conversation,
345
+ output: { answer },
346
+ tools: availableTools(),
347
+ })
348
+ appendBackendLogs(current, addEvent)
349
+ continue
350
+ }
351
+
352
+ const result = await select(current.key, signal, '', current.input ?? {})
353
+
354
+ const doneText = toActionDoneText({
355
+ key: current.key,
356
+ label: actionLabel,
357
+ input: current.input,
358
+ })
359
+
360
+ patchEvent(actionEventId, {
361
+ status: 'done',
362
+ text: doneText,
363
+ })
364
+
365
+ current = await nextAiExecution({
366
+ conversation: current.conversation,
367
+ output: result.kind === 'page' ? undefined : result.output,
368
+ tools: availableTools(),
369
+ })
370
+ appendBackendLogs(current, addEvent)
371
+ } catch (error) {
372
+ patchEvent(actionEventId, {
373
+ status: 'error',
374
+ text: 'Failed: ' + actionLabel,
375
+ })
376
+
377
+ await cancelAiExecution({ conversation: current.conversation })
378
+ throw error
379
+ }
380
+ }
381
+
382
+ reset()
383
+
384
+ const summary = extractSummary(parseDoneInput(current?.input)) ?? 'Task completed.'
385
+
386
+ return { summary }
387
+ })
388
+
389
+ return () => {
390
+ setExecutor(null)
391
+ }
392
+ }, [
393
+ calculateAvailableLLMActions,
394
+ cancelAiExecution,
395
+ loginState,
396
+ nextAiExecution,
397
+ reset,
398
+ select,
399
+ setExecutor,
400
+ startAiExecution,
401
+ ])
402
+ }
403
+ `;
404
+ }
405
+ //# sourceMappingURL=base-global-actions.generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-global-actions.generator.js","sourceRoot":"","sources":["../../../src/frontend-actions/generators/base-global-actions.generator.ts"],"names":[],"mappings":";;AAAA,8DAgZC;AAhZD,SAAgB,yBAAyB;IACvC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8YR,CAAA;AACD,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function generateCommandPaletteAction(): string;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateCommandPaletteAction = generateCommandPaletteAction;
4
+ function generateCommandPaletteAction() {
5
+ return `import { z } from 'zod'
6
+
7
+ export type CommandPaletteActionPage = {
8
+ label?: string
9
+ actions: CommandPaletteAction[]
10
+ back?: CommandPaletteActionPage
11
+ }
12
+
13
+ export type CommandPaletteActionVisibility = 'visible' | 'llm' | 'user'
14
+
15
+ export type CommandPaletteActionResult =
16
+ | ({ kind: 'page' } & CommandPaletteActionPage)
17
+ | { kind: 'output'; output: Record<string, unknown> }
18
+ | { kind: 'close'; output?: Record<string, unknown> }
19
+ | { kind: 'continue'; output?: Record<string, unknown> }
20
+
21
+ export type CommandPaletteAction = {
22
+ kind: 'command' | 'input'
23
+ key: string
24
+ label: string
25
+ icon?: React.ReactNode
26
+ visibility: CommandPaletteActionVisibility
27
+ group?: string
28
+ keywords?: string[]
29
+ suggestions?: string[]
30
+ inputSchema?: z.ZodSchema
31
+ run: (
32
+ query: string,
33
+ input: unknown,
34
+ signal: AbortSignal,
35
+ render: (component: React.FC | null) => void,
36
+ ) => Promise<CommandPaletteActionResult>
37
+ }
38
+
39
+ const zInputQuery = z.object({ query: z.string() })
40
+
41
+ export const command = (action: Omit<CommandPaletteAction, 'kind'>): CommandPaletteAction => {
42
+ const key = sanitizeKey(action.key)
43
+
44
+ return {
45
+ ...action,
46
+ key,
47
+ keywords: [...key.split('-'), ...(action.keywords ?? [])],
48
+ kind: 'command',
49
+ }
50
+ }
51
+
52
+ export const input = (action: Omit<CommandPaletteAction, 'kind'>): CommandPaletteAction => {
53
+ const key = sanitizeKey(action.key)
54
+
55
+ return {
56
+ ...action,
57
+ key,
58
+ keywords: [...key.split('-'), ...(action.keywords ?? [])],
59
+ kind: 'input',
60
+ inputSchema: action.inputSchema ?? zInputQuery,
61
+ run: action.inputSchema
62
+ ? action.run
63
+ : async (query, input, signal, render) => {
64
+ const parsed = zInputQuery.safeParse(input)
65
+ if (parsed.success) {
66
+ return action.run(parsed.data.query, parsed.data, signal, render)
67
+ }
68
+
69
+ return action.run(query, { query }, signal, render)
70
+ },
71
+ }
72
+ }
73
+
74
+ export const waitForNextFrame = async () => {
75
+ await new Promise((resolve) => requestAnimationFrame(() => resolve(undefined)))
76
+ }
77
+
78
+ const sanitizeKey = (value: string): string =>
79
+ value
80
+ .trim()
81
+ .toLowerCase()
82
+ .replaceAll(/[^a-z0-9-]+/g, '-')
83
+ .replaceAll(/-{2,}/g, '-')
84
+ .replaceAll(/(^-+)|(-+$)/g, '')
85
+ `;
86
+ }
87
+ //# sourceMappingURL=command-palette-action.generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-palette-action.generator.js","sourceRoot":"","sources":["../../../src/frontend-actions/generators/command-palette-action.generator.ts"],"names":[],"mappings":";;AAAA,oEAkFC;AAlFD,SAAgB,4BAA4B;IAC1C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgFR,CAAA;AACD,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function generateCommandPaletteStore(): string;