2024-07-30 23:33:33 +08:00
|
|
|
import type { AppCommand } from "$lib/command.ts";
|
|
|
|
import type { CommandHook } from "./hooks/command.ts";
|
|
|
|
import type { PlugNamespaceHook } from "$common/hooks/plug_namespace.ts";
|
|
|
|
import type { SilverBulletHooks } from "../lib/manifest.ts";
|
2024-02-07 21:50:01 +08:00
|
|
|
import { buildQueryFunctions } from "./query_functions.ts";
|
|
|
|
import { ScriptEnvironment } from "./space_script.ts";
|
2024-07-30 23:33:33 +08:00
|
|
|
import type { EventHook } from "./hooks/event.ts";
|
|
|
|
import type { DataStore } from "$lib/data/datastore.ts";
|
|
|
|
import type { System } from "$lib/plugos/system.ts";
|
|
|
|
import type { CodeWidgetHook } from "../web/hooks/code_widget.ts";
|
|
|
|
import type { PanelWidgetHook } from "../web/hooks/panel_widget.ts";
|
|
|
|
import type { SlashCommandHook } from "../web/hooks/slash_command.ts";
|
|
|
|
import type { DataStoreMQ } from "$lib/data/mq.datastore.ts";
|
|
|
|
import type { ParseTree } from "../plug-api/lib/tree.ts";
|
2024-02-07 21:50:01 +08:00
|
|
|
|
2024-03-10 19:35:06 +08:00
|
|
|
const mqTimeout = 10000; // 10s
|
|
|
|
const mqTimeoutRetry = 3;
|
|
|
|
|
2024-02-07 21:50:01 +08:00
|
|
|
export abstract class CommonSystem {
|
|
|
|
system!: System<SilverBulletHooks>;
|
|
|
|
|
|
|
|
// Hooks
|
|
|
|
commandHook!: CommandHook;
|
|
|
|
slashCommandHook!: SlashCommandHook;
|
|
|
|
namespaceHook!: PlugNamespaceHook;
|
|
|
|
codeWidgetHook!: CodeWidgetHook;
|
|
|
|
panelWidgetHook!: PanelWidgetHook;
|
|
|
|
|
2024-05-28 02:33:41 +08:00
|
|
|
readonly allKnownFiles = new Set<string>();
|
2024-02-07 21:50:01 +08:00
|
|
|
readonly spaceScriptCommands = new Map<string, AppCommand>();
|
2024-02-28 03:05:12 +08:00
|
|
|
scriptEnv: ScriptEnvironment = new ScriptEnvironment();
|
2024-02-07 21:50:01 +08:00
|
|
|
|
|
|
|
constructor(
|
|
|
|
protected mq: DataStoreMQ,
|
2024-07-30 03:21:16 +08:00
|
|
|
public ds: DataStore,
|
2024-07-27 01:12:10 +08:00
|
|
|
public eventHook: EventHook,
|
2024-02-07 21:50:01 +08:00
|
|
|
public readOnlyMode: boolean,
|
|
|
|
protected enableSpaceScript: boolean,
|
|
|
|
) {
|
|
|
|
setInterval(() => {
|
2024-03-10 19:35:06 +08:00
|
|
|
mq.requeueTimeouts(mqTimeout, mqTimeoutRetry, true).catch(console.error);
|
2024-02-07 21:50:01 +08:00
|
|
|
}, 20000); // Look to requeue every 20s
|
|
|
|
}
|
|
|
|
|
|
|
|
async loadSpaceScripts() {
|
|
|
|
let functions = buildQueryFunctions(
|
2024-05-28 02:33:41 +08:00
|
|
|
this.allKnownFiles,
|
2024-02-07 21:50:01 +08:00
|
|
|
this.system,
|
|
|
|
);
|
|
|
|
if (this.enableSpaceScript) {
|
2024-02-28 03:05:12 +08:00
|
|
|
this.scriptEnv = new ScriptEnvironment();
|
2024-02-07 21:50:01 +08:00
|
|
|
try {
|
2024-02-28 03:05:12 +08:00
|
|
|
await this.scriptEnv.loadFromSystem(this.system);
|
2024-02-07 21:50:01 +08:00
|
|
|
console.log(
|
|
|
|
"Loaded",
|
2024-02-28 03:05:12 +08:00
|
|
|
Object.keys(this.scriptEnv.functions).length,
|
2024-08-07 02:11:38 +08:00
|
|
|
"functions,",
|
2024-02-28 03:05:12 +08:00
|
|
|
Object.keys(this.scriptEnv.commands).length,
|
2024-08-07 02:11:38 +08:00
|
|
|
"commands,",
|
|
|
|
Object.keys(this.scriptEnv.eventHandlers).length,
|
|
|
|
"event handlers from space-script",
|
2024-02-07 21:50:01 +08:00
|
|
|
);
|
|
|
|
} catch (e: any) {
|
|
|
|
console.error("Error loading space-script:", e.message);
|
|
|
|
}
|
2024-02-28 03:05:12 +08:00
|
|
|
functions = { ...functions, ...this.scriptEnv.functions };
|
2024-02-07 21:50:01 +08:00
|
|
|
|
|
|
|
// Reset the space script commands
|
|
|
|
this.spaceScriptCommands.clear();
|
2024-02-28 03:05:12 +08:00
|
|
|
for (const [name, command] of Object.entries(this.scriptEnv.commands)) {
|
2024-02-07 21:50:01 +08:00
|
|
|
this.spaceScriptCommands.set(name, command);
|
|
|
|
}
|
|
|
|
|
2024-02-28 03:05:12 +08:00
|
|
|
// Inject the registered events in the event hook
|
|
|
|
this.eventHook.scriptEnvironment = this.scriptEnv;
|
|
|
|
|
2024-02-07 21:50:01 +08:00
|
|
|
this.commandHook.throttledBuildAllCommands();
|
|
|
|
}
|
|
|
|
// Swap in the expanded function map
|
|
|
|
this.ds.functionMap = functions;
|
|
|
|
}
|
2024-02-28 03:05:12 +08:00
|
|
|
|
|
|
|
invokeSpaceFunction(name: string, args: any[]) {
|
2024-02-28 17:54:03 +08:00
|
|
|
const fn = this.scriptEnv.functions[name];
|
|
|
|
if (!fn) {
|
|
|
|
throw new Error(`Function ${name} not found`);
|
|
|
|
}
|
|
|
|
return fn(...args);
|
2024-02-28 03:05:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
async applyAttributeExtractors(
|
|
|
|
tags: string[],
|
|
|
|
text: string,
|
|
|
|
tree: ParseTree,
|
|
|
|
): Promise<Record<string, any>> {
|
|
|
|
let resultingAttributes: Record<string, any> = {};
|
|
|
|
for (const tag of tags) {
|
|
|
|
const extractors = this.scriptEnv.attributeExtractors[tag];
|
|
|
|
if (!extractors) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
for (const fn of extractors) {
|
|
|
|
const extractorResult = await fn(text, tree);
|
|
|
|
if (extractorResult) {
|
|
|
|
// Merge the attributes in
|
|
|
|
resultingAttributes = {
|
|
|
|
...resultingAttributes,
|
|
|
|
...extractorResult,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return resultingAttributes;
|
|
|
|
}
|
2024-02-07 21:50:01 +08:00
|
|
|
}
|