この記事を作った動機

 2026/9/2 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。

次に軽くやりたいことを記述

 まだ拡張機能の読み込み部分は、とりあえず書いたという段階であり、パスやインポートの記述がおかしかったりするおそれがあり、デバッグが必要である。また、拡張機能を読み込んで DataServer が動作する事を確認するために、Core 拡張機能を完成させる必要がある。

 Core 拡張機能を完成させるためには、主にパスの解決が正しく出来るように、拡張機能のモジュール呼び出しにおいて、どうやってmainSysと提携させるかが課題となっている。今具体的に考えている実装の一つとしては、モジュール呼び出し時に、DataServer のルートのパスや Notebook へのパスは、拡張機能ではない DataServer 側の組み込みの実装としてパスを解決しモジュールに伝える機構を実装することが考えられた。

 また、mainSysについては、Python の仮想環境機能を使うことが考えられた。依存関係などをインストールするとき、既にインストールされている Python 環境を汚したりしてしまうのは避けたいと考えた。仮想環境は、存在しなければ拡張機能読み込みの段階で初期化し、存在すればそれが DataServer 起動時などに有効化されて使われるというような事を考えている。

 今回の試作物としては、とりあえず DataServer が拡張機能を介して動作するということを最低限の目標としたいと考えた。そこまでできたら次は、3つ目のプロトタイプとして今度はフロントエンドをなんとかするというロードマップにしようかなと作業と進捗状況から思ったところであった。フロントエンドには、zustand のストアにおける値が異なるストア間で重複しているなど、SQLの文脈におけるデータ項目の重複と正規化の問題があり、その点がまず修正点としてあげられる。

 DataServer において、WebSocket によるフロントエンドとの接続に関してセッションを管理したい。フロントエンドが接続してきたら、それぞれのフロントエンド自体をUUIDなどで識別して、正しく Command や Interrupt の経路がつながっているか管理することを考えている。

やったことの詳細

Core 拡張機能を実装

 完全ではないが、とりあえず最低限の機能を DataServer に与えるために、Core 拡張機能を作成し、中身には前回のプロトタイプで存在していた、command、interrupt、task の実装を移植した。移植したと言っても配置して、manifest.jsonにまだその存在を記述しただけであり、まだ今回の試作物に適合させる実装がこれから必要である。

 manifest.jsonの実装についても変更点があり、DataServerの項目についてCommandModulesInterruptModulesTaskModulesの3つに分けて、モジュールを記述するようにした。それぞれは、拡張機能のmanifest.jsonがあるフォルダを起点としたモジュールまでの相対パスが記述されている。それぞれのモジュールは1つのスクリプトで1つのモジュールという構成にしており、[moduleName].pyというモジュールであれば、内部にある関数名は必ず、def [moduleName](request,websocket):の形態を取る必要がある。パスの解決の問題により、今後モジュールが共通して受け付けるべき引数が増える可能性がある。

    "DataServer":{
        "CommandModules":[
            "backend/commands/info.py",

            "backend/commands/notebookAndPage/createNotebook.py",
            "backend/commands/notebookAndPage/deleteNotebook.py",
            "backend/commands/notebookAndPage/getPageType.py",
            "backend/commands/notebookAndPage/pageInfo.py",
            "backend/commands/notebookAndPage/updatePage.py",
            "backend/commands/notebookAndPage/copyPage.py",
            "backend/commands/notebookAndPage/createPage.py",
            "backend/commands/notebookAndPage/deletePage.py",
            "backend/commands/notebookAndPage/movePage.py",
            "backend/commands/notebookAndPage/renamePage.py",

            "backend/commands/notebookAndPage/addTag.py",
            "backend/commands/notebookAndPage/createTag.py",
            "backend/commands/notebookAndPage/deleteTag.py",
            "backend/commands/notebookAndPage/getTagList.py",
            "backend/commands/notebookAndPage/queryTag.py",
            "backend/commands/notebookAndPage/removeTag.py",

            "backend/commands/notebookAndPage/fileAdd.py",
            "backend/commands/notebookAndPage/fileData.py",
            "backend/commands/notebookAndPage/fileDelete.py",
            "backend/commands/notebookAndPage/fileInfo.py"
        ],
        "InterruptModules":[
            "backend/interrupts/newInfo.py",
            "backend/interrupts/updatePage.py",
            "backend/interrupts/updateTag.py"
        ],
        "TaskModules":[
            "backend/tasks/pageCleaner.py",
            "backend/tasks/showPingMessage.py"
        ]
    },

 manifest.jsonの他の変更点としては、別の拡張機能を依存関係として書けるようにした。具体的にどうやって異なる拡張機能間を上手く提携させるか、どういう課題があるかはみえていないが、とりあえず拡張機能の依存関係を記述できるようにした。例は以下のようなものである。

{
    //...
    "extensionDependencies":[
        {
            "name": "Core",
            "UUID": "589fe65d-639c-42a3-b395-fca2143afd75"
        }
    ]
}

extensionLoaderに関して実装を進めた

 extensions 配下に配置された拡張機能の zip を展開して、文字列操作をした後に、runtime.pyとしてmainSysに組み込む実装を行った。manifest などのバリデーションは存在を確認するだけの簡易的な実装であり、まだ中身のキーなどの検証についてはとりあえず動くことを優先し、実装していない。

 また、拡張機能の要件を追加した。具体的には、Python の依存関係を記述した requirements.txtファイルがあることを要件とした。これにより、拡張機能を読み込むとと同時に、自動的に依存関係をインストールできるようにする試みである。

mainSysに対するコントローラモジュールに関する変更点

 設計上の変更点としては、command、interrupt、task のそれぞれのコントローラが参照するモジュールの辞書型の変数名をextensionMoludesとするところから、それぞれのコントローラ用に独立させるために、commandExtensionMoludesinterruptExtensionMoludestaskExtensionMoludesとした。その意図としては、複数のランタイムファイルを生成すると実装が煩雑になり、バグになりやすいと考えたところがある。それぞれの名前が衝突しないようにすることで、ランタイムは DataServer に関しては、runtime.pyに全てを記述すれば揃うことになり、そっちのほうがやりやすいだろうということになった。

 他の変更点としては、コマンドの呼び出しを、[拡張機能名]-[UUID]/[コマンド名(モジュール名)]という形態にした。同じ名前の拡張機能があっても、呼び出しにおいて衝突しないようにした。ただ、拡張機能を開発する側としては余分に、UUID を指定する必要があるため、拡張モジュールの開発のしやすさに影響が出ると考えられる。

研究に関係ありそうなブログ記事

 今回は特になし。

参考にしたサイトとか