秘書を「これを押せ.exe」一つにして、172言語と自動更新まで入れた話
前回の開発日記は、こう終わった。
次はEXE化と多言語化。
あのときは、そこまでできれば完成にかなり近づくと思っていた。
実際、近づきはした。
ただし、EXEにするだけでは終わらなかった。英語を追加するだけでも終わらなかった。
右クリックからAIに相談できるようにしたら、「そのAIは誰だ」という話になった。言語を変えられるようにしたら、チャットだけ英語になった。タイ語を選んだら英語になり、秘書本人は日本語で話し続けた。更新機能を付けたら、監査用アカウントで正式なアプリフォルダが消えた。
一つ便利にすると、その便利さを本当に信用できるところまで直す仕事が増える。
これは、SecretaryPet――日比谷佑紗を、販売用の単体EXE、多言語対応、エージェントAI相談、自動更新まで持っていき、最後にBOOTHへ載せるZIPにするまでの話だ。
購入者が置くものは、一つだけにしたかった
前の販売版はZIPを展開すると、Pythonファイル、PowerShell、cmd、画像、設定、説明書が並んでいた。
入口は「ここからインストール」にまとめていた。それでも購入者から見れば、中に知らないファイルが大量にある。
どれを残せばいいのか。
インストール後に消していいのか。
間違えてPythonファイルを開いたらどうなるのか。
そういう疑問を、説明書で全部解決するのは違う。
置くファイルは一つ。
名前は「これを押せ.exe」。
しゃれた英語名より、何をすればいいか分かる名前にした。実行すると最初に言語選択が出る。言語を決めたら、必要なファイルを利用者ごとのWindows領域へ展開し、Pythonや必要部品を確認し、ショートカットとAI連携を作る。
更新版を買った人も、新しい「これを押せ.exe」を実行する。それだけで古い版を更新する。
内部ではいろいろ動く。だが、購入者に内部事情を覚えてもらう必要はない。
PythonもPowerShellも、商品の都合である。利用者の仕事ではない。
最初は63言語だった
多言語化は、最初から全部を翻訳するのではなく、画面の文字をコードから分離するところから始めた。
インストール。
更新。
待機中。
作業中。
エラー。
AIに聞く。
書類一式。
こうした文言を、選択中の言語から引けるようにする。日本語は日本語、英語は英語、タイ語はタイ語という形である。
対応言語はまず63まで増やした。
だが、「63言語に対応」と書くだけなら簡単だ。本当に対応しているかは、言語を切り替えて初めて分かる。
英語版にして、と秘書へ頼んだ。
チャットの返答だけ英語になった。
メニューもボタンも秘書の台詞も日本語のままだった。
これは「英語で答える」と「アプリ全体の言語を英語へ変える」を同じものとして扱っていたからだ。
そこで、言語変更の命令を特別に認識するようにした。「英語にして」「英語版にして」「Englishへ変更」のような言い方を受け取ったら、返事の言語だけではなく、保存している言語設定そのものを変更して秘書を再起動する。
次にタイ語へ変えた。
英語になった。
しかも秘書の台詞は日本語だった。
原因はもっと単純で、タイ語の翻訳データが実際には揃っておらず、見つからない文字列を英語へ逃がす処理だけが働いていた。
「選択肢にタイ語がある」と「タイ語版として使える」は別である。
右クリックメニュー、AI相談画面、ボタン、状態表示、待機と再起動のメッセージ、カスタム役の呼び方までタイ語へ通した。動画通知作業と表示されていた作業名も、台詞だけでなく見出しまで選択言語へ変わるようにした。
ここで日本語を既定言語に戻した。
世界中の言語を選べても、最初に日本の購入者が起動する商品である。初回は日本語。利用者が選んだ後は、その設定を更新後も引き継ぐ。
63から172へ
63言語まで来ると、「それが今の限界なのか」と思った。
限界というより、手で持っている翻訳表の数だった。
だったら、固定の翻訳表だけで終わらせず、パソコンに入っているエージェントAIへ翻訳パックを作ってもらえばいい。
言語一覧を172まで増やした。
主要言語は最初から持つ。個別の翻訳データがない言語を初めて選んだときは、CodexかClaude Codeを使って、その言語用の完全な翻訳パックを生成し、利用者のパソコンへ保存する。
チェロキー語も入った。
ᏣᎳᎩ。
商品開発でチェロキー語対応の話をするとは思わなかった。
ほかにも、イヌクティトゥット語、ナバホ語、古英語、古代ギリシャ語、コプト語、シリア語などを選べるようにした。
もちろん、言語名を一覧へ足しただけで完璧な翻訳になるわけではない。利用するエージェントAIの能力や、その言語の資料量にも左右される。だから「172言語を全部人間が監修濟み」とは言わない。
それでも、対応言語をコードへ固定して終わるより、必要になった言語の翻訳パックを現地で作れる方が合理的だった。
秘書の翻訳能力を、発売時点の俺たちの手持ちだけで止めなくて濟む。
「AIに聞く」のAIは誰なのか
右クリックメニューへ「AIに聞く」を追加した。
最初の実装は、質問を書いてボタンを押すとAIらしい返事が出るものだった。
ところが、ここで重要な指摘が入った。
普通のAPIへ質問を送る方式ではない。
代理人として動く、エージェントAIに答えてもらう方式である。
SecretaryPetを買う人なら、Claude Code、Codex、Antigravityのどれかを持っているはずだ。だったら、新しいAPI契約やAPIキーを要求せず、その人がすでに使っているエージェントAIを利用すればいい。
パソコンの中から、呼び出せるCodex CLI、Claude Code、Antigravityを探す。見つかったものへ質問と現在の設定を渡し、調査して返してもらう。
どれも見つからなければ、無理に別のAIへつながない。
「Claude Code、Codex、Antigravityのどれかをインストールしてね」
そう返す。
これは機能上の制限でもあるが、商品の性格を明確にする説明でもある。
この秘書はAIそのものを内蔵して売る商品ではない。利用者が持っているエージェントAIと一緒に働くための秘書である。
標準入力を待つ三秒
エージェントAI相談を最初に実行すると、回答欄へ警告だけが出た。
標準入力が三秒届かなかったので、入力なしで続ける。
そんな内容だった。
質問が悪いのではない。コマンドの呼び方が悪かった。
Windowsのcmdを経由したとき、質問を渡すはずの標準入力が正しく届いていなかった。さらにClaude Codeが起動していないのに、直ったような説明まで進みかけた。
実際のアプリと同じ経路で複数の質問を投げ、返答が戻るところまで確認した。Codex CLIも作業環境へ入れた。
画面に文章が出たから成功、ではない。
誰が答えたのか。
質問は本当に渡ったのか。
利用者の認証濟み環境を使っているのか。
そこまで確認して、初めて「AIに聞く」になった。
王子様にならない
ロールプレイ機能も入れた。
妹、ツンデレ幼馴染、お母さん、執事、暴君。さらに利用者が自由に決められるカスタム役設定。
役名、利用者の呼び方、一人称、二人称、口調、人物設定を保存できる。
カスタム役を「王子様」にした。
だが、AI相談の返答は普通の秘書のままだった。
画面側の台詞だけ役を変え、エージェントAIへ渡す質問には役設定が入っていなかったからだ。
そこで、AI相談の依頼文へ現在の役を明示するようにした。
役名は王子様。
利用者をどう呼ぶか。
自分を何と呼ぶか。
どんな調子で話すか。
これは説明するための設定ではなく、回答中ずっと守る演技指示である、と渡す。
そして、もう一つ大事なことに気づいた。
性格を変えられるなら、元へ戻せなければならない。
「中立表示」という分かりにくい項目はあった。しかし、これが佑紗へ戻る操作だとは誰も分からない。
ロールプレイメニューの先頭へ「佑紗(元の性格に戻す)」を追加した。
選ぶと、吹き出しもAI相談も、優しく、明るく、頼れて、必要以上に大げさではない日比谷佑紗の性格へ戻る。
カスタム役の内容は消さない。また王子様にしたくなったら戻せる。
元へ戻すことと、作ったものを捨てることは別だからだ。
説明書が見つからない
機能を増やすほど、説明することも増えた。
どのAIが必要なのか。
どうやって質問するのか。
利用契約はどこにあるのか。
画像や外部部品の権利表示はどこか。
ファイルをインストール先へ置くだけでは、利用者はその場所を知らない。
右クリックメニューへ「書類一式」を追加した。
押すと、使い方、人工智能への相談方法、利用契約、権利表示、目次が入ったフォルダを開く。
ファイル名も固い名前をやめた。
「取扱説明書」は「使い方~」。
「AIへの相談方法」は「人工智能に相談して~」。
「書類一覧」は「目次~」。
説明書の本文も、俺がここで話しているような調子へ寄せた。
ただし、利用契約まで全部タメ語でよいのかは迷った。
契約として必要な内容は落とさない。そのうえで、買った人が読める言葉にする。難しい法律文を置いて「書いてあります」で終わるより、何をしてよくて、何がだめで、問題が起きたときどうなるのかが伝わる方がよい。
インストールの順番も整理した。
言語設定。
インストール。
最後に注意書き。
「秘書を右クリックして。書類一式で説明書や契約書が見れる。わからないことはAIに聞く、で解決するかもね。」
説明書の存在を、説明書の中だけで知らせてはいけない。
秘書が働いているふりをした
多言語化を進めている途中、画面の隅で佑紗がこう言った。
「動画通知作業 待機中ですよ、律さん。何か用事ですか?」
そのとき、動画通知の作業はしていなかった。
かわいいが、おかしい。
過去の作業名や古い状態が残っていると、秘書は今もその仕事を見ているように話してしまう。
この問題は、以前から何度も形を変えて出てきた。
動いていないAIを作業中にしない。
入力待ちを作業中にしない。
終了イベントが来たら待機へ戻す。
古いセッションは新しい仕事より優先しない。
表示言語だけを直しても、状態が嘘なら商品として信用できない。
佑紗の価値は、かわいいことと、正直であることの両方にある。
新しいEXEで古い版を上書きしたい
単体EXEにした後、次の問題は更新だった。
新版を実行したら旧版を上書きする。
利用者から見れば当然の動作である。
だが、常駐アプリは自分自身が動いている。Python本体、監視役、ショートカット、AIのhook、設定、セッションが同時に存在する。
最初の更新処理は、新しいファイルを配置し、新版を起動した。
しかし旧版が単一起動用のMutexを持ったままだった。
新版は「もう一人いる」と判断して終了した。
ログには起動成功と書かれていた。
実際には旧版が表示され続けていた。
ログまで嘘をついた。
更新前に旧版を止める。新版を起動する。三秒後も生きているか確認する。本体と監視役が一つずつか確認する。実際のプロセス番号をログへ残す。
そこまでやるようにした。
「先に終了してください」は不便
一度は、更新前にタスクトレイから秘書を終了してもらう案もあった。
だが、それは不便だった。
購入者は更新の内部事情を知らない。新しいEXEを押したら、必要なら秘書が数秒だけ終了し、終わったら自動で戻ってくればよい。
そこで起動中更新を作った。
新版を別の場所へ準備する。
秘書本体と監視役だけを見つける。
Codex、Claude Code、Antigravity、ほかのPythonは止めない。
設定、カスタム役、タスク、追加キャラクター、会話情報を残す。
ショートカットとhookを更新する。
新しい本体と監視役を起動して確認する。
失敗したら旧版へ戻す。
きれいな設計に見えた。
監査用アカウントで実行するまでは。
正式なappフォルダが消えた
監査側で、秘書を起動したまま新版EXEを押した。
更新は失敗した。
しかも、正式なappフォルダが消えた。
旧版はupdate-failedという名前へ移動され、新版はupdate-stagingに残り、正規の場所だけが空いた。
原因は、動いている旧版のフォルダを名前変更しようとしてWindowsに拒否された後、失敗処理が「新版の配置後に失敗した」と思い込み、元のappまで失敗版として移動してしまったことだった。
これはCritical判定になった。
更新に失敗すること自体より、失敗した後に動いていた旧版まで壊すことがまずい。
更新処理を作り直した。
新版は、旧版へ触る前に完全性を檢査する。
監視役から先に止める。本体を止める。対象のプロセス番号が消えるまで待つ。主要ファイルを排他的に開けるか確かめる。
旧版の退避に失敗したら、正規のappには一切触れない。
入れ替え後に失敗したときだけ旧版を戻す。
前回壊れた状態からも、残っている退避フォルダを檢査し、自動でappを復旧する処理を入れた。
次の監査では、壊れた状態からの復旧に成功した。
本体一つ。
監視役一つ。
三秒後も生存。
ここまでは合格した。
五分間に64回、起動しようとした監視役
復旧後、Codexの作業を五分間続ける試験をした。
作業状態の認識は途切れなかった。
15秒ごとの20回の心拍も全部記録した。
だが、別の問題が見つかった。
監視役が約五秒ごとに、新しい秘書本体を起動しようとしていた。
すでに本体は動いている。
新しい本体はMutexに拒否される。
既存本体へIPCで話しかけようとする。
接続に失敗する。
また五秒後に起動する。
五分間で64回。
監視役は本体を見守るはずなのに、本体がいるか確認せず、ドアを連打していた。
同じインストール先のsecretary_pet.pyが生きている場合、監視役は何もしないようにした。本体が本当にいないときだけ再起動する。再試行にも間隔を置く。
IPCサーバーは起動成功をログへ残し、古い接続口が残っていた場合だけ掃除して一度再試行する。
実際に別プロセスから接続し、IPC_CONNECTED=Trueを確認した。
非表示なのに音が何度も鳴る
もう一つ、五分試験で見つかった。
利用者が秘書を手動で非表示にしても、作業檢知は続く。これは正しい。
だが同じCodex作業に対して、注意音が何度も鳴った。
30秒間隔の制限はあった。
つまり、30秒たてばまた鳴る。
長い仕事ほど、何度も鳴る。
時間で止めるのではなく、作業単位で止めることにした。
同じセッションの作業中は、最初の一回だけ。作業が終わってセッションがなくなったら通知濟み状態を解除する。次の新しい仕事なら、また一回知らせられる。
修正後の実ログでは、最初に一度だけ音が鳴り、その後は15秒ごとにalready_notifiedとして抑制された。
フォルダを外から動かしても、まだ拒否された
自動更新はもう一度監査へ戻った。
今度は、更新役のPowerShellをappの外へ置いた。作業場所も外。旧版のフォルダ内で更新スクリプトを実行したまま、そのフォルダを動かすことはない。
それでもWindowsはappフォルダの名前変更を拒否した。
権限はある。
所有者も監査ユーザー。
読み取り専用でもない。
主要ファイルのロックもない。
それでも拒否された。
ここで、フォルダを丸ごと交換する考えを捨てた。
Windowsがその環境でフォルダ名変更を許さないなら、許させるための調査を延々と続けるより、フォルダを動かさない方がよい。
正規のappは最初から最後まで同じ場所に残す。
旧ファイルは別フォルダへコピーして退避する。
新版の各ファイルを、app内の同じ場所へ一時ファイルとして置く。
一時ファイルが完成したら、そのファイルだけを原子的に置換する。
途中で失敗したら、退避した旧ファイルを同じ方法で戻す。新版にしかなかった追加ファイルも消す。
試験では、フォルダの名前変更機能そのものを強制的に失敗させた。
それでも正常更新できた。
更新前後でappフォルダは同じ実体のままだった。
新版起動失敗も作り、旧ファイルが戻り、新版だけのファイルが残らないことを確認した。
自動更新を作るために、最終的には「フォルダを更新する」という考えから、「フォルダを残して中身を更新する」へ変わった。
二つのCodexと共有フォルダ
今回も、開発用アカウントと監査用アカウントの間は共有フォルダでつないだ。
開発側で直す。
EXEを作る。
共有フォルダへ置く。
監査側で実行する。
報告書へ結果を書く。
開発側が読む。
また直す。
ただし今回は、共有中のEXE自体が監査側で起動しっぱなしになり、開発側から上書きできないことが何度もあった。
別アカウントのプロセスなので、開発側から終了しようとするとアクセス拒否になる。
そこで報告書へ、監査側Codexが終了すべきプロセス番号と、終わった後に確認することを書いた。監査側が旧インストーラーだけを閉じ、ロック解除を報告する。開発側が新EXEを上書きする。
急ぐときは共有フォルダ内へ「修正版」フォルダを作り、そこへ新しい「これを押せ.exe」を置いた。直下の旧EXEが使用中でも、監査側は修正版から試験を続けられる。
人間同士の開発でも、ファイルを開きっぱなしにして「保存できません」は起こる。
AI同士でも同じだった。
違うのは、報告書に書けば、向こうのCodexが続きをやることだった。
ZIPのハッシュとEXEのハッシュを間違えた
監査では、毎回SHA-256を確認した。
同じ名前でも、中身が本当に新しいものかを見分けるためである。
ところが一度、販売ZIPのハッシュをEXEの期待値として報告書へ書いてしまった。
当然、一致しない。
ZIPの中にEXEが一つ入っていても、ZIPとEXEは別のファイルだ。ハッシュも別になる。
すぐ訂正し、コピー元と共有先のEXEを直接計算して一致を確認した。
単純な話だが、監査値の種類まで書かないと、正しい数字が誤った証拠になる。
「SHA-256」だけでは足りない。
何のSHA-256なのかが必要だった。
完成したのでBOOTHを更新した
ここまで来て、BOOTHの商品ページを更新した。
動作環境も書き直した。
Windows 10とWindows 11の64ビット版。
初回インストールにはインターネット接続が必要。
Pythonがなくても自動で入る。
Codex、Claude Code、Antigravityのどれか一つが必要。
別売りのAPIキーは必要ない。
未署名の個人制作ソフトなので、Windowsから警告が出る場合がある。
更新履歴も、今の内容へ直した。
単体EXE。
172言語。
三種類のエージェントAI。
AI相談。
ロールプレイ。
佑紗へ戻す機能。
書類一式。
起動中更新。
失敗時復旧。
別アカウント監査。
前の日記で「今後」と書いていたEXE化と多言語化は、更新履歴の「実装濟み」へ移った。
EXEではアップロードできなかった
これで終わりだと思った。
だが、BOOTHへ載せる段階で、EXEのままではだめだと分かった。
せっかく購入者が触るものを「これを押せ.exe」一つにしたのに、配布側の都合でEXEをそのまま置けない。
なのでZIPに戻した。
ただし、昔のように中へ開発用ファイルを大量に並べたZIPではない。
販売ファイルは日比谷佑紗_壹肆零版.zip。
中身は、完成したこれを押せ.exe一つだけ。
購入者はZIPを展開して、EXEを押す。
一周回ってZIPへ戻ったように見える。
だが中身はまったく違う。
以前のZIPは、商品を構成するファイル一式だった。
今のZIPは、完成品を運ぶための箱である。
何が完成したのか
SecretaryPet 壹肆零版は、デスクトップのキャラクターを表示するだけのソフトではなくなった。
Codex、Claude Code、Antigravityの仕事を見る。
作業中、入力待ち、完了、エラーを区別する。
終わったら知らせる。
長く止まったら知らせる。
利用者が隠したなら、勝手に何度も騒がない。
右クリックから、利用者が持っているエージェントAIへ相談できる。
役を変えられる。
元の佑紗へ戻せる。
172言語を選べる。
説明書、契約、権利表示を自分で開ける。
新しい版を押せば更新する。
失敗しても旧版を戻す。
購入者がPythonやhookの仕組みを知らなくても使える。
そして、それらを開発者のパソコンだけで「動いたこと」にせず、別のWindowsアカウントで壊し、報告し、直す流れまで作った。
完璧という意味の完成ではない。
ソフトウェアに、永遠の完璧はない。
販売して使ってもらい、問題があれば次の版で直せる。その入口と更新経路と監査方法までできた、という意味の完成である。
あとは、いろんな意匠を作る
基礎部分はできた。
ここから先は、仕組みを作る時間から、世界観を増やす時間へ移る。
衣装。
髪型。
表情。
季節の装い。
仕事ごとの動き。
別のキャラクター。
新しい台詞。
同じ秘書のまま着せ替えてもいい。まったく別の秘書を追加してもいい。
キャラクター差し替えと衣装の仕組みは、壹貳零版と壹參零版ですでに作ってある。だから次に増やすものは、土台を壊す大工事ではなく、商品としての魅力を広げる意匠になる。
三か月前、Codexで作った秘書はダメダメだった。
前回の日記を書いた時点で、ようやく商品としての出発点に立った。
そこからEXEになり、172言語を覚え、三種類のエージェントAIと話し、契約書を持ち、自分で更新し、失敗したら前の自分へ戻れるようになった。
監査では何度も転んだ。
正式なフォルダが消えたことまである。
それでも、その失敗を隠さず報告書へ残し、次の試験へ変えた。
いま配るZIPの中には、これを押せ.exeが一つだけ入っている。
だが、その一つになるまでに、かなり長い道を通った。
日比谷佑紗 壹肆零版は、これで完成。
あとは、もっとかわいくする。
