1
0
Junyi Du 2 жил өмнө
parent
commit
8b246753d7

+ 27 - 0
docs/plugin-system.md

@@ -0,0 +1,27 @@
+## Description
+
+This page describes design & (Logseq side) development practices for the plugin system.
+
+This page is a work in progress. Contributions are welcome.
+
+## Basic concepts
+
+`@logseq/libs` are the dependencies for the plugin sandbox environment side. It should be imported by the plugin. Refer plugin dev documents for detail.
+
+The entry point of Logseq APIs in ClojureScript is `src/main/logseq/api.cljs`. 
+
+Then they will be exposed to plugin sandbox environment in `libs/src/LSPlugin.user.ts`. The communication between Logseq and Plugin is done via `_execCallableAPI` or `_execCallableAPIAsync`.
+
+## Service
+
+To define a service, you need to:
+
+1. Define the service register in Logseq, in `src/main/logseq/api.cljs`
+
+2. Define the service register in plugin sandbox environment, in `libs/src/LSPlugin.user.ts`
+
+Then a plugin can register the service. Next, we want to call the registered service from Logseq:
+
+3. Implement the `call-service!` logic in Logseq, and invoke the service call in Logseq
+
+4. Implement the service hook logic in `libs/src/modules`, which handles / replies the service calls (3.) from Logseq

+ 1 - 1
libs/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@logseq/libs",
-  "version": "0.0.15",
+  "version": "0.0.16",
   "description": "Logseq SDK libraries",
   "main": "dist/lsplugin.user.js",
   "typings": "index.d.ts",

+ 1 - 1
libs/src/LSPlugin.ts

@@ -331,7 +331,7 @@ export interface IPluginTextEncoderServiceHooks {
   name: string
   options?: Record<string, any>
 
-  textEncode: (text: string) => Promise<string>
+  textEncode: (text: string) => Promise<Float32Array>
 }
 
 /**

+ 16 - 1
libs/src/LSPlugin.user.ts

@@ -35,7 +35,7 @@ import {
   BlockEntity,
   IDatom,
   IAssetsProxy,
-  AppInfo, IPluginSearchServiceHooks,
+  AppInfo, IPluginSearchServiceHooks, IPluginTextEncoderServiceHooks,
 } from './LSPlugin'
 import Debug from 'debug'
 import * as CSS from 'csstype'
@@ -44,6 +44,7 @@ import { IAsyncStorage, LSPluginFileStorage } from './modules/LSPlugin.Storage'
 import { LSPluginExperiments } from './modules/LSPlugin.Experiments'
 import { LSPluginRequest } from './modules/LSPlugin.Request'
 import { LSPluginSearchService } from './modules/LSPlugin.Search'
+import { LSPluginTextEncoderService } from './modules/LSPlugin.TextEncoder'
 
 declare global {
   interface Window {
@@ -113,6 +114,9 @@ function checkEffect(p: LSPluginUser) {
 let _appBaseInfo: AppInfo = null
 let _searchServices: Map<string, LSPluginSearchService> = new Map()
 
+// AI services
+let _textEncoderServices: Map<string, LSPluginTextEncoderService> = new Map()
+
 const app: Partial<IAppProxy> = {
   async getInfo(
     this: LSPluginUser,
@@ -137,6 +141,17 @@ const app: Partial<IAppProxy> = {
     _searchServices.set(s.name, new LSPluginSearchService(this, s))
   },
 
+  registerTextEncoderService<T extends IPluginTextEncoderServiceHooks>(
+    this: LSPluginUser,
+    s: T
+  ) {
+    if (_textEncoderServices.has(s.name)) {
+      throw new Error(`TextEncoderService: #${s.name} has registered!`)
+    }
+
+    _textEncoderServices.set(s.name, new LSPluginTextEncoderService(this, s))
+  },
+
   registerCommandPalette(
     opts: { key: string; label: string; keybinding?: SimpleCommandKeybinding },
     action: SimpleCommandCallback

+ 3 - 3
src/main/frontend/ai/text_encoder.cljs

@@ -5,11 +5,11 @@
             [frontend.handler.plugin :as plugin-handler]
             [cljs-bean.core :as bean]))
 
-(defn- call-text-encoder-service!
+(defn- call-service!
   "Handling communication with text encoder plugin
   When reply? is true, it will listen to the `service:<event>:<name>:reply `event
   and return a promise of the result"
-  ([service event payload] (call-text-encoder-service! service event payload false))
+  ([service event payload] (call-service! service event payload false))
   ([service event payload reply?]
    (when-let [^js pl (plugin-handler/get-plugin-inst (:pid service))]
      (let [{:keys [name]} service
@@ -25,7 +25,7 @@
 
 (defn- text-encode'
   [text service]
-  (call-text-encoder-service! service "textEncoder:textEncode" {:text text} true))
+  (call-service! service "textEncoder:textEncode" {:text text} true))
 
 (defn text-encode
   "Return a promise of the encoded text"

+ 0 - 10
src/main/frontend/state.cljs

@@ -1589,16 +1589,6 @@ Similar to re-frame subscriptions"
     (set-state! :search/engines
                 (update-vals engines #(assoc % :result nil)))))
 
-(defn get-all-plugin-text-encoders
-  []
-  (:ai/text-encoders @state))
-
-(defn reset-plugin-text-encoder
-  []
-  (when-let [encoders (get-all-plugin-text-encoders)]
-    (set-state! :ai/text-encoders
-                (update-vals encoders #(assoc % :result nil)))))
-
 (defn install-plugin-hook
   ([pid hook] (install-plugin-hook pid hook true))
   ([pid hook opts]

+ 6 - 3
src/main/logseq/api.cljs

@@ -396,17 +396,20 @@
   [pid]
   (plugin-handler/unregister-plugin-search-services pid))
 
-(defn ^:export register_text_encoder
+(defn ^:export register_text_encoder_service
   [pid name ^js opts]
+  (prn "register_text_encoder_service") ;; TODO Junyi
   (plugin-handler/register-plugin-text-encoder pid name (bean/->clj opts)))
 
-(defn ^:export unregister_text_encoders
+(defn ^:export unregister_text_encoder_services
   [pid]
   (plugin-handler/unregister-plugin-text-encoders pid))
 
 (defn ^:export text_encode
   [text encoder-name]
-  (text-encoder/text-encode text encoder-name))
+  (if encoder-name
+    (text-encoder/text-encode text encoder-name) 
+    (text-encoder/text-encode text)))
 
 (def ^:export register_plugin_ui_item
   (fn [pid type ^js opts]