Compare commits
7 commits
develop
...
pyrox-aisc
Author | SHA1 | Date | |
---|---|---|---|
|
10b146fb2d | ||
|
07c80c6023 | ||
|
0fe9799a3e | ||
|
2eb71791fe | ||
|
00a3d18627 | ||
|
4c82b54686 | ||
|
2cc6276b3b |
11 changed files with 770 additions and 64 deletions
|
@ -40,7 +40,7 @@
|
|||
"@peertube/http-signature": "1.7.0",
|
||||
"@redocly/openapi-core": "1.0.0-beta.120",
|
||||
"@sinonjs/fake-timers": "9.1.2",
|
||||
"@syuilo/aiscript": "0.11.1",
|
||||
"@syuilo/aiscript": "0.13.3",
|
||||
"@tensorflow/tfjs": "^4.2.0",
|
||||
"adm-zip": "^0.5.10",
|
||||
"ajv": "8.12.0",
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"@rollup/plugin-alias": "3.1.9",
|
||||
"@rollup/plugin-json": "4.1.0",
|
||||
"@rollup/pluginutils": "^4.2.1",
|
||||
"@syuilo/aiscript": "0.11.1",
|
||||
"@syuilo/aiscript": "^0.13.3",
|
||||
"@types/escape-regexp": "0.0.1",
|
||||
"@types/glob": "8.1.0",
|
||||
"@types/gulp": "4.0.11",
|
||||
|
|
|
@ -22,7 +22,7 @@ import {
|
|||
onUnmounted,
|
||||
PropType,
|
||||
} 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";
|
||||
|
@ -51,8 +51,9 @@ export default defineComponent({
|
|||
nextTick(() => {
|
||||
if (props.page.script && hpml.aiscript) {
|
||||
let ast;
|
||||
const parser = new Parser();
|
||||
try {
|
||||
ast = parse(props.page.script);
|
||||
ast = parser.parse(props.page.script);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
/*os.alert({
|
||||
|
|
|
@ -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";
|
||||
|
@ -68,7 +68,8 @@ watch(code, () => {
|
|||
|
||||
async function run() {
|
||||
logs.value = [];
|
||||
const aiscript = new AiScript(
|
||||
const parser = new Parser();
|
||||
const aiscript = new Interpreter(
|
||||
createAiScriptEnv({
|
||||
storageKey: "scratchpad",
|
||||
token: $i?.token,
|
||||
|
@ -111,11 +112,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",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -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 } from "@syuilo/aiscript";
|
||||
import { v4 as uuid } from "uuid";
|
||||
import FormTextarea from "@/components/form/textarea.vue";
|
||||
import FormButton from "@/components/MkButton.vue";
|
||||
|
@ -49,21 +48,22 @@ function installPlugin({ id, meta, ast, token }) {
|
|||
|
||||
async function install() {
|
||||
let ast;
|
||||
const parser = new Parser();
|
||||
try {
|
||||
ast = parse(code.value);
|
||||
ast = parser.parse(code.value);
|
||||
} catch (err) {
|
||||
os.alert({
|
||||
type: "error",
|
||||
text: "Syntax error :(",
|
||||
text: "Syntax error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const meta = AiScript.collectMetadata(ast);
|
||||
const meta = Interpreter.collectMetadata(ast);
|
||||
if (meta == null) {
|
||||
os.alert({
|
||||
type: "error",
|
||||
text: "No metadata found :(",
|
||||
text: "No metadata found",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ async function install() {
|
|||
if (metadata == null) {
|
||||
os.alert({
|
||||
type: "error",
|
||||
text: "No metadata found :(",
|
||||
text: "No metadata found",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ async function install() {
|
|||
if (name == null || version == null || author == null) {
|
||||
os.alert({
|
||||
type: "error",
|
||||
text: "Required property not found :(",
|
||||
text: "Required property not found",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ async function install() {
|
|||
config,
|
||||
},
|
||||
token,
|
||||
ast: serialize(ast),
|
||||
ast: ast,
|
||||
});
|
||||
|
||||
os.success();
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { AiScript, utils, values } from "@syuilo/aiscript";
|
||||
import { deserialize } from "@syuilo/aiscript/built/serializer";
|
||||
import { Interpreter, utils, values } from "@syuilo/aiscript";
|
||||
import { jsToVal } from "@syuilo/aiscript/built/interpreter/util";
|
||||
import { createAiScriptEnv } from "@/scripts/aiscript/api";
|
||||
import { inputText } from "@/os";
|
||||
|
@ -11,12 +10,12 @@ import {
|
|||
userActions,
|
||||
} from "@/store";
|
||||
|
||||
const pluginContexts = new Map<string, AiScript>();
|
||||
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: plugin,
|
||||
storageKey: `plugins:${plugin.id}`,
|
||||
|
@ -40,7 +39,7 @@ export function install(plugin) {
|
|||
|
||||
initPlugin({ plugin, aiscript });
|
||||
|
||||
aiscript.exec(deserialize(plugin.ast));
|
||||
aiscript.exec(plugin.ast);
|
||||
}
|
||||
|
||||
function createPluginEnv(opts) {
|
||||
|
|
718
packages/client/src/scripts/aiscript/ui.ts
Normal file
718
packages/client/src/scripts/aiscript/ui.ts
Normal file
|
@ -0,0 +1,718 @@
|
|||
import { utils, values } from "@syuilo/aiscript";
|
||||
import { v4 as uuid } from "uuid";
|
||||
import { ref, Ref } from "vue";
|
||||
|
||||
export type AsUiComponentBase = {
|
||||
id: string;
|
||||
hidden?: boolean;
|
||||
};
|
||||
|
||||
export type AsUiRoot = AsUiComponentBase & {
|
||||
type: "root";
|
||||
children: AsUiComponent["id"][];
|
||||
};
|
||||
|
||||
export type AsUiContainer = AsUiComponentBase & {
|
||||
type: "container";
|
||||
children?: AsUiComponent["id"][];
|
||||
align?: "left" | "center" | "right";
|
||||
bgColor?: string;
|
||||
fgColor?: string;
|
||||
font?: "serif" | "sans-serif" | "monospace";
|
||||
borderWidth?: number;
|
||||
borderColor?: string;
|
||||
padding?: number;
|
||||
rounded?: boolean;
|
||||
hidden?: boolean;
|
||||
};
|
||||
|
||||
export type AsUiText = AsUiComponentBase & {
|
||||
type: "text";
|
||||
text?: string;
|
||||
size?: number;
|
||||
bold?: boolean;
|
||||
color?: string;
|
||||
font?: "serif" | "sans-serif" | "monospace";
|
||||
};
|
||||
|
||||
export type AsUiMfm = AsUiComponentBase & {
|
||||
type: "mfm";
|
||||
text?: string;
|
||||
size?: number;
|
||||
bold?: boolean;
|
||||
color?: string;
|
||||
font?: "serif" | "sans-serif" | "monospace";
|
||||
};
|
||||
|
||||
export type AsUiButton = AsUiComponentBase & {
|
||||
type: "button";
|
||||
text?: string;
|
||||
onClick?: () => void;
|
||||
primary?: boolean;
|
||||
rounded?: boolean;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export type AsUiButtons = AsUiComponentBase & {
|
||||
type: "buttons";
|
||||
buttons?: AsUiButton[];
|
||||
};
|
||||
|
||||
export type AsUiSwitch = AsUiComponentBase & {
|
||||
type: "switch";
|
||||
onChange?: (v: boolean) => void;
|
||||
default?: boolean;
|
||||
label?: string;
|
||||
caption?: string;
|
||||
};
|
||||
|
||||
export type AsUiTextarea = AsUiComponentBase & {
|
||||
type: "textarea";
|
||||
onInput?: (v: string) => void;
|
||||
default?: string;
|
||||
label?: string;
|
||||
caption?: string;
|
||||
};
|
||||
|
||||
export type AsUiTextInput = AsUiComponentBase & {
|
||||
type: "textInput";
|
||||
onInput?: (v: string) => void;
|
||||
default?: string;
|
||||
label?: string;
|
||||
caption?: string;
|
||||
};
|
||||
|
||||
export type AsUiNumberInput = AsUiComponentBase & {
|
||||
type: "numberInput";
|
||||
onInput?: (v: number) => void;
|
||||
default?: number;
|
||||
label?: string;
|
||||
caption?: string;
|
||||
};
|
||||
|
||||
export type AsUiSelect = AsUiComponentBase & {
|
||||
type: "select";
|
||||
items?: {
|
||||
text: string;
|
||||
value: string;
|
||||
}[];
|
||||
onChange?: (v: string) => void;
|
||||
default?: string;
|
||||
label?: string;
|
||||
caption?: string;
|
||||
};
|
||||
|
||||
export type AsUiFolder = AsUiComponentBase & {
|
||||
type: "folder";
|
||||
children?: AsUiComponent["id"][];
|
||||
title?: string;
|
||||
opened?: boolean;
|
||||
};
|
||||
|
||||
export type AsUiPostFormButton = AsUiComponentBase & {
|
||||
type: "postFormButton";
|
||||
text?: string;
|
||||
primary?: boolean;
|
||||
rounded?: boolean;
|
||||
form?: {
|
||||
text: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type AsUiComponent =
|
||||
| AsUiRoot
|
||||
| AsUiContainer
|
||||
| AsUiText
|
||||
| AsUiMfm
|
||||
| AsUiButton
|
||||
| AsUiButtons
|
||||
| AsUiSwitch
|
||||
| AsUiTextarea
|
||||
| AsUiTextInput
|
||||
| AsUiNumberInput
|
||||
| AsUiSelect
|
||||
| AsUiFolder
|
||||
| AsUiPostFormButton;
|
||||
|
||||
export function patch(
|
||||
id: string,
|
||||
def: values.Value,
|
||||
call: (fn: values.VFn, args: values.Value[]) => Promise<values.Value>,
|
||||
) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
function getRootOptions(
|
||||
def: values.Value | undefined,
|
||||
): Omit<AsUiRoot, "id" | "type"> {
|
||||
utils.assertObject(def);
|
||||
|
||||
const children = def.value.get("children");
|
||||
utils.assertArray(children);
|
||||
|
||||
return {
|
||||
children: children.value.map((v) => {
|
||||
utils.assertObject(v);
|
||||
return v.value.get("id").value;
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
function getContainerOptions(
|
||||
def: values.Value | undefined,
|
||||
): Omit<AsUiContainer, "id" | "type"> {
|
||||
utils.assertObject(def);
|
||||
|
||||
const children = def.value.get("children");
|
||||
if (children) utils.assertArray(children);
|
||||
const align = def.value.get("align");
|
||||
if (align) utils.assertString(align);
|
||||
const bgColor = def.value.get("bgColor");
|
||||
if (bgColor) utils.assertString(bgColor);
|
||||
const fgColor = def.value.get("fgColor");
|
||||
if (fgColor) utils.assertString(fgColor);
|
||||
const font = def.value.get("font");
|
||||
if (font) utils.assertString(font);
|
||||
const borderWidth = def.value.get("borderWidth");
|
||||
if (borderWidth) utils.assertNumber(borderWidth);
|
||||
const borderColor = def.value.get("borderColor");
|
||||
if (borderColor) utils.assertString(borderColor);
|
||||
const padding = def.value.get("padding");
|
||||
if (padding) utils.assertNumber(padding);
|
||||
const rounded = def.value.get("rounded");
|
||||
if (rounded) utils.assertBoolean(rounded);
|
||||
const hidden = def.value.get("hidden");
|
||||
if (hidden) utils.assertBoolean(hidden);
|
||||
|
||||
return {
|
||||
children: children
|
||||
? children.value.map((v) => {
|
||||
utils.assertObject(v);
|
||||
return v.value.get("id").value;
|
||||
})
|
||||
: [],
|
||||
align: align?.value,
|
||||
fgColor: fgColor?.value,
|
||||
bgColor: bgColor?.value,
|
||||
font: font?.value,
|
||||
borderWidth: borderWidth?.value,
|
||||
borderColor: borderColor?.value,
|
||||
padding: padding?.value,
|
||||
rounded: rounded?.value,
|
||||
hidden: hidden?.value,
|
||||
};
|
||||
}
|
||||
|
||||
function getTextOptions(
|
||||
def: values.Value | undefined,
|
||||
): Omit<AsUiText, "id" | "type"> {
|
||||
utils.assertObject(def);
|
||||
|
||||
const text = def.value.get("text");
|
||||
if (text) utils.assertString(text);
|
||||
const size = def.value.get("size");
|
||||
if (size) utils.assertNumber(size);
|
||||
const bold = def.value.get("bold");
|
||||
if (bold) utils.assertBoolean(bold);
|
||||
const color = def.value.get("color");
|
||||
if (color) utils.assertString(color);
|
||||
const font = def.value.get("font");
|
||||
if (font) utils.assertString(font);
|
||||
|
||||
return {
|
||||
text: text?.value,
|
||||
size: size?.value,
|
||||
bold: bold?.value,
|
||||
color: color?.value,
|
||||
font: font?.value,
|
||||
};
|
||||
}
|
||||
|
||||
function getMfmOptions(
|
||||
def: values.Value | undefined,
|
||||
): Omit<AsUiMfm, "id" | "type"> {
|
||||
utils.assertObject(def);
|
||||
|
||||
const text = def.value.get("text");
|
||||
if (text) utils.assertString(text);
|
||||
const size = def.value.get("size");
|
||||
if (size) utils.assertNumber(size);
|
||||
const bold = def.value.get("bold");
|
||||
if (bold) utils.assertBoolean(bold);
|
||||
const color = def.value.get("color");
|
||||
if (color) utils.assertString(color);
|
||||
const font = def.value.get("font");
|
||||
if (font) utils.assertString(font);
|
||||
|
||||
return {
|
||||
text: text?.value,
|
||||
size: size?.value,
|
||||
bold: bold?.value,
|
||||
color: color?.value,
|
||||
font: font?.value,
|
||||
};
|
||||
}
|
||||
|
||||
function getTextInputOptions(
|
||||
def: values.Value | undefined,
|
||||
call: (fn: values.VFn, args: values.Value[]) => Promise<values.Value>,
|
||||
): Omit<AsUiTextInput, "id" | "type"> {
|
||||
utils.assertObject(def);
|
||||
|
||||
const onInput = def.value.get("onInput");
|
||||
if (onInput) utils.assertFunction(onInput);
|
||||
const defaultValue = def.value.get("default");
|
||||
if (defaultValue) utils.assertString(defaultValue);
|
||||
const label = def.value.get("label");
|
||||
if (label) utils.assertString(label);
|
||||
const caption = def.value.get("caption");
|
||||
if (caption) utils.assertString(caption);
|
||||
|
||||
return {
|
||||
onInput: (v) => {
|
||||
if (onInput) call(onInput, [utils.jsToVal(v)]);
|
||||
},
|
||||
default: defaultValue?.value,
|
||||
label: label?.value,
|
||||
caption: caption?.value,
|
||||
};
|
||||
}
|
||||
|
||||
function getTextareaOptions(
|
||||
def: values.Value | undefined,
|
||||
call: (fn: values.VFn, args: values.Value[]) => Promise<values.Value>,
|
||||
): Omit<AsUiTextarea, "id" | "type"> {
|
||||
utils.assertObject(def);
|
||||
|
||||
const onInput = def.value.get("onInput");
|
||||
if (onInput) utils.assertFunction(onInput);
|
||||
const defaultValue = def.value.get("default");
|
||||
if (defaultValue) utils.assertString(defaultValue);
|
||||
const label = def.value.get("label");
|
||||
if (label) utils.assertString(label);
|
||||
const caption = def.value.get("caption");
|
||||
if (caption) utils.assertString(caption);
|
||||
|
||||
return {
|
||||
onInput: (v) => {
|
||||
if (onInput) call(onInput, [utils.jsToVal(v)]);
|
||||
},
|
||||
default: defaultValue?.value,
|
||||
label: label?.value,
|
||||
caption: caption?.value,
|
||||
};
|
||||
}
|
||||
|
||||
function getNumberInputOptions(
|
||||
def: values.Value | undefined,
|
||||
call: (fn: values.VFn, args: values.Value[]) => Promise<values.Value>,
|
||||
): Omit<AsUiNumberInput, "id" | "type"> {
|
||||
utils.assertObject(def);
|
||||
|
||||
const onInput = def.value.get("onInput");
|
||||
if (onInput) utils.assertFunction(onInput);
|
||||
const defaultValue = def.value.get("default");
|
||||
if (defaultValue) utils.assertNumber(defaultValue);
|
||||
const label = def.value.get("label");
|
||||
if (label) utils.assertString(label);
|
||||
const caption = def.value.get("caption");
|
||||
if (caption) utils.assertString(caption);
|
||||
|
||||
return {
|
||||
onInput: (v) => {
|
||||
if (onInput) call(onInput, [utils.jsToVal(v)]);
|
||||
},
|
||||
default: defaultValue?.value,
|
||||
label: label?.value,
|
||||
caption: caption?.value,
|
||||
};
|
||||
}
|
||||
|
||||
function getButtonOptions(
|
||||
def: values.Value | undefined,
|
||||
call: (fn: values.VFn, args: values.Value[]) => Promise<values.Value>,
|
||||
): Omit<AsUiButton, "id" | "type"> {
|
||||
utils.assertObject(def);
|
||||
|
||||
const text = def.value.get("text");
|
||||
if (text) utils.assertString(text);
|
||||
const onClick = def.value.get("onClick");
|
||||
if (onClick) utils.assertFunction(onClick);
|
||||
const primary = def.value.get("primary");
|
||||
if (primary) utils.assertBoolean(primary);
|
||||
const rounded = def.value.get("rounded");
|
||||
if (rounded) utils.assertBoolean(rounded);
|
||||
const disabled = def.value.get("disabled");
|
||||
if (disabled) utils.assertBoolean(disabled);
|
||||
|
||||
return {
|
||||
text: text?.value,
|
||||
onClick: () => {
|
||||
if (onClick) call(onClick, []);
|
||||
},
|
||||
primary: primary?.value,
|
||||
rounded: rounded?.value,
|
||||
disabled: disabled?.value,
|
||||
};
|
||||
}
|
||||
|
||||
function getButtonsOptions(
|
||||
def: values.Value | undefined,
|
||||
call: (fn: values.VFn, args: values.Value[]) => Promise<values.Value>,
|
||||
): Omit<AsUiButtons, "id" | "type"> {
|
||||
utils.assertObject(def);
|
||||
|
||||
const buttons = def.value.get("buttons");
|
||||
if (buttons) utils.assertArray(buttons);
|
||||
|
||||
return {
|
||||
buttons: buttons
|
||||
? buttons.value.map((button) => {
|
||||
utils.assertObject(button);
|
||||
const text = button.value.get("text");
|
||||
utils.assertString(text);
|
||||
const onClick = button.value.get("onClick");
|
||||
utils.assertFunction(onClick);
|
||||
const primary = button.value.get("primary");
|
||||
if (primary) utils.assertBoolean(primary);
|
||||
const rounded = button.value.get("rounded");
|
||||
if (rounded) utils.assertBoolean(rounded);
|
||||
const disabled = button.value.get("disabled");
|
||||
if (disabled) utils.assertBoolean(disabled);
|
||||
|
||||
return {
|
||||
text: text.value,
|
||||
onClick: () => {
|
||||
call(onClick, []);
|
||||
},
|
||||
primary: primary?.value,
|
||||
rounded: rounded?.value,
|
||||
disabled: disabled?.value,
|
||||
};
|
||||
})
|
||||
: [],
|
||||
};
|
||||
}
|
||||
|
||||
function getSwitchOptions(
|
||||
def: values.Value | undefined,
|
||||
call: (fn: values.VFn, args: values.Value[]) => Promise<values.Value>,
|
||||
): Omit<AsUiSwitch, "id" | "type"> {
|
||||
utils.assertObject(def);
|
||||
|
||||
const onChange = def.value.get("onChange");
|
||||
if (onChange) utils.assertFunction(onChange);
|
||||
const defaultValue = def.value.get("default");
|
||||
if (defaultValue) utils.assertBoolean(defaultValue);
|
||||
const label = def.value.get("label");
|
||||
if (label) utils.assertString(label);
|
||||
const caption = def.value.get("caption");
|
||||
if (caption) utils.assertString(caption);
|
||||
|
||||
return {
|
||||
onChange: (v) => {
|
||||
if (onChange) call(onChange, [utils.jsToVal(v)]);
|
||||
},
|
||||
default: defaultValue?.value,
|
||||
label: label?.value,
|
||||
caption: caption?.value,
|
||||
};
|
||||
}
|
||||
|
||||
function getSelectOptions(
|
||||
def: values.Value | undefined,
|
||||
call: (fn: values.VFn, args: values.Value[]) => Promise<values.Value>,
|
||||
): Omit<AsUiSelect, "id" | "type"> {
|
||||
utils.assertObject(def);
|
||||
|
||||
const items = def.value.get("items");
|
||||
if (items) utils.assertArray(items);
|
||||
const onChange = def.value.get("onChange");
|
||||
if (onChange) utils.assertFunction(onChange);
|
||||
const defaultValue = def.value.get("default");
|
||||
if (defaultValue) utils.assertString(defaultValue);
|
||||
const label = def.value.get("label");
|
||||
if (label) utils.assertString(label);
|
||||
const caption = def.value.get("caption");
|
||||
if (caption) utils.assertString(caption);
|
||||
|
||||
return {
|
||||
items: items
|
||||
? items.value.map((item) => {
|
||||
utils.assertObject(item);
|
||||
const text = item.value.get("text");
|
||||
utils.assertString(text);
|
||||
const value = item.value.get("value");
|
||||
if (value) utils.assertString(value);
|
||||
return {
|
||||
text: text.value,
|
||||
value: value ? value.value : text.value,
|
||||
};
|
||||
})
|
||||
: [],
|
||||
onChange: (v) => {
|
||||
if (onChange) call(onChange, [utils.jsToVal(v)]);
|
||||
},
|
||||
default: defaultValue?.value,
|
||||
label: label?.value,
|
||||
caption: caption?.value,
|
||||
};
|
||||
}
|
||||
|
||||
function getFolderOptions(
|
||||
def: values.Value | undefined,
|
||||
): Omit<AsUiFolder, "id" | "type"> {
|
||||
utils.assertObject(def);
|
||||
|
||||
const children = def.value.get("children");
|
||||
if (children) utils.assertArray(children);
|
||||
const title = def.value.get("title");
|
||||
if (title) utils.assertString(title);
|
||||
const opened = def.value.get("opened");
|
||||
if (opened) utils.assertBoolean(opened);
|
||||
|
||||
return {
|
||||
children: children
|
||||
? children.value.map((v) => {
|
||||
utils.assertObject(v);
|
||||
return v.value.get("id").value;
|
||||
})
|
||||
: [],
|
||||
title: title?.value ?? "",
|
||||
opened: opened?.value ?? true,
|
||||
};
|
||||
}
|
||||
|
||||
function getPostFormButtonOptions(
|
||||
def: values.Value | undefined,
|
||||
call: (fn: values.VFn, args: values.Value[]) => Promise<values.Value>,
|
||||
): Omit<AsUiPostFormButton, "id" | "type"> {
|
||||
utils.assertObject(def);
|
||||
|
||||
const text = def.value.get("text");
|
||||
if (text) utils.assertString(text);
|
||||
const primary = def.value.get("primary");
|
||||
if (primary) utils.assertBoolean(primary);
|
||||
const rounded = def.value.get("rounded");
|
||||
if (rounded) utils.assertBoolean(rounded);
|
||||
const form = def.value.get("form");
|
||||
if (form) utils.assertObject(form);
|
||||
|
||||
const getForm = () => {
|
||||
const text = form!.value.get("text");
|
||||
utils.assertString(text);
|
||||
return {
|
||||
text: text.value,
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
text: text?.value,
|
||||
primary: primary?.value,
|
||||
rounded: rounded?.value,
|
||||
form: form
|
||||
? getForm()
|
||||
: {
|
||||
text: "",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function registerAsUiLib(
|
||||
components: Ref<AsUiComponent>[],
|
||||
done: (root: Ref<AsUiRoot>) => void,
|
||||
) {
|
||||
const instances = {};
|
||||
|
||||
function createComponentInstance(
|
||||
type: AsUiComponent["type"],
|
||||
def: values.Value | undefined,
|
||||
id: values.Value | undefined,
|
||||
getOptions: (
|
||||
def: values.Value | undefined,
|
||||
call: (fn: values.VFn, args: values.Value[]) => Promise<values.Value>,
|
||||
) => any,
|
||||
call: (fn: values.VFn, args: values.Value[]) => Promise<values.Value>,
|
||||
) {
|
||||
if (id) utils.assertString(id);
|
||||
const _id = id?.value ?? uuid();
|
||||
const component = ref({
|
||||
...getOptions(def, call),
|
||||
type,
|
||||
id: _id,
|
||||
});
|
||||
components.push(component);
|
||||
const instance = values.OBJ(
|
||||
new Map([
|
||||
["id", values.STR(_id)],
|
||||
[
|
||||
"update",
|
||||
values.FN_NATIVE(([def], opts) => {
|
||||
utils.assertObject(def);
|
||||
const updates = getOptions(def, call);
|
||||
for (const update of def.value.keys()) {
|
||||
if (!Object.hasOwn(updates, update)) continue;
|
||||
component.value[update] = updates[update];
|
||||
}
|
||||
}),
|
||||
],
|
||||
]),
|
||||
);
|
||||
instances[_id] = instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
const rootInstance = createComponentInstance(
|
||||
"root",
|
||||
utils.jsToVal({ children: [] }),
|
||||
utils.jsToVal("___root___"),
|
||||
getRootOptions,
|
||||
() => {},
|
||||
);
|
||||
const rootComponent = components[0] as Ref<AsUiRoot>;
|
||||
done(rootComponent);
|
||||
|
||||
return {
|
||||
"Ui:root": rootInstance,
|
||||
|
||||
"Ui:patch": values.FN_NATIVE(([id, val], opts) => {
|
||||
utils.assertString(id);
|
||||
utils.assertArray(val);
|
||||
patch(id.value, val.value, opts.call);
|
||||
}),
|
||||
|
||||
"Ui:get": values.FN_NATIVE(([id], opts) => {
|
||||
utils.assertString(id);
|
||||
const instance = instances[id.value];
|
||||
if (instance) {
|
||||
return instance;
|
||||
} else {
|
||||
return values.NULL;
|
||||
}
|
||||
}),
|
||||
|
||||
// Ui:root.update({ children: [...] }) の糖衣構文
|
||||
"Ui:render": values.FN_NATIVE(([children], opts) => {
|
||||
utils.assertArray(children);
|
||||
|
||||
rootComponent.value.children = children.value.map((v) => {
|
||||
utils.assertObject(v);
|
||||
return v.value.get("id").value;
|
||||
});
|
||||
}),
|
||||
|
||||
"Ui:C:container": values.FN_NATIVE(([def, id], opts) => {
|
||||
return createComponentInstance(
|
||||
"container",
|
||||
def,
|
||||
id,
|
||||
getContainerOptions,
|
||||
opts.call,
|
||||
);
|
||||
}),
|
||||
|
||||
"Ui:C:text": values.FN_NATIVE(([def, id], opts) => {
|
||||
return createComponentInstance(
|
||||
"text",
|
||||
def,
|
||||
id,
|
||||
getTextOptions,
|
||||
opts.call,
|
||||
);
|
||||
}),
|
||||
|
||||
"Ui:C:mfm": values.FN_NATIVE(([def, id], opts) => {
|
||||
return createComponentInstance("mfm", def, id, getMfmOptions, opts.call);
|
||||
}),
|
||||
|
||||
"Ui:C:textarea": values.FN_NATIVE(([def, id], opts) => {
|
||||
return createComponentInstance(
|
||||
"textarea",
|
||||
def,
|
||||
id,
|
||||
getTextareaOptions,
|
||||
opts.call,
|
||||
);
|
||||
}),
|
||||
|
||||
"Ui:C:textInput": values.FN_NATIVE(([def, id], opts) => {
|
||||
return createComponentInstance(
|
||||
"textInput",
|
||||
def,
|
||||
id,
|
||||
getTextInputOptions,
|
||||
opts.call,
|
||||
);
|
||||
}),
|
||||
|
||||
"Ui:C:numberInput": values.FN_NATIVE(([def, id], opts) => {
|
||||
return createComponentInstance(
|
||||
"numberInput",
|
||||
def,
|
||||
id,
|
||||
getNumberInputOptions,
|
||||
opts.call,
|
||||
);
|
||||
}),
|
||||
|
||||
"Ui:C:button": values.FN_NATIVE(([def, id], opts) => {
|
||||
return createComponentInstance(
|
||||
"button",
|
||||
def,
|
||||
id,
|
||||
getButtonOptions,
|
||||
opts.call,
|
||||
);
|
||||
}),
|
||||
|
||||
"Ui:C:buttons": values.FN_NATIVE(([def, id], opts) => {
|
||||
return createComponentInstance(
|
||||
"buttons",
|
||||
def,
|
||||
id,
|
||||
getButtonsOptions,
|
||||
opts.call,
|
||||
);
|
||||
}),
|
||||
|
||||
"Ui:C:switch": values.FN_NATIVE(([def, id], opts) => {
|
||||
return createComponentInstance(
|
||||
"switch",
|
||||
def,
|
||||
id,
|
||||
getSwitchOptions,
|
||||
opts.call,
|
||||
);
|
||||
}),
|
||||
|
||||
"Ui:C:select": values.FN_NATIVE(([def, id], opts) => {
|
||||
return createComponentInstance(
|
||||
"select",
|
||||
def,
|
||||
id,
|
||||
getSelectOptions,
|
||||
opts.call,
|
||||
);
|
||||
}),
|
||||
|
||||
"Ui:C:folder": values.FN_NATIVE(([def, id], opts) => {
|
||||
return createComponentInstance(
|
||||
"folder",
|
||||
def,
|
||||
id,
|
||||
getFolderOptions,
|
||||
opts.call,
|
||||
);
|
||||
}),
|
||||
|
||||
"Ui:C:postFormButton": values.FN_NATIVE(([def, id], opts) => {
|
||||
return createComponentInstance(
|
||||
"postFormButton",
|
||||
def,
|
||||
id,
|
||||
getPostFormButtonOptions,
|
||||
opts.call,
|
||||
);
|
||||
}),
|
||||
};
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import autobind from "autobind-decorator";
|
||||
import { PageVar, envVarsDef, Fn, HpmlScope, HpmlError } from ".";
|
||||
import { version } from "@/config";
|
||||
import { AiScript, utils, values } from "@syuilo/aiscript";
|
||||
import { Interpreter, utils, values } from "@syuilo/aiscript";
|
||||
import { createAiScriptEnv } from "../aiscript/api";
|
||||
import { collectPageVars } from "../collect-page-vars";
|
||||
import { initHpmlLib, initAiLib } from "./lib";
|
||||
|
@ -16,7 +16,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({});
|
||||
|
@ -37,7 +37,7 @@ export class Hpml {
|
|||
|
||||
if (this.opts.enableAiScript) {
|
||||
this.aiscript = markRaw(
|
||||
new AiScript(
|
||||
new Interpreter(
|
||||
{
|
||||
...createAiScriptEnv({
|
||||
storageKey: `pages:${this.page.id}`,
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, ref, watch } from "vue";
|
||||
import { AiScript, parse, utils } from "@syuilo/aiscript";
|
||||
import { Interpreter, Parser, utils } from "@syuilo/aiscript";
|
||||
import {
|
||||
useWidgetPropsManager,
|
||||
Widget,
|
||||
|
@ -82,7 +82,7 @@ const logs = ref<
|
|||
|
||||
const run = async () => {
|
||||
logs.value = [];
|
||||
const aiscript = new AiScript(
|
||||
const aiscript = new Interpreter(
|
||||
createAiScriptEnv({
|
||||
storageKey: "widget",
|
||||
token: $i?.token,
|
||||
|
@ -124,12 +124,13 @@ const run = async () => {
|
|||
);
|
||||
|
||||
let ast;
|
||||
const parser = new Parser();
|
||||
try {
|
||||
ast = parse(widgetProps.script);
|
||||
ast = parser.parse(widgetProps.script);
|
||||
} catch (err) {
|
||||
os.alert({
|
||||
type: "error",
|
||||
text: "Syntax error :(",
|
||||
text: `Syntax Error: ${err.message}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="mkw-button">
|
||||
<div data-cy-mkw-button class="mkw-button">
|
||||
<MkButton :primary="widgetProps.colored" full @click="run">
|
||||
{{ widgetProps.label }}
|
||||
</MkButton>
|
||||
|
@ -7,8 +7,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, ref, watch } from "vue";
|
||||
import { AiScript, parse, utils } from "@syuilo/aiscript";
|
||||
import { Interpreter, Parser } from "@syuilo/aiscript";
|
||||
import {
|
||||
useWidgetPropsManager,
|
||||
Widget,
|
||||
|
@ -36,18 +35,16 @@ const widgetPropsDef = {
|
|||
script: {
|
||||
type: "string" as const,
|
||||
multiline: true,
|
||||
default: 'Mk:dialog("hello" "world")',
|
||||
default: 'Mk:dialog("Hello" "world")',
|
||||
},
|
||||
};
|
||||
|
||||
type WidgetProps = GetFormResultType<typeof widgetPropsDef>;
|
||||
|
||||
// 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない
|
||||
//const props = defineProps<WidgetComponentProps<WidgetProps>>();
|
||||
//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>();
|
||||
const props = defineProps<{ widget?: Widget<WidgetProps> }>();
|
||||
const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>();
|
||||
|
||||
|
||||
const { widgetProps, configure } = useWidgetPropsManager(
|
||||
name,
|
||||
widgetPropsDef,
|
||||
|
@ -55,8 +52,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,
|
||||
|
@ -67,7 +66,11 @@ const run = async () => {
|
|||
os.inputText({
|
||||
title: q,
|
||||
}).then(({ canceled, result: a }) => {
|
||||
ok(a);
|
||||
if (canceled) {
|
||||
ok("");
|
||||
} else {
|
||||
ok(a);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -82,11 +85,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.message}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -106,8 +109,3 @@ defineExpose<WidgetComponentExpose>({
|
|||
id: props.widget ? props.widget.id : null,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.mkw-button {
|
||||
}
|
||||
</style>
|
||||
|
|
26
pnpm-lock.yaml
generated
26
pnpm-lock.yaml
generated
|
@ -112,8 +112,8 @@ importers:
|
|||
specifier: 9.1.2
|
||||
version: 9.1.2
|
||||
'@syuilo/aiscript':
|
||||
specifier: 0.11.1
|
||||
version: 0.11.1
|
||||
specifier: 0.13.3
|
||||
version: 0.13.3
|
||||
'@tensorflow/tfjs':
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0(seedrandom@3.0.5)
|
||||
|
@ -688,8 +688,8 @@ importers:
|
|||
specifier: ^4.2.1
|
||||
version: 4.2.1
|
||||
'@syuilo/aiscript':
|
||||
specifier: 0.11.1
|
||||
version: 0.11.1
|
||||
specifier: ^0.13.3
|
||||
version: 0.13.3
|
||||
'@types/escape-regexp':
|
||||
specifier: 0.0.1
|
||||
version: 0.0.1
|
||||
|
@ -2923,14 +2923,13 @@ packages:
|
|||
resolution: {integrity: sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==}
|
||||
requiresBuild: true
|
||||
|
||||
/@syuilo/aiscript@0.11.1:
|
||||
resolution: {integrity: sha512-chwOIA3yLUKvOB0G611hjLArKTeOWNmTm3lHERSaDW1d+dS6do56naX6Lkwy2UpnwWC0qzeNSgg35elk6t2gZg==}
|
||||
/@syuilo/aiscript@0.13.3:
|
||||
resolution: {integrity: sha512-0YFlWA+7YhyRRsp+9Nl72SoSUg5ghskthjCdLvj4qdGyLedeyanKZWJlH2A9d47Nes03UYY8CRDsMHHv64IWcg==}
|
||||
dependencies:
|
||||
autobind-decorator: 2.4.0
|
||||
chalk: 4.0.0
|
||||
seedrandom: 3.0.5
|
||||
stringz: 2.1.0
|
||||
uuid: 7.0.3
|
||||
uuid: 9.0.0
|
||||
|
||||
/@szmarczak/http-timer@4.0.6:
|
||||
resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==}
|
||||
|
@ -5524,13 +5523,6 @@ packages:
|
|||
escape-string-regexp: 1.0.5
|
||||
supports-color: 5.5.0
|
||||
|
||||
/chalk@4.0.0:
|
||||
resolution: {integrity: sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
supports-color: 7.2.0
|
||||
|
||||
/chalk@4.1.2:
|
||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -15332,10 +15324,6 @@ packages:
|
|||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/uuid@7.0.3:
|
||||
resolution: {integrity: sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==}
|
||||
hasBin: true
|
||||
|
||||
/uuid@8.0.0:
|
||||
resolution: {integrity: sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==}
|
||||
hasBin: true
|
||||
|
|
Loading…
Add table
Reference in a new issue