fix: (try to) make AiScript work

Co-authored-by: syuilo <syuilotan@yahoo.co.jp>
Co-authored-by: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com>
This commit is contained in:
naskya 2023-11-06 21:08:32 +09:00
parent f5cee3856d
commit 082cd3ac1d
Signed by: naskya
GPG key ID: 164DFF24E2D40139
10 changed files with 140 additions and 73 deletions

View file

@ -36,7 +36,6 @@
"@peertube/http-signature": "1.7.0",
"@redocly/openapi-core": "1.4.0",
"@sinonjs/fake-timers": "11.2.2",
"@syuilo/aiscript": "0.11.1",
"@tensorflow/tfjs": "4.12.0",
"adm-zip": "0.5.10",
"ajv": "8.12.0",

View file

@ -17,7 +17,7 @@
"@rollup/plugin-alias": "5.0.1",
"@rollup/plugin-json": "6.0.1",
"@rollup/pluginutils": "5.0.5",
"@syuilo/aiscript": "0.11.1",
"@syuilo/aiscript": "0.16.0",
"@types/glob": "8.1.0",
"@types/gulp": "4.0.16",
"@types/gulp-rename": "2.0.4",

View file

@ -17,7 +17,7 @@
<script lang="ts">
import type { PropType } from "vue";
import { defineComponent, nextTick, onMounted, onUnmounted } from "vue";
import { parse } from "@syuilo/aiscript";
import { Parser } from "@syuilo/aiscript";
import XBlock from "./page.block.vue";
import { Hpml } from "@/scripts/hpml/evaluator";
import { url } from "@/config";
@ -42,12 +42,14 @@ export default defineComponent({
enableAiScript: !defaultStore.state.disablePagesScript,
});
const parser = new Parser();
onMounted(() => {
nextTick(() => {
if (props.page.script && hpml.aiscript) {
let ast;
try {
ast = parse(props.page.script);
ast = parser.parse(props.page.script);
} catch (err) {
console.error(err);
/* os.alert({

View file

@ -45,7 +45,7 @@ import "prismjs/components/prism-javascript";
import "prismjs/themes/prism-okaidia.css";
import { PrismEditor } from "vue-prism-editor";
import "vue-prism-editor/dist/prismeditor.min.css";
import { AiScript, parse, utils } from "@syuilo/aiscript";
import { Interpreter, Parser, utils } from "@syuilo/aiscript";
import MkContainer from "@/components/MkContainer.vue";
import MkButton from "@/components/MkButton.vue";
import { createAiScriptEnv } from "@/scripts/aiscript/api";
@ -58,6 +58,8 @@ import icon from "@/scripts/icon";
const code = ref("");
const logs = ref<any[]>([]);
const parser = new Parser();
const saved = localStorage.getItem("scratchpad");
if (saved) {
code.value = saved;
@ -69,7 +71,7 @@ watch(code, () => {
async function run() {
logs.value = [];
const aiscript = new AiScript(
const aiscript = new Interpreter(
createAiScriptEnv({
storageKey: "scratchpad",
token: $i?.token,
@ -112,11 +114,11 @@ async function run() {
let ast;
try {
ast = parse(code.value);
ast = parser.parse(code.value);
} catch (error) {
os.alert({
type: "error",
text: "Syntax error :(",
text: `Syntax error : ${error}`,
});
return;
}

View file

@ -19,8 +19,7 @@
<script lang="ts" setup>
import { defineAsyncComponent, nextTick, ref } from "vue";
import { AiScript, parse } from "@syuilo/aiscript";
import { serialize } from "@syuilo/aiscript/built/serializer";
import { Interpreter, Parser, utils } from "@syuilo/aiscript";
import { v4 as uuid } from "uuid";
import FormTextarea from "@/components/form/textarea.vue";
import FormButton from "@/components/MkButton.vue";
@ -30,11 +29,20 @@ import { ColdDeviceStorage } from "@/store";
import { unisonReload } from "@/scripts/unison-reload";
import { i18n } from "@/i18n";
import { definePageMetadata } from "@/scripts/page-metadata";
import { compareVersions } from "compare-versions";
import icon from "@/scripts/icon";
const code = ref(null);
const code = ref<string>();
function installPlugin({ id, meta, ast, token }) {
function isSupportedVersion(version: string): boolean {
try {
return compareVersions(version, "0.12.0") >= 0;
} catch (err) {
return false;
}
}
function installPlugin({ id, meta, src, token }) {
ColdDeviceStorage.set(
"plugins",
ColdDeviceStorage.get("plugins").concat({
@ -42,25 +50,46 @@ function installPlugin({ id, meta, ast, token }) {
id,
active: true,
configData: {},
src,
token,
ast,
}),
);
}
const parser = new Parser();
async function install() {
let ast;
try {
ast = parse(code.value);
} catch (err) {
if (code.value == null) return;
const scriptVersion = utils.getLangVersion(code.value);
if (scriptVersion == null) {
os.alert({
type: "error",
text: "Syntax error :(",
text: "No language version annotation found :(",
});
return;
}
if (!isSupportedVersion(scriptVersion)) {
os.alert({
type: "error",
text: `aiscript version '${scriptVersion}' is not supported :(`,
});
return;
}
const meta = AiScript.collectMetadata(ast);
let ast;
try {
ast = parser.parse(code.value);
} catch (err) {
os.alert({
type: "error",
text: `Syntax error : ${err}`,
});
return;
}
const meta = Interpreter.collectMetadata(ast);
if (meta == null) {
os.alert({
type: "error",
@ -83,7 +112,7 @@ async function install() {
if (name == null || version == null || author == null) {
os.alert({
type: "error",
text: "Required property not found :(",
text: "Required property (name, version, author) not found :(",
});
return;
}
@ -134,8 +163,8 @@ async function install() {
permissions,
config,
},
src: code.value,
token,
ast: serialize(ast),
});
os.success();

View file

@ -1,6 +1,4 @@
import { AiScript, utils, values } from "@syuilo/aiscript";
import { deserialize } from "@syuilo/aiscript/built/serializer";
import { jsToVal } from "@syuilo/aiscript/built/interpreter/util";
import { Interpreter, Parser, utils, values } from "@syuilo/aiscript";
import { createAiScriptEnv } from "@/scripts/aiscript/api";
import { inputText } from "@/os";
import {
@ -11,12 +9,13 @@ import {
userActions,
} from "@/store";
const pluginContexts = new Map<string, AiScript>();
const parser = new Parser();
const pluginContexts = new Map<string, Interpreter>();
export function install(plugin) {
console.info("Plugin installed:", plugin.name, `v${plugin.version}`);
const aiscript = new AiScript(
const aiscript = new Interpreter(
createPluginEnv({
plugin,
storageKey: `plugins:${plugin.id}`,
@ -40,15 +39,15 @@ export function install(plugin) {
initPlugin({ plugin, aiscript });
aiscript.exec(deserialize(plugin.ast));
aiscript.exec(parser.parse(plugin.src));
}
function createPluginEnv(opts) {
const config = new Map();
for (const [k, v] of Object.entries(opts.plugin.config || {})) {
const config = new Map<string, values.Value>();
for (const [k, v] of Object.entries(opts.plugin.config ?? {})) {
config.set(
k,
jsToVal(
utils.jsToVal(
typeof opts.plugin.configData[k] !== "undefined"
? opts.plugin.configData[k]
: v.default,
@ -114,6 +113,9 @@ function createPluginEnv(opts) {
handler,
});
}),
"Plugin:register_page_view_interruptor": values.FN_NATIVE(([handler]) => {
registerPageViewInterruptor({ pluginId: opts.plugin.id, handler });
}),
"Plugin:open_url": values.FN_NATIVE(([url]) => {
window.open(url.value, "_blank");
}),
@ -129,10 +131,17 @@ function registerPostFormAction({ pluginId, title, handler }) {
postFormActions.push({
title,
handler: (form, update) => {
pluginContexts.get(pluginId).execFn(handler, [
const pluginContext = pluginContexts.get(pluginId);
if (!pluginContext) {
return;
}
pluginContext.execFn(handler, [
utils.jsToVal(form),
values.FN_NATIVE(([key, value]) => {
update(key.value, value.value);
if (!key || !value) {
return;
}
update(utils.valToJs(key), utils.valToJs(value));
}),
]);
},
@ -143,7 +152,11 @@ function registerUserAction({ pluginId, title, handler }) {
userActions.push({
title,
handler: (user) => {
pluginContexts.get(pluginId).execFn(handler, [utils.jsToVal(user)]);
const pluginContext = pluginContexts.get(pluginId);
if (!pluginContext) {
return;
}
pluginContext.execFn(handler, [utils.jsToVal(user)]);
},
});
}
@ -152,7 +165,11 @@ function registerNoteAction({ pluginId, title, handler }) {
noteActions.push({
title,
handler: (note) => {
pluginContexts.get(pluginId).execFn(handler, [utils.jsToVal(note)]);
const pluginContext = pluginContexts.get(pluginId);
if (!pluginContext) {
return;
}
pluginContext.execFn(handler, [utils.jsToVal(user)]);
},
});
}
@ -160,10 +177,12 @@ function registerNoteAction({ pluginId, title, handler }) {
function registerNoteViewInterruptor({ pluginId, handler }) {
noteViewInterruptors.push({
handler: async (note) => {
const pluginContext = pluginContexts.get(pluginId);
if (!pluginContext) {
return;
}
return utils.valToJs(
await pluginContexts
.get(pluginId)
.execFn(handler, [utils.jsToVal(note)]),
await pluginContext.execFn(handler, [utils.jsToVal(note)]),
);
},
});
@ -172,10 +191,26 @@ function registerNoteViewInterruptor({ pluginId, handler }) {
function registerNotePostInterruptor({ pluginId, handler }) {
notePostInterruptors.push({
handler: async (note) => {
const pluginContext = pluginContexts.get(pluginId);
if (!pluginContext) {
return;
}
return utils.valToJs(
await pluginContexts
.get(pluginId)
.execFn(handler, [utils.jsToVal(note)]),
await pluginContext.execFn(handler, [utils.jsToVal(note)]),
);
},
});
}
function registerPageViewInterruptor({ pluginId, handler }): void {
pageViewInterruptors.push({
handler: async (page) => {
const pluginContext = pluginContexts.get(pluginId);
if (!pluginContext) {
return;
}
return utils.valToJs(
await pluginContext.execFn(handler, [utils.jsToVal(page)]),
);
},
});

View file

@ -54,5 +54,8 @@ export function createAiScriptEnv(opts) {
),
);
}),
"Mk:url": values.FN_NATIVE(() => {
return values.STR(window.location.href);
}),
};
}

View file

@ -1,5 +1,5 @@
import autobind from "autobind-decorator";
import { AiScript, utils, values } from "@syuilo/aiscript";
import { Interpreter, utils, values } from "@syuilo/aiscript";
import type { Ref } from "vue";
import { markRaw, ref, unref } from "vue";
import { collectPageVars } from "../collect-page-vars";
@ -19,7 +19,7 @@ export class Hpml {
private variables: Variable[];
private pageVars: PageVar[];
private envVars: Record<keyof typeof envVarsDef, any>;
public aiscript?: AiScript;
public aiscript?: Interpreter;
public pageVarUpdatedCallback?: values.VFn;
public canvases: Record<string, HTMLCanvasElement> = {};
public vars: Ref<Record<string, any>> = ref({});
@ -40,7 +40,7 @@ export class Hpml {
if (this.opts.enableAiScript) {
this.aiscript = markRaw(
new AiScript(
new Interpreter(
{
...createAiScriptEnv({
storageKey: `pages:${this.page.id}`,

View file

@ -27,9 +27,13 @@
<script lang="ts" setup>
import { ref } from "vue";
import { AiScript, parse, utils } from "@syuilo/aiscript";
import type { Widget, WidgetComponentExpose } from "./widget";
import { useWidgetPropsManager } from "./widget";
import { Interpreter, Parser, utils } from "@syuilo/aiscript";
import {
useWidgetPropsManager,
WidgetComponentEmits,
WidgetComponentProps,
} from "./widget";
import type { WidgetComponentExpose } from "./widget";
import type { GetFormResultType } from "@/scripts/form";
import * as os from "@/os";
import MkContainer from "@/components/MkContainer.vue";
@ -55,11 +59,8 @@ const widgetPropsDef = {
type WidgetProps = GetFormResultType<typeof widgetPropsDef>;
// vueimporttype
// const props = defineProps<WidgetComponentProps<WidgetProps>>();
// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>();
const props = defineProps<{ widget?: Widget<WidgetProps> }>();
const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>();
const props = defineProps<WidgetComponentProps<WidgetProps>>();
const emit = defineEmits<WidgetComponentEmits<WidgetProps>>();
const { widgetProps, configure } = useWidgetPropsManager(
name,
@ -76,9 +77,11 @@ const logs = ref<
}[]
>([]);
const parser = new Parser();
const run = async () => {
logs.value = [];
const aiscript = new AiScript(
const aiscript = new Interpreter(
createAiScriptEnv({
storageKey: "widget",
token: $i?.token,
@ -121,11 +124,11 @@ const run = async () => {
let ast;
try {
ast = parse(widgetProps.script);
ast = parser.parse(widgetProps.script);
} catch (err) {
os.alert({
type: "error",
text: "Syntax error :(",
text: `Syntax error : ${err}`,
});
return;
}
@ -134,7 +137,7 @@ const run = async () => {
} catch (err) {
os.alert({
type: "error",
text: err,
text: String(err),
});
}
};

View file

@ -8,16 +8,16 @@
<script lang="ts" setup>
import { onMounted, onUnmounted, ref, watch } from "vue";
import { AiScript, parse, utils } from "@syuilo/aiscript";
import type { Widget, WidgetComponentExpose } from "./widget";
import { Interpreter, Parser } from "@syuilo/aiscript";
import { createAiScriptEnv } from "@/scripts/aiscript/api";
import {
useWidgetPropsManager,
WidgetComponentEmits,
WidgetComponentProps,
useWidgetPropsManager,
} from "./widget";
import type { WidgetComponentExpose } from "./widget";
import type { GetFormResultType } from "@/scripts/form";
import * as os from "@/os";
import { createAiScriptEnv } from "@/scripts/aiscript/api";
import { $i } from "@/reactiveAccount";
import MkButton from "@/components/MkButton.vue";
@ -41,11 +41,8 @@ const widgetPropsDef = {
type WidgetProps = GetFormResultType<typeof widgetPropsDef>;
// vueimporttype
// const props = defineProps<WidgetComponentProps<WidgetProps>>();
// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>();
const props = defineProps<{ widget?: Widget<WidgetProps> }>();
const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>();
const props = defineProps<WidgetComponentProps<WidgetProps>>();
const emit = defineEmits<WidgetComponentEmits<WidgetProps>>();
const { widgetProps, configure } = useWidgetPropsManager(
name,
@ -54,8 +51,10 @@ const { widgetProps, configure } = useWidgetPropsManager(
emit,
);
const parser = new Parser();
const run = async () => {
const aiscript = new AiScript(
const aiscript = new Interpreter(
createAiScriptEnv({
storageKey: "widget",
token: $i?.token,
@ -81,11 +80,11 @@ const run = async () => {
let ast;
try {
ast = parse(widgetProps.script);
ast = parser.parse(widgetProps.script);
} catch (err) {
os.alert({
type: "error",
text: "Syntax error :(",
text: `Syntax error: ${err}`,
});
return;
}
@ -94,7 +93,7 @@ const run = async () => {
} catch (err) {
os.alert({
type: "error",
text: err,
text: String(err),
});
}
};
@ -105,8 +104,3 @@ defineExpose<WidgetComponentExpose>({
id: props.widget ? props.widget.id : null,
});
</script>
<style lang="scss" scoped>
.mkw-button {
}
</style>