Skip to content

Commit b794f2c

Browse files
committed
add support for warnings
1 parent 2100ea0 commit b794f2c

File tree

6 files changed

+78
-24
lines changed

6 files changed

+78
-24
lines changed

docs-website/src/lib/edit-tool.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,14 @@ export function isStrReplaceParameterComplete(
7171

7272
// Export callback argument types
7373
export type ValidateNewContentArgs = { githubPath: string; content: string }
74+
export type ValidateNewContentResult = { error?: string; warning?: string } | undefined
7475
export type GetPageContentArgs = { githubPath: string }
7576

7677
export function createEditExecute({
7778
fileSystem,
7879
validateNewContent,
7980
}: {
80-
validateNewContent?: (x: ValidateNewContentArgs) => any
81+
validateNewContent?: (x: ValidateNewContentArgs) => Promise<ValidateNewContentResult>
8182
fileSystem: FileSystemEmulator
8283
}) {
8384
const previousEdits = [] as FileUpdate[]
@@ -158,16 +159,20 @@ export function createEditExecute({
158159
githubPath: path,
159160
content: file_text,
160161
})
161-
if (result && result.error) {
162+
if (result?.error) {
162163
return {
163164
success: false,
164-
error: `result content is invalid: create: ${result.error}`,
165+
error: `Page not created! The page creation failed with the following error:\n${result.error}`,
165166
}
166167
}
168+
if (result?.warning) {
169+
await fileSystem.write(path, file_text)
170+
return `Page created with following warning, fix it:\n${result.warning}\n\nFile content:\n\n${file_text}`
171+
}
167172
} catch (e: any) {
168173
return {
169174
success: false,
170-
error: e && e.message ? e.message : String(e),
175+
error: `Page not created! The page creation failed with the following error:\n${e && e.message ? e.message : String(e)}`,
171176
}
172177
}
173178
}
@@ -220,18 +225,20 @@ export function createEditExecute({
220225
// }
221226
// }
222227
const replacedContent = currentContent.replace(old_str, new_str)
228+
let warning: string | undefined
223229
if (validateNewContent) {
224230
try {
225231
const result = await validateNewContent({
226232
githubPath: path,
227233
content: replacedContent,
228234
})
229-
if (result && result.error) {
235+
if (result?.error) {
230236
return {
231237
success: false,
232238
error: `result content is invalid: str_replace: ${result.error}`,
233239
}
234240
}
241+
warning = result?.warning
235242
} catch (e: any) {
236243
return {
237244
success: false,
@@ -256,6 +263,9 @@ export function createEditExecute({
256263
if (occurrences > 1) {
257264
result += `, notice that you replaced more than one match, if that was not desired undo the change or add back the old content you want to keep`
258265
}
266+
if (warning) {
267+
result += `\n\nWarning: ${warning}`
268+
}
259269
result += `\n\n${cleanPatch}`
260270
return result
261271
}
@@ -295,18 +305,20 @@ export function createEditExecute({
295305
const insertAt = Math.min(insert_line, lines.length)
296306
lines.splice(insertAt, 0, new_str)
297307
const newContent = lines.join('\n')
308+
let warning: string | undefined
298309
if (validateNewContent) {
299310
try {
300311
const result = await validateNewContent({
301312
githubPath: path,
302313
content: newContent,
303314
})
304-
if (result && result.error) {
315+
if (result?.error) {
305316
return {
306317
success: false,
307318
error: `result content is invalid: insert: ${result.error}`,
308319
}
309320
}
321+
warning = result?.warning
310322
} catch (e: any) {
311323
return {
312324
success: false,
@@ -327,7 +339,12 @@ export function createEditExecute({
327339
/\\ No newline at end of file\n?/g,
328340
'',
329341
)
330-
return `Here is the diff of the changes made:\n\n${cleanPatch}`
342+
let result = `Here is the diff of the changes made`
343+
if (warning) {
344+
result += `\n\nWarning: ${warning}`
345+
}
346+
result += `:\n\n${cleanPatch}`
347+
return result
331348
}
332349
case 'undo_edit': {
333350
const previous = previousEdits.pop()
@@ -345,7 +362,7 @@ export function createEditExecute({
345362
githubPath: path,
346363
content: previous.content,
347364
})
348-
if (result && result.error) {
365+
if (result?.error) {
349366
return {
350367
success: false,
351368
error: `result content is invalid: undo_edit: ${result.error}`,
@@ -387,7 +404,7 @@ export function createEditTool({
387404
model,
388405
}: {
389406
fileSystem: FileSystemEmulator
390-
validateNewContent?: (x: ValidateNewContentArgs) => any
407+
validateNewContent?: (x: ValidateNewContentArgs) => Promise<ValidateNewContentResult>
391408
model?: { provider?: string }
392409
}) {
393410
const execute = createEditExecute({

website/src/lib/spiceflow-generate-message.tsx

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import {
4444
editToolParamsSchema,
4545
fileUpdateSchema,
4646
type FileUpdate,
47+
type ValidateNewContentResult,
4748
} from 'docs-website/src/lib/edit-tool'
4849
import { FileSystemEmulator } from './file-system-emulator'
4950
import { notifyError } from './errors'
@@ -91,6 +92,7 @@ export async function generateSystemMessage({
9192
await import('../prompts/css-variables.md?raw').then((x) => x.default),
9293
await import('../prompts/frontmatter.md?raw').then((x) => x.default),
9394
await import('../prompts/gitchamber.md?raw').then((x) => x.default),
95+
await import('../prompts/migrating.md?raw').then((x) => x.default),
9496
dedent`
9597
## fumabase.jsonc
9698
@@ -347,22 +349,23 @@ export async function* generateMessageStream({
347349
const strReplaceEditor = createEditTool({
348350
fileSystem,
349351
model: { provider: model.provider },
350-
async validateNewContent(x) {
352+
async validateNewContent(x): Promise<ValidateNewContentResult> {
351353
if (githubFolder && !x.githubPath.startsWith(githubFolder)) {
352-
throw new Error(
353-
`githubPath should always start with ${githubFolder}. This site is in ${githubFolder} base directory`,
354-
)
354+
return {
355+
error: `githubPath should always start with ${githubFolder}. This site is in ${githubFolder} base directory`,
356+
}
355357
}
358+
359+
let warning: string | undefined
360+
356361
if (mdxOrMdRegex.test(x.githubPath)) {
357362
const parsed = fm(x.content)
358363
const frontmatter = parsed.attributes as any
359364

360365
if (frontmatter && frontmatter.icon) {
361366
const iconName = String(frontmatter.icon)
362367
if (!isValidLucideIconName(iconName)) {
363-
throw new Error(
364-
`you used an invalid icon "${iconName}", to see the possible icons fetch the url https://fumabase.com/lucide-icons.json`,
365-
)
368+
warning = `you used an invalid icon "${iconName}", to see the possible icons fetch the url https://fumabase.com/lucide-icons.json`
366369
}
367370
}
368371
}
@@ -414,27 +417,29 @@ export async function* generateMessageStream({
414417
If you want to reference a page you plan to create later, first create it with empty content and only frontmatter
415418
`
416419

417-
throw createFormattedError(
420+
const errorMessage = createFormattedError(
418421
linkError,
419422
x.content,
420423
'Link Validation Error',
421424
additionalMessage,
422425
)
426+
return { error: errorMessage.message }
423427
}
424428
} catch (error: any) {
425429
if (
426430
error?.line != null ||
427431
error.position?.start?.line != null
428432
) {
429433
// Format MDX compilation errors
430-
throw createFormattedError(
434+
const errorMessage = createFormattedError(
431435
error as ErrorWithPosition,
432436
x.content,
433437
'MDX Compilation Error',
434438
'Please fix the MDX syntax error and submit the tool call again.',
435439
)
440+
return { error: errorMessage.message }
436441
}
437-
throw error
442+
return { error: error.message || String(error) }
438443
}
439444
}
440445
if (x.githubPath.endsWith('.json')) {
@@ -460,14 +465,18 @@ export async function* generateMessageStream({
460465
jsonError.line = line
461466
jsonError.column = column
462467

463-
throw createFormattedError(
468+
const errorMessage = createFormattedError(
464469
jsonError,
465470
x.content,
466471
'JSON Parse Error',
467472
'Please fix the JSON syntax error and submit the tool call again.',
468473
)
474+
return { error: errorMessage.message }
469475
}
470476
}
477+
478+
// Return warning if we found one, or undefined if everything is ok
479+
return warning ? { warning } : undefined
471480
},
472481
})
473482

@@ -503,7 +512,7 @@ export async function* generateMessageStream({
503512
githubFolder || '.',
504513
'fumabase.jsonc',
505514
),
506-
title: 'Use the renderForm tool to update these values',
515+
title: 'Use the updateFumabaseJsonc tool to update these values',
507516
})
508517
// filePaths.push({ path: 'styles.css', title: 'The CSS styles for the website. Only update this file for advanced CSS customisations' })
509518
return printDirectoryTree({

website/src/prompts/agent.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ You are a professional docs content writer
22

33
You have access to tools to edit and create files in the project.
44

5-
DO NOT THINK too much
5+
DO NOT THINK.
6+
7+
when the user asks you to do something never reply with `ok, i will do ..., proceed?`. JUST do the thing the user asked you without waiting for confirmation.
68

79
You do not have access to terminal commands. You are not in a sandbox terminal environment, you cannot run bash commands or use a filesystem. You instead have to use the tools available to edit files. DO NOT USE bash commands.
810

website/src/prompts/migrating.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
## migrating existing websites to fumabase
2+
3+
the user will sometimes ask to use an existing website as the source of a new fumabase website
4+
5+
you will have to migrate the pages from the existing website to fumabase. create a new .mdx page for each page from the old website.
6+
7+
when migrating existing websites, when the user provides you a url of existing website, here is the procedure to follow
8+
9+
- try to fetch the docs website sitemap. this can usually be done fetching /sitemap.xml and following the references with more fetch calls. only consider the results related to the docs website
10+
- sometimes docs websites providers like Mintlify or GitBook expose the website markdown directly in the website if you append .md to the url query. Try doing this to get up to date markdown
11+
- Some docs websites are stored in a GitHub repository using markdown files. You can find the GitHub repository by reading the page HTML and looking for "Edit this page on GitHub" links, these will point to the github repository and file of the current markdown file there. If you find links like these you can use gitchamber to read the files in the repository and read them to migrate them to fumabase.
12+
- If you can't find the source markdown for the pages your only way to migrate the pages will be to manually convert the html to markdown and migrate the pages this way, this should be done as a last resort
13+
14+
NEVER leave comments like `(content continues, converted fully)`. ALWAYS migrate the full content of a page! If the content is too long for a single tool call split the `strReplaceEditor` `insert` tool calls into many calls that append a section of valid markdown each.
15+
16+
when migrating an existing website never add the pages in a folder like `gitbook` or `migrated-website`. Replicate the website structure exactly like the old website, putting pages in the root level folder. NEVER put the migrated pages in a single folder.
17+
18+
### migrating existing .md to fumabase mdx
19+
20+
you may need to fix the pages being migrated, sometimes it's not possible to just copy them as is directly into a fumabase mdx document.
21+
22+
here are the things you may need to do when migrating old website pages to fumabase
23+
- convert missing mdx components to ones that are available in fumabase (Notice fumabase implements basically all Mintlify components so this should not be necessary in that case)
24+
- remove html style comments when creating .mdx pages. mdx uses js style comments like `{/* comment */}` instead of `<-- comment -->`
25+
- if a page is using `<iframe>` elements to display media or videos (urls ends with .mp4 for example) use the video html tag instead of iframe.
26+
27+
28+
IMPORTANT: when migrating a page from an existing website do not add this information in the prompt in the frontmatter. Leave the frontmatter prompt in that case

website/src/routes/org.$orgId.site.$siteId.chat.$chatId.create-pr.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ export async function loader({
141141
}: Route.LoaderArgs) {
142142
const { userId } = await getSession({ request })
143143

144-
// Return a promise that will resolve with the PR URL
145144
const prPromise = createPrSuggestionForChat({
146145
chatId,
147146
userId,

website/src/routes/org.$orgId.site.$siteId.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ export async function loader({
2323
throw new Error('Request aborted')
2424
}
2525

26-
// TODO change params to be branchId instead of siteId! then get the branch here
2726
const [site, chatHistory, siteBranches] = await Promise.all([
2827
prisma.site.findUnique({
2928
where: {

0 commit comments

Comments
 (0)