1tempo
曖昧な依頼文を MiL へ変換し、承認してから dsh で選択中のモデルへ渡す dsh プラグイン。
/onetempo 3Dモデルを作って
↓ sarashina が MiL へ変換(mil-spec を system に渡す)
↓ 原文と MiL を表示し、承認(必要なら修正)
↓ 承認済みの MiL を、dsh で選択中のモデルへ渡す
- 確定設計: architecture.md
- dsh への要望(会話へ書く API): dsh-feature-request.md
- 企画の原案・質疑応答・実測レポート(
proposal.md/qa-record.md/preflight-report-*.md)はローカル記録のため、この公開リポジトリには含めていない。本文中のpreflight-report-run*.mdはその記録のファイル名を示す。
何をするか
/onetempoが起動したときだけ動く。通常の依頼文には反応しない。- 依頼文を Sarashina API に送り、MiL へ変換する。
- 原文と MiL を表示し、承認を求める。承認前に編集もできる。
- 承認された MiL を、dsh の選択モデルへ 利用者のメッセージとして 渡す(
source.kind: 'user')。dsh はsource.kind === 'user'のメッセージだけを利用者の行として扱い、/rewindの戻り先にもする(それ以外はコンテキスト行になり、会話に出ない)。変換の来歴はプラグインの storage ログと通知に残す。 - 原文・MiL・逆翻訳・変換モデル・呼び出し回数・承認有無を dsh の storage に記録する。storage が使えない場合は「ログ: 保存できませんでした(理由)」と出し、保存したように見せない(セッション内の記録だけを保持する)。
必要なもの
- dsh(
@deepseek-harness-tui/dsh-tuiが入ったプロファイル) - Node.js 24 以降(テストと測定ツールで確認)
SARASHINA_API_KEY(Sarashina で発行。無償ベータ、Google ログイン、事前申し込み不要)
キーの指定方法は以下のいずれか(優先順位順):
~/.dsh/.credentials.yaml(dsh 標準の認証情報ファイル、推奨)- 環境変数
SARASHINA_API_KEY(.envを使う場合はnode --env-file=.env)
# 測定ツールの例(~/.dsh/.credentials.yaml にキーがあれば --env-file 不要)
node tools/preflight-decode.mjs --dry
使い方
/onetempo [mini|nano] [back] <依頼文>
| 引数 | 意味 |
|---|---|
mini / nano |
変換モデルの上書き。sarashina3-mini(6 RPM) / sarashina3-nano(60 RPM、既定) |
back |
逆翻訳(MiL を自然語へ戻したもの)も表示する。省略時は設定の既定 |
<依頼文> |
変換対象。フラグの後に来た文字列をそのまま使う |
引数なしの /onetempo は使い方を表示する。
名前について: プロジェクト名は 1tempo だが、コマンドと識別子は
onetempo。dsh のコマンド名とプラグイン所有の設定名前空間は/^[a-z][a-z0-9_-]*$/(英小文字で始まる)に一致する必要があり、当初案の1tempoは数字始まりのため拒否される(実測:command name "1tempo" must match .../invalid TUI settings-section namespace: 1tempo)。表示名(1tempo、設定セクションの見出し、source.plugin)は1tempoのまま。
表示と承認
- 変換結果は 通知欄 に出る。200 セル以内に収まる形に整形する(
1tempo: 送信しました…/MiL: <送信する MiL>/ 逆翻訳・ログ行)。- dsh はプラグインのコマンド結果を
channel.notify(cleanRenderText(text, COMMAND_RESULT_CELLS = 200))で通知欄に描く。200 セルを超えた分は…で切られるため、先頭を MiL にし、続く注記は予算内の分だけ載せる(プラグイン側では切り詰めない) - 長い MiL の全文は承認ダイアログの初期値(490 セルまで)で読める
- dsh はプラグインのコマンド結果を
- 会話に出るのは送信メッセージの本文だけ(
content)。本文は MiL のみ。contentは「会話に表示されるテキスト」と「モデルが読むテキスト」を兼ねる。dsh に両者を分ける欄は無い(実測:tools/inspect-session-log.mjs --grepでagent/inbox/splicedに本文が入ることを確認)。そのため原文を会話に出すと、そのままモデルにも渡るincludeOriginalInMessage: trueにすると本文が「依頼: <原文>」→「MiL: …」になる。会話の行が自分の言葉で始まり/rewindで識別しやすいが、MiL の圧縮効果は失われる。既定はfalsesourceは{ kind: 'user' }のみ(formを付けない)。dsh はisHuman = sourceKind === 'user'の一点で利用者とプラグインを区別し(dsh-adapter/trajectory/projection.js)、/rewindも同じ条件で戻り先を選ぶ(sessionTree.js)。plugin:1tempoのままだと context 行になり会話に出ず、formを付けると行ごと消える(どちらも実機で確認)。代償: セッションログ上は「利用者が送った」記録になる。変換の来歴は storage ログと通知に残す(qa-record.md§6.22)- 会話へ任意の行を足す API は無い。プラグインのコマンド結果は通知に回り(200 セル上限)、
session.appendでログ専用イベントを足すこともできない(ignorableを付けられない)。「会話にだけ原文を出す」要望はdsh-feature-request.mdの提案 6(入力欄へ本文を入れる API)にまとめた
- 承認は 編集ダイアログ 1 つだけ。MiL がダイアログの初期値として表示されるので、その場で読んで確認できる。
- そのまま Enter → 送信
- 本文を編集して Enter → 修正した MiL を送信
- Esc / Ctrl+C → 送信を取り消す(未編集の MiL を勝手に送らない)
dialogTimeoutMs(既定 3 分)を過ぎた場合も取り消す
- 確認ダイアログ(「この MiL を送信しますか」)は 2026-10-14 に廃止した。コマンドの出力はハンドラの終了後に出るため、その時点では MiL が画面に無く、見えないまま承認させることになっていた。
- MiL が 490 セルを超える場合は編集ダイアログを開かず、表示のみ行う。
- MiL が質問のみで内容を持たない場合は、その旨を注記に出す(依頼の要件が落ちていないかを確認するため)。
- 変換に失敗したときは、設定
failureModeに従う(既定は「原文をそのまま送るか確認」。自動送信はしない)。 - ダイアログ下部の操作ヒント(
Enter to confirm · Esc to cancelなど)は dsh のダイアログ部品が描くもので、プラグインからは消せない。消すにはダイアログを使わない方式(会話で完結する 2 段階)へ変える必要がある。
インストール(dsh への登録)
このリポジトリは dsh の bundle パッケージとして作ってある(package.json の dsh.bundle.patch → cordis.patch.yml)。したがって、展開も手作業の設定も不要で、dsh のプラグイン管理から spec を指定するだけで入る。
1. Web UI の Plugins ページから(推奨)
サイドバーの Plugins ページで追加先に次を入れて Install する。
github:puyokura/dsh-1tempo
- dsh のプラグイン管理(
@deepseek-ai/dsh-plugin-manager)がpnpm addでこのリポジトリをプロファイルへ入れ、bundle を既定で有効化し、同梱のcordis.patch.ymlの行を適用する。手でcordis.patch.ymlを編集する必要はない。 - プロファイルが HMR 有効(
patchReload: live)ならその場で反映される。無効なら dsh を再起動する。 - 削除も同じページから行える(
pnpm remove相当)。
エージェント経由なら plugin_manager ツールの install_bundle に同じ spec を渡す(Creator 系プリセットで有効。実行には danger-full-access か承認が要る)。
2. プロファイルへ CLI で入れる(bundle 方式)
Web UI を使わない場合(サーバー上で動かす、ヘッドレスなど)は同じ操作を CLI で行う。
cd ~/.dsh/profiles/<プロファイル名>
pnpm add github:puyokura/dsh-1tempo
次に package.json の dsh.profile.bundles の末尾へ "dsh-plugin-1tempo" を足す。pnpm add だけでは bundle は有効にならず、この 1 行が Install ボタンの仕事にあたる。
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-plugin-1tempo"
],
- 反映は
patchReload: liveなら即時、そうでなければ dsh を再起動する。 - 戻すときは
pnpm remove dsh-plugin-1tempoとbundlesからの削除。 - サーバー側の Web UI で使う場合、
SARASHINA_API_KEYはそのサーバーの~/.dsh/.credentials.yamlに置く。プラグインはコマンド実行時にキーを読むため、置いた時点で有効になる(再起動は不要)。
3. プロファイルのパッチへ直接書く(手動・従来の方法)
プロファイルのパッチ(例: ~/.dsh/profiles/dsh-tui/cordis.patch.yml)の insert: に 1 行追加する。
- id: onetempo
name: <このリポジトリの絶対パス>/index.mjs
config:
model: sarashina3-nano
specPreamble: off
nameはindex.mjsの絶対パス。Windows ではスラッシュ区切りで書く(例:C:/Users/you/1tempo-pulgin/index.mjs)。idは設定画面が設定セクションを引く名前空間になる。/^[a-z][a-z0-9_-]*$/に一致する必要がある(1tempoは不可)。configは省略可能。省略時は下記の既定値が使われる。- bundle として入れたプロファイルに、この手動の行を足さない(同じ
id: onetempoが二重になる)。すでに手動の行があるプロファイルへ bundle を入れるときは、先に手動の行を消す。 - 読み込みに失敗すると dsh の起動がロールバックする。戻すときはこの 4 行を削除する。
Web UI(プロファイル web)
同じ手順(上記 1 か 2)を web プロファイルへ行う。手動で入れる場合だけ、insert: 行を ~/.dsh/profiles/web/cordis.patch.yml に置く。プラグインはどちらのホストでも動く(接点は実行時に選ばれる)。
| 用途 | TUI(dsh-tui) |
Web UI |
|---|---|---|
| コマンド登録 | ctx.tuiPluginHost(帰属つき)。無ければ ctx.commands |
ctx.commands(コアが提供。結果テキストは会話のコマンドカードに出て、複数行は展開表示になる) |
| 確認・編集 | ctx.tuiDialogs.input(初期値つき) |
ctx.userQuestions.ask の自由記述。初期値の欄が無いので、現在の MiL は detail に出る。空のまま送ると、その MiL をそのまま使う |
| 中止 | Esc / Ctrl+C / タイムアウト | 質問の取り消し、または dialogTimeoutMs での打ち切り |
| ログ | ctx.tuiPluginStorage(~/.dsh-tui/plugin-storage/、grant が必要) |
ctx.storageDomain(~/.dsh/storages/tempo_bridge.json、grant 不要) |
- TUI 固有の 3 サービス(
tuiPluginHost/tuiDialogs/tuiPluginStorage)は Web ホストに存在しない。ctx.storageDomainは逆に TUI ホストに mount されていない(実測 2026-10-15)。 - どちらの対話接点も無い構成では、MiL を表示するだけで送信しない(未確認の送信を避ける)。
設定
config または設定セクション(/settings)で変更する。未知の値は警告つきで既定に落ちる。
| キー | 既定 | 意味 |
|---|---|---|
model |
sarashina3-nano |
変換モデル(sarashina3-mini / sarashina3-nano) |
backtranslate |
off |
always で逆翻訳も表示(追加で 1 回呼び出す) |
atSymbol |
ext: |
送信前に @ を置換する ASCII 記号。@ と空白と先頭 # は使えない |
failureMode |
confirm |
confirm(原文送信を確認) / abort(常に中止) |
specPreamble |
off |
off(MiL のみ送る) / prepend(定義行を前置。原典の運用と同じ) |
includeFrozenExample |
true |
形式の見本と依頼の見本を変換指示に同梱する |
stripSpecClauses |
true |
変換結果から、定義と逐語一致する節を除去する |
replyLanguageSectionEnabled |
false |
system prompt に返答言語の指示を足す |
replyLanguageSection |
(日本語で返す旨の 1 文) | 上を有効にしたときの文面 |
convertInstruction |
(同梱の既定文) | 変換の指示文(見本はこの後ろに付く) |
backtranslateInstruction |
(同梱の既定文) | 逆翻訳の指示文 |
temperature |
0 |
再現性のため 0 に固定 |
seed |
20261014 |
ベストエフォートの決定性 |
maxCompletionTokens |
2000 |
1〜8000 |
retryWaitsMs |
[10000, 20000, 40000] |
429・一時サーバーエラー(5xx)・転送失敗の再試行間隔(最大 3 回) |
requestTimeoutMs |
60000 |
1 呼び出しの上限 |
dialogTimeoutMs |
180000 |
承認・編集ダイアログの上限。明示しないとホスト既定の 30 秒で勝手に取り消される |
minIntervalMs |
null |
連続呼び出しの最小間隔。null ならモデルの RPM から算出(nano 1000ms / mini 10000ms) |
includeOriginalInMessage |
false |
true にすると送信本文の先頭に「依頼: <原文>」を入れる。会話の行が自分の言葉で始まり /rewind で識別しやすいが、その原文はモデルにも渡る(content は会話とモデル入力の両方を兼ねるため、MiL の圧縮効果が失われる) |
specPreamble の使い分け(実測に基づく指針)
prepend は定義行を MiL の前に置く。原典の使用例(例A)と同じ運用で、対象モデルが MiL を知らない場合に復号が安定する。代わりにペイロードが定義行の分だけ長くなる。off は軽く、MiL のみを送る。
どちらも復号テストに合格している(preflight-report-run6-off.md / preflight-report-run7-prepend.md。ローカル記録)。対象モデルが MiL を初めて見る場合は prepend、すでに文脈がある場合やトークンを抑えたい場合は off を目安にする。
記法(MiL)と本プラグインの立場
MiL は @AM09_21 が CC0 1.0 で公開した記法。本プラグインは仕様を改良も公式化もしない。
- 定義本体: https://x.com/AM09_21/status/2103233036817170460
- 精密化: https://x.com/AM09_21/status/2103282758231707887
@衝突の報告: https://x.com/AM09_21/status/2103290587374096573
仕様の写しと、本プラグイン独自の追加規則は mil-spec/ にある。
| ファイル | 用途 |
|---|---|
mil-spec/prompt-v0-snapshot-2026-09-25.txt |
変換呼び出しの system に渡す定義行のみ |
mil-spec/v0-snapshot-2026-09-25.md |
出典・引用・読み取れる規則・未取得の記録(人向け。モデルには渡さない) |
mil-spec/reference-style.txt |
原典で実際に使われていた本文の形(転記)と合成例 |
mil-spec/examples-v0.txt |
依頼 → MiL の見本(本プラグインが作成。原典には依頼の変換例が無い) |
mil-spec/author-examples.md |
原典の使用例の転記と、そこから読み取れること |
本プラグイン独自の規則(原典には無い。mil-spec/v0-snapshot-2026-09-25.md §4):
- 送信直前にトークン先頭の
@をext:へ置換し、復元しない(dsh が@をファイルメンションとして展開するため)。 - 返答言語の指示を system prompt に足せる(既定は無効)。
開発
node --test "tests/*.test.mjs" # 173 件
| パス | 内容 |
|---|---|
index.mjs |
プラグイン本体(name / inject / apply、コマンド引数の解釈、変換フロー、ダイアログ、接点の登録) |
cordis.patch.yml |
bundle として配布するためのパッチ(- id: onetempo の 1 行)。package.json の dsh.bundle.patch が指す |
locale/{en,ja}.json |
dsh のプラグイン一覧に出す表示名と説明(meta.title / meta.description) |
src/delivery.mjs |
承認後の送信(通知の組み立て、送信本文、エージェント選択、ログ結果の報告) |
src/seams.mjs |
任意接点の soft probe(無い構成でも落とさない) |
src/interaction.mjs |
対話接点の抽象化。TUI は ctx.tuiDialogs(初期値つき)、Web は ctx.userQuestions(自由記述のみ・初期値なし・タイムアウト無し=自前の signal で bound)。どちらも無ければ unavailable を返し、未確認の MiL を送らない |
src/storage-domain.mjs |
Web ホストの永続化 ctx.storageDomain(defineDomain 相当の spec をローカルに構築。TUI の tuiPluginStorage は Web に存在しない) |
src/config.mjs |
設定の既定値・検証・変換指示の組み立て |
src/mil.mjs |
@ 置換、MiL の検証、二ブロック抽出、定義逐語節の除去、引数解析 |
src/sarashina.mjs |
Chat Completions クライアント(429 再試行、レート間隔、鍵の redaction) |
src/message.mjs |
送信メッセージの生成(source.kind: 'user'、本文は「依頼+MiL」) |
src/log.mjs |
dsh storage 経由のログ(256 KiB 上限に合わせた 50 件のリング)。ハンドルは1アクティベーションにつき1回だけ解決し、使えない場合は失敗として報告する |
src/prompt.mjs |
返答言語の system prompt 段 |
src/settings.mjs |
設定セクションの記述子 |
src/spec.mjs |
mil-spec ファイルの読み込み |
src/examples.mjs |
実例の解析 |
src/report.mjs |
実測レポートの解析(ペイロード再利用) |
tools/preflight-decode.mjs |
事前実測(変換 → 復号テスト、--dry、--decode-only) |
tools/draft-examples.mjs |
実例の下書き生成(レビュー前提) |
tools/freeze-example.mjs |
下書きの凍結(現在は不使用。examples-v0.txt は手作業で整備) |
tools/check-cell-width.mjs |
表示セル幅の差分検証(自前の cellWidth を導入済み dsh-tui の stringWidth と比較。過小評価=ホストが切り詰める危険のみを失敗とする) |
測定
# 送信 payload の確認(API を呼ばない)
node tools/preflight-decode.mjs --dry
# 変換と復号テスト(対象モデルを差し替え可能。変換器は Sarashina 固定)
node --env-file=.env tools/preflight-decode.mjs --count 5 --instruction example `
--target-base https://api.commandcode.ai/provider/v1 `
--target-model inclusionai/ling-3.1-flash:free `
--target-key-env COMMANDCODE_API_KEY `
--out preflight-report.md
# 既存レポートのペイロードで復号だけを試す
node --env-file=.env tools/preflight-decode.mjs --decode-only preflight-report-run6-off.md `
--target-base https://api.commandcode.ai/provider/v1 `
--target-model inclusionai/ling-3.1-flash:free `
--target-key-env COMMANDCODE_API_KEY
検証状況
| 項目 | 状態 |
|---|---|
| 単体・統合テスト | 173 件通過(実プロセスで実行) |
| 変換(Sarashina → MiL) | 実測で確認。実例の形を原典の本文に合わせた時点で成立した(preflight-report-run6-off.md / run7-prepend.md) |
| 復号(spec なしで対象モデルが読めるか) | 実測で確認(commandcode の無料モデル)。ユーザーの本番モデルでは未検証 |
| dsh の接点 | コマンド登録・変換・承認ダイアログ・編集ダイアログ・編集の取り消し(Esc で中止)・送信(agents.followup。会話に MiL が自分の発言として出ることをユーザーが確認)は実機で動作。storage への記録内容は未確認 |
| 変換レポートの表示 | 通知欄のみ(200 セル以内に整形)。会話へ出すプラグイン API が dsh に無い。要望は dsh-feature-request.md |
| 対象モデルの選定 | 未確定(無料モデルで確認したのみ) |
ライセンスと帰属
- 本プラグインのコードは MIT ライセンス(
LICENSE)。 - MiL の記法は @AM09_21 による CC0 1.0 の公開物。原典の URL は本 README と
mil-spec/に残している。 mil-spec/examples-v0.txtは原典ではなく本プラグインが作成した教材である。
No comments yet. Be the first to write one.