@postxl/generators 1.12.3 → 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.
- package/dist/backend-ai/ai.generator.d.ts +18 -0
- package/dist/backend-ai/ai.generator.js +174 -0
- package/dist/backend-ai/ai.generator.js.map +1 -0
- package/dist/backend-ai/generators/ai-agent-service.generator.d.ts +4 -0
- package/dist/backend-ai/generators/ai-agent-service.generator.js +264 -0
- package/dist/backend-ai/generators/ai-agent-service.generator.js.map +1 -0
- package/dist/backend-ai/generators/ai-cache-service.generator.d.ts +1 -0
- package/dist/backend-ai/generators/ai-cache-service.generator.js +110 -0
- package/dist/backend-ai/generators/ai-cache-service.generator.js.map +1 -0
- package/dist/backend-ai/generators/ai-config.generator.d.ts +1 -0
- package/dist/backend-ai/generators/ai-config.generator.js +27 -0
- package/dist/backend-ai/generators/ai-config.generator.js.map +1 -0
- package/dist/backend-ai/generators/ai-module.generator.d.ts +2 -0
- package/dist/backend-ai/generators/ai-module.generator.js +89 -0
- package/dist/backend-ai/generators/ai-module.generator.js.map +1 -0
- package/dist/backend-ai/generators/ai-route.generator.d.ts +1 -0
- package/dist/backend-ai/generators/ai-route.generator.js +29 -0
- package/dist/backend-ai/generators/ai-route.generator.js.map +1 -0
- package/dist/backend-ai/generators/ai-tools-service.generator.d.ts +4 -0
- package/dist/backend-ai/generators/ai-tools-service.generator.js +222 -0
- package/dist/backend-ai/generators/ai-tools-service.generator.js.map +1 -0
- package/dist/backend-ai/generators/model-provider-interface.generator.d.ts +1 -0
- package/dist/backend-ai/generators/model-provider-interface.generator.js +48 -0
- package/dist/backend-ai/generators/model-provider-interface.generator.js.map +1 -0
- package/dist/backend-ai/generators/openai-model-provider-service.generator.d.ts +1 -0
- package/dist/backend-ai/generators/openai-model-provider-service.generator.js +128 -0
- package/dist/backend-ai/generators/openai-model-provider-service.generator.js.map +1 -0
- package/dist/backend-ai/index.d.ts +4 -0
- package/dist/backend-ai/index.js +40 -0
- package/dist/backend-ai/index.js.map +1 -0
- package/dist/backend-core/generators/main.generator.js +4 -3
- package/dist/backend-core/generators/main.generator.js.map +1 -1
- package/dist/backend-e2e/backend-e2e.generator.js +4 -4
- package/dist/backend-e2e/backend-e2e.generator.js.map +1 -1
- package/dist/backend-import/generators/detect-delta/detect-delta-functions.generator.js +1 -1
- package/dist/backend-router-trpc/generators/app-routes.generator.js +3 -1
- package/dist/backend-router-trpc/generators/app-routes.generator.js.map +1 -1
- package/dist/backend-router-trpc/generators/trpc-plugin.generator.js +3 -0
- package/dist/backend-router-trpc/generators/trpc-plugin.generator.js.map +1 -1
- package/dist/backend-router-trpc/generators/trpc-router-module.generator.js +2 -1
- package/dist/backend-router-trpc/generators/trpc-router-module.generator.js.map +1 -1
- package/dist/backend-router-trpc/generators/trpc-shared.generator.js +7 -1
- package/dist/backend-router-trpc/generators/trpc-shared.generator.js.map +1 -1
- package/dist/backend-router-trpc/router-trpc.generator.d.ts +2 -1
- package/dist/backend-router-trpc/router-trpc.generator.js +2 -0
- package/dist/backend-router-trpc/router-trpc.generator.js.map +1 -1
- package/dist/backend-seed/seed.generator.js +10 -1
- package/dist/backend-seed/seed.generator.js.map +1 -1
- package/dist/base/template/scripts/setup.sh +9 -4
- package/dist/base/template/sonar-project.properties +9 -1
- package/dist/devops/generators/bitbucket-pipelines-yml.generator.js +1 -0
- package/dist/devops/generators/bitbucket-pipelines-yml.generator.js.map +1 -1
- package/dist/devops/generators/e2e-yml.generator.js +35 -10
- package/dist/devops/generators/e2e-yml.generator.js.map +1 -1
- package/dist/devops/generators/jenkinsfile.generator.js +25 -1
- package/dist/devops/generators/jenkinsfile.generator.js.map +1 -1
- package/dist/e2e/template/e2e/specs/example.spec.ts-snapshots/Navigate-to-homepage-and-take-snapshot-1-chromium-linux.png +0 -0
- package/dist/frontend-actions/actions.generator.d.ts +9 -0
- package/dist/frontend-actions/actions.generator.js +111 -0
- package/dist/frontend-actions/actions.generator.js.map +1 -0
- package/dist/frontend-actions/generators/ai-action-text.utils.generator.d.ts +1 -0
- package/dist/frontend-actions/generators/ai-action-text.utils.generator.js +52 -0
- package/dist/frontend-actions/generators/ai-action-text.utils.generator.js.map +1 -0
- package/dist/frontend-actions/generators/ai-assistant-store.generator.d.ts +1 -0
- package/dist/frontend-actions/generators/ai-assistant-store.generator.js +230 -0
- package/dist/frontend-actions/generators/ai-assistant-store.generator.js.map +1 -0
- package/dist/frontend-actions/generators/ai-sidebar-content.generator.d.ts +1 -0
- package/dist/frontend-actions/generators/ai-sidebar-content.generator.js +139 -0
- package/dist/frontend-actions/generators/ai-sidebar-content.generator.js.map +1 -0
- package/dist/frontend-actions/generators/ai-sidepane.generator.d.ts +1 -0
- package/dist/frontend-actions/generators/ai-sidepane.generator.js +98 -0
- package/dist/frontend-actions/generators/ai-sidepane.generator.js.map +1 -0
- package/dist/frontend-actions/generators/base-global-actions.generator.d.ts +1 -0
- package/dist/frontend-actions/generators/base-global-actions.generator.js +405 -0
- package/dist/frontend-actions/generators/base-global-actions.generator.js.map +1 -0
- package/dist/frontend-actions/generators/command-palette-action.generator.d.ts +1 -0
- package/dist/frontend-actions/generators/command-palette-action.generator.js +87 -0
- package/dist/frontend-actions/generators/command-palette-action.generator.js.map +1 -0
- package/dist/frontend-actions/generators/command-palette-store.generator.d.ts +1 -0
- package/dist/frontend-actions/generators/command-palette-store.generator.js +288 -0
- package/dist/frontend-actions/generators/command-palette-store.generator.js.map +1 -0
- package/dist/frontend-actions/generators/command-palette.generator.d.ts +5 -0
- package/dist/frontend-actions/generators/command-palette.generator.js +332 -0
- package/dist/frontend-actions/generators/command-palette.generator.js.map +1 -0
- package/dist/frontend-actions/generators/filter-utils.generator.d.ts +1 -0
- package/dist/frontend-actions/generators/filter-utils.generator.js +50 -0
- package/dist/frontend-actions/generators/filter-utils.generator.js.map +1 -0
- package/dist/frontend-actions/generators/sidepanel-toggle.generator.d.ts +1 -0
- package/dist/frontend-actions/generators/sidepanel-toggle.generator.js +37 -0
- package/dist/frontend-actions/generators/sidepanel-toggle.generator.js.map +1 -0
- package/dist/frontend-actions/index.d.ts +4 -0
- package/dist/frontend-actions/index.js +40 -0
- package/dist/frontend-actions/index.js.map +1 -0
- package/dist/frontend-admin/admin.generator.d.ts +3 -1
- package/dist/frontend-admin/admin.generator.js +8 -1
- package/dist/frontend-admin/admin.generator.js.map +1 -1
- package/dist/frontend-admin/generators/admin-global-actions.generator.d.ts +4 -0
- package/dist/frontend-admin/generators/admin-global-actions.generator.js +152 -0
- package/dist/frontend-admin/generators/admin-global-actions.generator.js.map +1 -0
- package/dist/frontend-admin/generators/detail-sidebar.generator.js +44 -32
- package/dist/frontend-admin/generators/detail-sidebar.generator.js.map +1 -1
- package/dist/frontend-admin/generators/model-admin-page.generator.js +172 -11
- package/dist/frontend-admin/generators/model-admin-page.generator.js.map +1 -1
- package/dist/frontend-admin/utils.d.ts +1 -0
- package/dist/frontend-admin/utils.js +1 -0
- package/dist/frontend-admin/utils.js.map +1 -1
- package/dist/frontend-core/generators/tsconfig.generator.js +1 -0
- package/dist/frontend-core/generators/tsconfig.generator.js.map +1 -1
- package/dist/frontend-core/template/.env.example +3 -0
- package/dist/frontend-core/template/src/components/ui/color-mode-toggle/color-mode-toggle.tsx +1 -1
- package/dist/frontend-core/template/src/lib/color.ts +6 -3
- package/dist/frontend-core/template/src/lib/config.ts +3 -1
- package/dist/generators.js +4 -0
- package/dist/generators.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/types/template/ai.types.ts +34 -0
- package/dist/types/types.generator.js +1 -0
- package/dist/types/types.generator.js.map +1 -1
- 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;
|