Skip to content

Commit

Permalink
ai cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
YousefED committed Oct 17, 2023
1 parent b320e1d commit 699310f
Show file tree
Hide file tree
Showing 12 changed files with 75 additions and 151 deletions.
7 changes: 5 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/editor/src/integrations/ai/openai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export async function queryOpenAI(parameters: {

const openai = new OpenAI({
apiKey: key,
// this should be ok as we are not exposing any keys
dangerouslyAllowBrowser: true,
});

Expand Down
3 changes: 2 additions & 1 deletion packages/frame/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"typescript": "5.0.4",
"vscode-lib": "^0.1.2",
"y-protocols": "^1.0.5",
"yjs": "^13.6.4"
"yjs": "^13.6.4",
"y-prosemirror": "^1.0.20"
},
"devDependencies": {
"cross-fetch": "^4.0.0",
Expand Down
76 changes: 34 additions & 42 deletions packages/frame/src/Frame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,20 @@ const originalItems = [
...getDefaultReactSlashMenuItems(),
{
name: "Code block",
execute: (editor: any) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
execute: (editor: BlockNoteEditor<any>) =>
insertOrUpdateBlock(editor, {
type: "codeblock",
} as any),
}),
aliases: ["code"],
hint: "Add a live code block",
group: "Code",
icon: <RiCodeSSlashFill size={18} />,
},
{
name: "Inline",
execute: (editor: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
execute: (editor: BlockNoteEditor<any>) => {
// state.tr.replaceSelectionWith(dinoType.create({type}))
const node = editor._tiptapEditor.schema.node(
"inlineCode",
Expand Down Expand Up @@ -293,88 +295,77 @@ export const Frame: React.FC<Props> = observer((props) => {
[props.documentIdString, monaco],
);

console.log("size", editorStore.current.customBlocks.size);
slashMenuItems.splice(
originalItems.length,
slashMenuItems.length,
{
name: "AI",
// eslint-disable-next-line @typescript-eslint/no-explicit-any
execute: async (editor: BlockNoteEditor<any>) => {
const p = prompt("AI");
const p = prompt("What would you like TypeCell AI to do?");
if (!p) {
return;
}

const commands = await getAICode(
p!,
p,
tools.newExecutionHost,
editor,
editorStore.current!,
editorStore.current,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
connectionMethods.current!.queryLLM,
);
// debugger;
// const commands = [
// {
// // afterId: "3d70d0b1-02d7-4103-b145-452fafb93884",
// afterId: editor.topLevelBlocks[1].id,
// type: "add",
// content:
// "// This is a code block\nexport let value = 10;\nconsole.log(value);",
// blockType: "codeblock",
// } as const,
// ];

// TODO: we should validate the commands before applying them
applyChanges(
commands,
document.ydoc.getXmlFragment("doc"),
document.awareness,
);
// console.log(response);
},
aliases: ["ai", "magic"],
hint: "Prompt your AI code assistant",
aliases: ["ai", "wizard", "openai", "llm"],
hint: "Prompt your TypeCell AI assistant",
group: "Code",
icon: <VscWand size={18} />,
},
...[...editorStore.current.customBlocks.values()].map((data: any) => {
...[...editorStore.current.customBlocks.values()].map((data) => {
console.log("update blocks");
return {
name: data.name,
execute: (editor: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
execute: (editor: BlockNoteEditor<any>) => {
const origVarName = variables.toCamelCaseVariableName(data.name);
let varName = origVarName;
let i = 0;
// eslint-disable-next-line no-constant-condition
while (true) {
// append _1, _2, _3, ... to the variable name until it is unique

if (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(
tools.newExecutionHost.engine.observableContext
.rawContext as any
)[varName] === undefined
) {
const context =
tools.newExecutionHost.engine.observableContext.rawContext;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((context as any)[varName] === undefined) {
break;
}
i++;
varName = origVarName + "_" + i;
}

insertOrUpdateBlock(
editor as any,
{
type: "codeblock",
props: {
language: "typescript",
storage: "",
},
content: `// @default-collapsed
insertOrUpdateBlock(editor, {
type: "codeblock",
props: {
language: "typescript",
storage: "",
},
content: `// @default-collapsed
import * as doc from "${data.documentId}";
export let ${varName} = doc.${data.blockVariable};
export let ${varName}Scope = doc;
export default ${varName};
`,
} as any,
);
});
},
// execute: (editor) =>
// insertOrUpdateBlock(editor, {
Expand All @@ -383,7 +374,7 @@ export default ${varName};
// aliases: [data[0]],
// hint: "Add a " + data[0],
group: "Custom",
} as any;
};
}),
);

Expand Down Expand Up @@ -436,6 +427,7 @@ export default ${varName};
});

if (editorStore.current.editor !== editor) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
editorStore.current.editor = editor as any;
}

Expand Down
78 changes: 13 additions & 65 deletions packages/frame/src/ai/ai.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
// import LocalExecutionHost from "../../../runtime/executor/executionHosts/local/LocalExecutionHost"
import "@blocknote/core/style.css";
import * as mobx from "mobx";
Expand All @@ -8,48 +9,8 @@ import { BlockNoteEditor } from "@blocknote/core";
import { HostBridgeMethods } from "@typecell-org/shared";
import { uri } from "vscode-lib";
import { EditorStore } from "../EditorStore";
import { compile } from "../runtime/compiler/compilers/MonacoCompiler";
import { ExecutionHost } from "../runtime/executor/executionHosts/ExecutionHost";
import { customStringify } from "../stringify";
import { CodeBlockRuntimeInfo } from "./types";

// and for the runtime info:

// /**
// * Runtime information about a code block of the main document
// * The code itself is not included (it's in the Block.id with the corresponding blockId)
// */
// type MainCodeBlockRuntimeInfo = {
// imported: false;
// blockId: string;
// // .d.ts TypeScript types of values exported by this block
// types: string;
// // the runtime values exported by this block. Data can be trimmed for brevity
// // IMPORTANT: if this is for example { outputVariable: 5 }, it means the code block exports a variable \`outputVariable\` and the current value is 5
// // You can access this reactive variable in other code blocks using the \`$\` variable. e.g.: \`$.outputVariable\` (it supports both reading and writing)
// data: any;
// };

// /**
// * Runtime + code information of code blocks imported from other documents
// */
// type ImportedCodeBlockRuntimeInfo = {
// imported: true;
// /**
// * Because we don't pass the entire document this code is imported from, we need to pass the code of this code block
// */
// code: string;
// // .d.ts TypeScript types of values exported by this block
// types: string;
// documentId: string;
// blockId: string;
// // the runtime values exported by this block. Data can be trimmed for brevity
// data: any;
// };

// export type CodeBlockRuntimeInfo =
// | MainCodeBlockRuntimeInfo
// | ImportedCodeBlockRuntimeInfo;
import { trimmedStringify } from "./trimmedStringify";

const TYPECELL_PROMPT = `
You're a smart AI assistant for TypeCell: a rich text document tool that also supports interactive Code Blocks written in Typescript.
Expand Down Expand Up @@ -122,10 +83,6 @@ export async function getAICode(
editorStore: EditorStore,
queryLLM: HostBridgeMethods["queryLLM"],
) {
const models = monaco.editor.getModels();
const typeCellModels = models.filter((m) =>
m.uri.path.startsWith("/!typecell:typecell.org"),
);
const blocks = editor.topLevelBlocks;

let blockContexts: any[] = [];
Expand Down Expand Up @@ -187,6 +144,13 @@ type ExpandRecursively<T> = T extends object
// const def3 = await ts.get(tmpModel.uri.toString(), pos, {});
tmpModel.dispose();

/*
// const models = monaco.editor.getModels();
// const typeCellModels = models.filter((m) =>
// m.uri.path.startsWith("/!typecell:typecell.org"),
// );
const codeInfoPromises = typeCellModels.map(async (m) => {
const code = await compile(m, monaco);
const output = await executionHost.outputs.get(m.uri.toString())?.value;
Expand Down Expand Up @@ -218,7 +182,7 @@ type ExpandRecursively<T> = T extends object
return ret;
});
let codeInfos = await Promise.all(codeInfoPromises);
codeInfos = codeInfos.filter((x) => !!x.imported);
codeInfos = codeInfos.filter((x) => !!x.imported);*/

const context = executionHost.engine.observableContext.rawContext as any;

Expand All @@ -228,7 +192,7 @@ type ExpandRecursively<T> = T extends object
mobx.toJS(context[key]),
]),
);
outputJS = JSON.parse(customStringify(outputJS));
outputJS = JSON.parse(trimmedStringify(outputJS));

function cleanBlock(block: any) {
if (!block.content?.length && !block.children?.length) {
Expand All @@ -243,12 +207,8 @@ type ExpandRecursively<T> = T extends object
}
return block;
}
// console.log("request", JSON.stringify(blocks).length);
const sanitized = blocks.map(cleanBlock).filter((x) => !!x);
// console.log("sanitized", JSON.stringify(sanitized).length);

// debugger;
// const command = prompt("prompt");
const sanitized = blocks.map(cleanBlock).filter((x) => !!x);
const contextInfo =
contextType.replace("type ContextType = ", "const $: ") +
" = " +
Expand Down Expand Up @@ -281,26 +241,14 @@ type ExpandRecursively<T> = T extends object
blockContextInfo
: ""),
},

// codeInfos.length
// ? {
// role: "user",
// content: `This is the runtime / compiler data of the Code Blocks (CodeBlockRuntimeInfo[]):
// """${JSON.stringify(codeInfos)}"""`,
// }
// : {
// role: "user",
// content: `There are no code blocks in the document, so there's no runtime / compiler data for these (CodeBlockRuntimeInfo[]).`,
// },
{
role: "system",
content: `You are an AI assistant helping user to modify his document. This means changes can either be code related (in that case, you'll need to add / modify Code Blocks),
or not at all (in which case you'll need to add / modify regular blocks), or a mix of both.`,
},
{
role: "user",
content: prompt, // +
// " . \n\nRemember to reply ONLY with OperationsResponse JSON (DO NOT add any further comments). So start with [{ and end with }]",
content: prompt,
},
];

Expand Down
Loading

0 comments on commit 699310f

Please sign in to comment.