kiokuko-dsh 0.1.29 → 0.1.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/PERMISSIONS.md +8 -4
  2. package/README.ja.md +12 -6
  3. package/README.ko.md +12 -6
  4. package/README.md +13 -7
  5. package/README.zh-CN.md +12 -6
  6. package/dist/client.cjs +27 -12
  7. package/dist/client.d.ts.map +1 -1
  8. package/dist/dsh/config.d.ts +22 -0
  9. package/dist/dsh/config.d.ts.map +1 -1
  10. package/dist/dsh/config.js +3 -1
  11. package/dist/dsh/config.js.map +1 -1
  12. package/dist/dsh/enno-delegation.d.ts +52 -0
  13. package/dist/dsh/enno-delegation.d.ts.map +1 -0
  14. package/dist/dsh/enno-delegation.js +194 -0
  15. package/dist/dsh/enno-delegation.js.map +1 -0
  16. package/dist/dsh/execution-selection.d.ts +145 -0
  17. package/dist/dsh/execution-selection.d.ts.map +1 -0
  18. package/dist/dsh/execution-selection.js +45 -0
  19. package/dist/dsh/execution-selection.js.map +1 -0
  20. package/dist/dsh/host-adapter.d.ts +3 -0
  21. package/dist/dsh/host-adapter.d.ts.map +1 -1
  22. package/dist/dsh/host-adapter.js +244 -14
  23. package/dist/dsh/host-adapter.js.map +1 -1
  24. package/dist/dsh/index.js +1 -1
  25. package/dist/dsh/index.js.map +1 -1
  26. package/dist/dsh/input-claim.d.ts +4 -0
  27. package/dist/dsh/input-claim.d.ts.map +1 -1
  28. package/dist/dsh/input-claim.js +11 -0
  29. package/dist/dsh/input-claim.js.map +1 -1
  30. package/dist/dsh/intake-gate.d.ts +2 -1
  31. package/dist/dsh/intake-gate.d.ts.map +1 -1
  32. package/dist/dsh/intake-gate.js +4 -1
  33. package/dist/dsh/intake-gate.js.map +1 -1
  34. package/dist/dsh/model-configuration.d.ts +189 -0
  35. package/dist/dsh/model-configuration.d.ts.map +1 -0
  36. package/dist/dsh/model-configuration.js +96 -0
  37. package/dist/dsh/model-configuration.js.map +1 -0
  38. package/dist/dsh/model-routing.d.ts +23 -0
  39. package/dist/dsh/model-routing.d.ts.map +1 -0
  40. package/dist/dsh/model-routing.js +61 -0
  41. package/dist/dsh/model-routing.js.map +1 -0
  42. package/dist/dsh/model-selection-ui.d.ts +21 -0
  43. package/dist/dsh/model-selection-ui.d.ts.map +1 -0
  44. package/dist/dsh/model-selection-ui.js +251 -0
  45. package/dist/dsh/model-selection-ui.js.map +1 -0
  46. package/dist/dsh/orca-command-surface.d.ts.map +1 -1
  47. package/dist/dsh/orca-command-surface.js +6 -5
  48. package/dist/dsh/orca-command-surface.js.map +1 -1
  49. package/dist/dsh/orca-hooks.d.ts.map +1 -1
  50. package/dist/dsh/orca-hooks.js +4 -1
  51. package/dist/dsh/orca-hooks.js.map +1 -1
  52. package/dist/dsh/orca-host.d.ts +5 -0
  53. package/dist/dsh/orca-host.d.ts.map +1 -1
  54. package/dist/dsh/orca-host.js +37 -5
  55. package/dist/dsh/orca-host.js.map +1 -1
  56. package/dist/dsh/orca-session-choice.d.ts +19 -0
  57. package/dist/dsh/orca-session-choice.d.ts.map +1 -0
  58. package/dist/dsh/orca-session-choice.js +128 -0
  59. package/dist/dsh/orca-session-choice.js.map +1 -0
  60. package/dist/dsh/orca-store.d.ts +3 -1
  61. package/dist/dsh/orca-store.d.ts.map +1 -1
  62. package/dist/dsh/orca-store.js +12 -0
  63. package/dist/dsh/orca-store.js.map +1 -1
  64. package/dist/dsh/orca-types.d.ts +6 -0
  65. package/dist/dsh/orca-types.d.ts.map +1 -1
  66. package/dist/dsh/orca-types.js.map +1 -1
  67. package/dist/dsh/standard-skills.d.ts +1 -1
  68. package/dist/dsh/standard-skills.d.ts.map +1 -1
  69. package/dist/dsh/standard-skills.js +1 -1
  70. package/dist/dsh/standard-skills.js.map +1 -1
  71. package/dist/dsh/task-intake.d.ts +2 -0
  72. package/dist/dsh/task-intake.d.ts.map +1 -1
  73. package/dist/dsh/task-intake.js +6 -1
  74. package/dist/dsh/task-intake.js.map +1 -1
  75. package/dist/dsh/tool-policy.d.ts +2 -2
  76. package/dist/dsh/tool-policy.d.ts.map +1 -1
  77. package/dist/dsh/tool-policy.js +4 -3
  78. package/dist/dsh/tool-policy.js.map +1 -1
  79. package/dist/dsh/tools.d.ts +2 -2
  80. package/dist/dsh/tools.d.ts.map +1 -1
  81. package/dist/dsh/tools.js +4 -1
  82. package/dist/dsh/tools.js.map +1 -1
  83. package/dist/dsh/user-interaction.d.ts.map +1 -1
  84. package/dist/dsh/user-interaction.js +24 -16
  85. package/dist/dsh/user-interaction.js.map +1 -1
  86. package/dist/enno-oduno/schemas.d.ts +14 -14
  87. package/dist/enno-oduno/service.d.ts.map +1 -1
  88. package/dist/enno-oduno/service.js +4 -0
  89. package/dist/enno-oduno/service.js.map +1 -1
  90. package/dist/enno-oduno/validation-errors.d.ts +1 -1
  91. package/dist/model-tools/contracts.d.ts +20 -3
  92. package/dist/model-tools/contracts.d.ts.map +1 -1
  93. package/dist/model-tools/contracts.js +6 -0
  94. package/dist/model-tools/contracts.js.map +1 -1
  95. package/docs/README.ja.md +2 -0
  96. package/docs/README.md +2 -0
  97. package/docs/architecture.md +1 -1
  98. package/docs/dsh-plugin.md +9 -5
  99. package/docs/enno-oduno.md +3 -1
  100. package/docs/model-selection.ja.md +101 -0
  101. package/docs/model-selection.md +68 -0
  102. package/docs/orca-recording.md +30 -7
  103. package/dsh/cordis.patch.yml +2 -2
  104. package/migrations/009_dsh_execution_selection.sql +21 -0
  105. package/migrations/010_dsh_orca_session_choices.sql +10 -0
  106. package/package.json +4 -4
  107. package/skills/kiokuko-enno-oduno/SKILL.md +6 -2
  108. package/skills/kiokuko-simple-work/SKILL.md +11 -10
  109. package/skills/kiokuko-single-purpose-functions/SKILL.md +1 -1
  110. package/skills/kiokuko-soul/SKILL.md +37 -4
  111. package/skills/kiokuko-ui-design-soul/SKILL.md +6 -2
  112. package/skills/memory-reasoning/SKILL.md +10 -7
package/PERMISSIONS.md CHANGED
@@ -57,19 +57,23 @@ conflicts are reported as failures or unavailable states. They are never
57
57
  converted into normal success or silently redirected to another repository or
58
58
  run.
59
59
 
60
- ## Optional Orca recordings
60
+ ## Orca recordings
61
61
 
62
- `orca.enabled` defaults to `false`. The runtime dependencies
62
+ `orca.enabled` defaults to `true`, including in the installed bundle configuration.
63
+ This enables the feature; a native question asks whether to record each session.
64
+ Only affirmative choices or `/kioku-orca start` authorize capture. Choices are
65
+ saved in SQLite; skip/cancel or unavailable UI continues without recording.
66
+ Set it to `false` and reload to disable the feature. The runtime dependencies
63
67
  `@orcareplay/core`, `@orcareplay/schema`, and `@orcareplay/viewer` with range `>=0.2.1`
64
68
  are installed automatically by npm/pnpm with this package. No extra installer,
65
69
  startup subprocess, automatic package repair, or network transmission is added.
66
70
  The dependencies are Apache-2.0; the [upstream license](docs/ORCAREPLAY-LICENSE.txt)
67
71
  and viewer credit are retained. Disabled recording never initializes Orca or creates trace files.
68
72
 
69
- With explicit configuration, projected model content and tool final results are
73
+ After an affirmative session choice or start command, projected model content and tool final results are
70
74
  written to `<verified workspace>/.orca/runs`, or under
71
75
  `<Kiokuko data directory>/traces/projects/<workspace hash>/.orca/runs`.
72
- The main database holds only the session/run index. `show` and `export` require
76
+ For Orca, the main database holds the session/run index and recording choices, not log bodies. `show` and `export` require
73
77
  the exact native command agent/session; no Orca HTTP API or model tool exists.
74
78
  Offline HTML is written only to `.orca/exports/<run ID>.html`.
75
79
 
package/README.ja.md CHANGED
@@ -3,11 +3,13 @@
3
3
  [English](README.md) | 日本語 | [简体中文](README.zh-CN.md) | [한국어](README.ko.md)
4
4
 
5
5
  [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) に、プロジェクトの記憶・作業計画・検証支援を追加するプラグインです。
6
- 任意の OrcaReplay 記録を有効にすると、モデル・ツールの動作確認と HTML 出力もできます。
6
+ OrcaReplay でモデル・ツールの動作を記録し、内容の確認と HTML 出力もできます。
7
7
 
8
+
9
+ 新しい変更作業では、通常実行か役小角(enno-oduno)を選べます。役小角ではおすすめテンプレート、またはDSH設定済みモデルから役割ごとの構成を選択します。[モデル選択と接続上の制約](docs/model-selection.ja.md)
8
10
  ## 導入と使い方
9
11
 
10
- 対応 DSH: `0.1.2-rc.1` / [0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1)。
12
+ 対応 DSH: `0.1.2-rc.1` / [0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1) / [v0.1.3-alpha.2](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.2)
11
13
  Node.js **24.16.0 以上**と pnpm が必要です。
12
14
  インストール済みの `dsh` CLI で、公開済み npm パッケージを導入して起動します。
13
15
 
@@ -20,10 +22,14 @@ DSH の checkout から使う場合は、各 `dsh` コマンドの先頭に `pnp
20
22
  起動後は普通に依頼を入力します。Kiokuko 専用の setup 操作は不要です。
21
23
  GitHub・ローカルからの導入は [プラグインガイド](docs/dsh-plugin.md) を参照してください。
22
24
 
23
- Orca の依存パッケージは自動導入され、記録は **初期状態では無効**です。
24
- プラグイン設定の `orca.enabled` を `true` にして再読み込みすると記録を開始できます。
25
- `/kioku-orca list`、`/kioku-orca show <run ID>`、`/kioku-orca export <run ID>` で確認・出力できます。
26
- 詳細は [記録設定とコマンド](docs/orca-recording.md) を参照してください。
25
+ OrcaReplay の機能設定は自動導入され、**手動設定は不要**です。チャットの最初に詳細ログを「記録する/記録しない」を選びます。
26
+ 「記録する」を選ぶと、その後のモデル応答やツール実行結果を作業プロジェクトの `.orca/runs/` に保存します。選択はセッションごとに保持され、スキップ・取消時は記録せず続行します。
27
+
28
+ - `/kioku-orca start`: 手動で記録を開始、または停止後に再開します。最初に「記録する」を選んだ場合は実行不要です。過去の動作は記録されません。
29
+ - `/kioku-orca status`: 機能の有効・無効、セッションの記録選択、記録状態・エラーを確認します。
30
+
31
+ `/kioku-orca stop` でログを確定後、`list` で run ID を確認し、`show <run ID>` で内容を表示、`export <run ID>` で HTML を出力できます(いずれも `/kioku-orca` に続けて入力)。
32
+ 無効にする場合は `orca.enabled: false` を設定して再読み込みします。詳細は [記録設定とコマンド](docs/orca-recording.md) を参照してください。
27
33
 
28
34
  ## 更新
29
35
 
package/README.ko.md CHANGED
@@ -3,11 +3,13 @@
3
3
  [English](README.md) | [日本語](README.ja.md) | [简体中文](README.zh-CN.md) | 한국어
4
4
 
5
5
  [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)에 프로젝트 기억, 작업 계획, 검증 지원을 추가합니다.
6
- 선택 기능인 OrcaReplay 기록을 켜면 모델과 도구의 동작을 확인하고 HTML로 내보낼 수 있습니다.
6
+ OrcaReplay 모델과 도구의 동작을 기록하고, 기록을 확인하거나 HTML로 내보낼 수 있습니다.
7
7
 
8
+
9
+ 새 변경 작업에서는 일반 실행 또는 役小角(enno-oduno)를 선택할 수 있습니다. 역할별 모델은 추천 템플릿이나 DSH에 설정된 모델에서 선택합니다. [모델 선택과 연결 제한](docs/model-selection.md).
8
10
  ## 설치 및 사용
9
11
 
10
- DSH `0.1.2-rc.1`과 [0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1) 지원합니다.
12
+ DSH `0.1.2-rc.1`, [0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1), [v0.1.3-alpha.2](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.2)를 지원합니다.
11
13
  Node.js **24.16.0 이상**과 pnpm이 필요합니다.
12
14
  설치된 `dsh` CLI로 공개된 npm 패키지를 설치하고 시작합니다.
13
15
 
@@ -20,10 +22,14 @@ DSH 소스 디렉터리에서 실행한다면 각 `dsh` 명령 앞에 `pnpm`을
20
22
  시작 후 평소처럼 작업을 입력하면 됩니다. Kiokuko 전용 setup 작업은 필요하지 않습니다.
21
23
  GitHub 및 로컬 설치 방법은 [플러그인 안내](docs/dsh-plugin.md)를 참고하세요.
22
24
 
23
- Orca 의존 패키지는 자동 설치되며 기록은 **기본적으로 꺼져 있습니다**.
24
- 플러그인 설정의 `orca.enabled`를 `true`로 바꾸고 다시 로드하면 활성화됩니다.
25
- `/kioku-orca list`, `/kioku-orca show <run ID>`, `/kioku-orca export <run ID>`로 기록을 확인하고 내보낼 수 있습니다.
26
- 자세한 내용은 [기록 설정과 명령](docs/orca-recording.md)을 참고하세요.
25
+ OrcaReplay 기능은 자동으로 설정되며 **수동 설정이 필요 없습니다**. 채팅 시작 시 상세 로그를 기록할지 선택합니다.
26
+ 기록을 선택하면 이후 모델 응답과 도구 실행 결과가 세션 작업 공간의 `.orca/runs/`에 저장됩니다. 선택은 세션별로 유지되며, 건너뛰거나 취소하면 기록 없이 채팅을 계속합니다.
27
+
28
+ - `/kioku-orca start`: 기록을 수동으로 시작하거나 중지 후 다시 시작합니다. 시작 시 기록을 선택했다면 실행할 필요가 없습니다. 과거 동작은 기록되지 않습니다.
29
+ - `/kioku-orca status`: 기능 활성화 여부, 세션의 기록 선택, 기록 상태와 오류를 확인합니다.
30
+
31
+ `/kioku-orca stop`으로 로그를 확정한 뒤 `list`로 run ID를 확인하고, `show <run ID>`로 내용을 보거나 `export <run ID>`로 HTML을 내보낼 수 있습니다(모두 `/kioku-orca` 뒤에 입력).
32
+ 기록을 끄려면 `orca.enabled: false`를 설정하고 다시 로드하세요. 자세한 내용은 [기록 설정과 명령](docs/orca-recording.md)을 참고하세요.
27
33
 
28
34
  ## 업데이트
29
35
 
package/README.md CHANGED
@@ -1,14 +1,16 @@
1
- # Kiokuko(記憶庫) DeepSeek Harness Plugin
2
1
 
2
+ # Kiokuko(記憶庫) DeepSeek Harness Plugin
3
3
  [日本語](README.ja.md) | [简体中文](README.zh-CN.md) | [한국어](README.ko.md)
4
4
 
5
5
  Kiokuko adds project memory, planning, and verification support to
6
6
  [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness).
7
- Optional OrcaReplay recording lets you inspect model/tool activity and export HTML.
7
+ OrcaReplay records model/tool activity for inspection and HTML export.
8
+
8
9
 
10
+ For new coding tasks, choose normal execution or 役小角(enno-oduno). Enno offers model templates and role assignments from configured DSH models. [Model selection and connection limits](docs/model-selection.md).
9
11
  ## Install and use
10
12
 
11
- Supports DSH `0.1.2-rc.1` and [0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1).
13
+ Supports DSH `0.1.2-rc.1`, [0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1), and [v0.1.3-alpha.2](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.2).
12
14
  Requires Node.js **24.16.0+** and pnpm.
13
15
  With an installed `dsh` CLI, install the published npm package and start:
14
16
 
@@ -21,10 +23,14 @@ From a DSH checkout, prefix each `dsh` command with `pnpm`.
21
23
  Enter your task normally; no Kiokuko setup command is needed.
22
24
  For GitHub/local installation, see the [plugin guide](docs/dsh-plugin.md).
23
25
 
24
- Orca dependencies install automatically; recording is **off by default**.
25
- Set `orca.enabled: true` in the plugin configuration and reload to enable it.
26
- Use `/kioku-orca list`, `/kioku-orca show <run ID>`, or `/kioku-orca export <run ID>`.
27
- See [recording settings and commands](docs/orca-recording.md).
26
+ OrcaReplay is configured automatically; **no manual setup is required**. At the start of a chat, choose whether to record detailed logs.
27
+ Choosing to record saves subsequent model responses and tool results to `.orca/runs/` in the session workspace. The choice is remembered per session; skipped or cancelled questions continue without recording.
28
+
29
+ - `/kioku-orca start`: start recording manually or resume after stopping. Not needed if you chose to record at the start; past activity is not captured.
30
+ - `/kioku-orca status`: check feature availability, the session recording choice, recording state, and errors.
31
+
32
+ Use `/kioku-orca stop` to finalize the log, `list` to find its run ID, `show <run ID>` to inspect it, and `export <run ID>` to create HTML (all under `/kioku-orca`).
33
+ To disable recording, set `orca.enabled: false` and reload. See [recording settings and commands](docs/orca-recording.md).
28
34
 
29
35
  ## Update
30
36
 
package/README.zh-CN.md CHANGED
@@ -3,11 +3,13 @@
3
3
  [English](README.md) | [日本語](README.ja.md) | 简体中文 | [한국어](README.ko.md)
4
4
 
5
5
  为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 添加项目记忆、任务规划和验证支持。
6
- 可选的 OrcaReplay 记录功能可用于查看模型和工具活动,并导出 HTML。
6
+ OrcaReplay 可记录模型和工具活动,查看记录并导出 HTML。
7
7
 
8
+
9
+ 新的修改任务可以选择普通执行或役小角(enno-oduno)。役小角支持推荐模板,也可从DSH已配置的模型中为各角色选择模型。[模型选择与连接限制](docs/model-selection.md)。
8
10
  ## 安装与使用
9
11
 
10
- 支持 DSH `0.1.2-rc.1` 和 [0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1)。
12
+ 支持 DSH `0.1.2-rc.1`、[0.1.3-alpha.1](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.1) 和 [v0.1.3-alpha.2](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.3-alpha.2)
11
13
  需要 Node.js **24.16.0 以上**和 pnpm。
12
14
  使用已安装的 `dsh` CLI 安装已发布的 npm 包并启动:
13
15
 
@@ -20,10 +22,14 @@ dsh web
20
22
  启动后直接输入任务,无需额外的 Kiokuko setup 操作。
21
23
  GitHub 和本地安装方式见[插件指南](docs/dsh-plugin.md)。
22
24
 
23
- Orca 依赖会自动安装,记录功能**默认关闭**。
24
- 将插件配置中的 `orca.enabled` 设为 `true` 并重新加载即可启用。
25
- 使用 `/kioku-orca list`、`/kioku-orca show <run ID>` 和 `/kioku-orca export <run ID>` 查看或导出记录。
26
- 详见[记录设置与命令](docs/orca-recording.md)。
25
+ OrcaReplay 的功能配置会自动安装,**无需手动设置**。聊天开始时,可选择是否记录详细日志。
26
+ 选择记录后,后续模型回复和工具执行结果将保存到会话工作目录的 `.orca/runs/`。选择按会话保存;跳过或取消时,不记录并继续聊天。
27
+
28
+ - `/kioku-orca start`:手动开始记录,或在停止后重新开始。如果开始时已选择记录,则无需执行。不会补录过去的活动。
29
+ - `/kioku-orca status`:查看功能是否启用、会话的记录选择、记录状态和错误。
30
+
31
+ 用 `/kioku-orca stop` 完成日志记录后,用 `list` 查看 run ID、`show <run ID>` 查看内容、`export <run ID>` 导出 HTML(均在 `/kioku-orca` 后输入)。
32
+ 要禁用记录,请设置 `orca.enabled: false` 并重新加载。详见[记录设置与命令](docs/orca-recording.md)。
27
33
 
28
34
  ## 更新
29
35
 
package/dist/client.cjs CHANGED
@@ -257,15 +257,15 @@ window.__ModuleLoader__.load({
257
257
  setDraft(value);
258
258
  setError('');
259
259
  };
260
- const settle = (cancel = false, skip = false) => {
260
+ const settle = (cancel = false) => {
261
261
  if (inFlight.current)
262
262
  return;
263
263
  const custom = draft.custom.trim();
264
- if (!cancel && !skip && draft.selected === null && custom === '') {
264
+ if (!cancel && draft.selected === null && custom === '') {
265
265
  setError('選択肢を選ぶか、自由入力してください。');
266
266
  return;
267
267
  }
268
- if (!cancel && !skip && /^[0-90-9]+$/u.test(custom)) {
268
+ if (!cancel && /^[0-90-9]+$/u.test(custom)) {
269
269
  const ordinal = Number(custom.normalize('NFKC'));
270
270
  if (ordinal < 1 || ordinal > question.options.length) {
271
271
  setError(`番号は1〜${question.options.length}で入力してください。`);
@@ -278,8 +278,8 @@ window.__ModuleLoader__.load({
278
278
  // Enter is a separate confirmation. Typing, key-repeat and IME cannot submit twice.
279
279
  void Promise.resolve().then(() => cancel ? pending.cancel() : pending.answer({ answers: [{
280
280
  id: question.id,
281
- selected: skip || draft.selected === null ? [] : [question.options[draft.selected].label],
282
- ...(!skip && custom ? { custom } : {}),
281
+ selected: draft.selected === null ? [] : [question.options[draft.selected].label],
282
+ ...(custom ? { custom } : {}),
283
283
  }] })).then(() => { intakeDrafts.delete(pending); }).catch(cause => {
284
284
  if (!mounted.current)
285
285
  return;
@@ -316,8 +316,8 @@ window.__ModuleLoader__.load({
316
316
  jsxs('header', { children: [jsx('h2', { id: titleId, children: question.question }),
317
317
  jsx('button', { type: 'button', disabled: busy, onClick: () => settle(true), 'aria-label': '質問を閉じる', children: '閉じる' })] }),
318
318
  jsxs('div', { className: 'kiokuko-intake-body', children: [
319
- jsx('p', { children: question.detail }),
320
- jsx('p', { children: `1〜${question.options.length}キーで選択、Enterで確定。自由入力中の数字は文字として入力されます。` }),
319
+ question.detail ? jsx('p', { children: question.detail }) : null,
320
+ jsx('p', { children: `1〜${question.options.length}キーで選択、Enterで確定。` }),
321
321
  jsx('div', { 'aria-label': '作業の選択肢', children: question.options.map((option, index) => jsxs('button', {
322
322
  key: option.label, type: 'button', className: 'kiokuko-intake-option', disabled: busy,
323
323
  ref: (element) => { optionElements.current[index] = element; },
@@ -330,16 +330,15 @@ window.__ModuleLoader__.load({
330
330
  event.stopPropagation();
331
331
  settle();
332
332
  },
333
- children: [jsx('strong', { children: `${index + 1}. ${option.label}` }), jsx('span', { children: option.description })],
333
+ children: [jsx('strong', { children: `${index + 1}. ${option.label}` }), option.description ? jsx('span', { children: option.description }) : null],
334
334
  })) }),
335
- jsx('label', { htmlFor: `${titleId}-custom`, children: '自由入力(番号でも回答できます)' }),
336
- jsx('textarea', { id: `${titleId}-custom`, rows: 2, disabled: busy, value: draft.custom,
335
+ jsx('label', { htmlFor: `${titleId}-custom`, children: '自由入力(任意)' }),
336
+ jsx('textarea', { id: `${titleId}-custom`, rows: 1, disabled: busy, value: draft.custom,
337
337
  onChange: (event) => update({ selected: null, custom: event.target.value }),
338
338
  }),
339
339
  ] }),
340
340
  jsxs('footer', { children: [
341
341
  jsx('span', { role: 'status', 'aria-live': 'polite', children: error || (busy ? '送信中…' : draft.selected === null ? '' : `${draft.selected + 1}. ${question.options[draft.selected].label}を選択中`) }),
342
- jsx('button', { type: 'button', disabled: busy, onClick: () => settle(false, true), children: '作業を始めず会話する' }),
343
342
  jsx('button', { type: 'button', disabled: busy || (draft.selected === null && !draft.custom.trim()), onClick: () => settle(), children: '確定(Enter)' }),
344
343
  ] }),
345
344
  ],
@@ -349,7 +348,23 @@ window.__ModuleLoader__.load({
349
348
  if (typeof document === 'undefined')
350
349
  return undefined;
351
350
  const style = document.createElement('style');
352
- style.textContent = '.kiokuko-intake{border:1px solid var(--dsw-alias-border-l4,#bbb);border-radius:16px;padding:16px;background:var(--dsw-alias-background-primary,Canvas);color:var(--dsw-alias-label-primary,CanvasText);display:flex;flex-direction:column;max-height:70dvh;gap:12px}.kiokuko-intake header,.kiokuko-intake footer{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.kiokuko-intake h2{font-size:18px;margin:0;flex:1}.kiokuko-intake-body{overflow:auto;min-height:0}.kiokuko-intake p{white-space:pre-wrap;line-height:1.5}.kiokuko-intake button{font:inherit;color:inherit;background:transparent;border:1px solid var(--dsw-alias-border-l4,#bbb);border-radius:8px;padding:10px;min-height:44px;cursor:pointer}.kiokuko-intake button:disabled{cursor:default;opacity:.6}.kiokuko-intake-option{display:flex;width:100%;text-align:left;flex-direction:column;gap:4px;margin-bottom:8px;overflow-wrap:anywhere}.kiokuko-intake-option[aria-pressed=true]{border:2px solid var(--dsw-alias-label-primary,CanvasText);background:var(--dsw-alias-interactive-bg-hover,#eee)}.kiokuko-intake-option span{font-size:13px;line-height:1.5}.kiokuko-intake textarea{box-sizing:border-box;width:100%;font:inherit;color:inherit;background:transparent;border:1px solid var(--dsw-alias-border-l4,#bbb);padding:8px;border-radius:8px}.kiokuko-intake :focus-visible,.kiokuko-intake:focus-visible{outline:2px solid Highlight;outline-offset:3px}.kiokuko-intake footer [role=status]{flex:1;min-width:120px}';
351
+ style.textContent = `
352
+ .kiokuko-intake{box-sizing:border-box;width:100%;max-width:680px;align-self:center;margin-inline:auto;border:1px solid var(--dsw-alias-border-l4,#bbb);border-radius:12px;padding:12px;background:var(--dsw-alias-background-primary,Canvas);color:var(--dsw-alias-label-primary,CanvasText);display:flex;flex-direction:column;min-height:0;max-height:min(480px,70dvh);gap:8px;font-size:14px}
353
+ .kiokuko-intake header,.kiokuko-intake footer{display:flex;gap:8px;align-items:center;flex-wrap:wrap;flex-shrink:0}
354
+ .kiokuko-intake h2{font-size:16px;line-height:1.4;margin:0;flex:1}
355
+ .kiokuko-intake-body{overflow:auto;min-height:0;display:flex;flex-direction:column;gap:8px}
356
+ .kiokuko-intake p{margin:0;white-space:pre-wrap;line-height:1.4;font-size:12px}
357
+ .kiokuko-intake button{font:inherit;color:inherit;background:transparent;border:1px solid var(--dsw-alias-border-l4,#bbb);border-radius:8px;padding:8px 10px;min-height:40px;cursor:pointer}
358
+ .kiokuko-intake button:disabled{cursor:default;opacity:.6}
359
+ .kiokuko-intake-option{display:flex;width:100%;text-align:left;flex-direction:column;gap:4px;margin-bottom:6px;overflow-wrap:anywhere}
360
+ .kiokuko-intake-option:last-child{margin-bottom:0}
361
+ .kiokuko-intake-option[aria-pressed=true]{border-color:var(--dsw-alias-label-primary,CanvasText);box-shadow:inset 0 0 0 1px currentColor;background:var(--dsw-alias-interactive-bg-hover,#eee)}
362
+ .kiokuko-intake-option span{font-size:12px;line-height:1.4}
363
+ .kiokuko-intake label{font-size:12px}
364
+ .kiokuko-intake textarea{box-sizing:border-box;width:100%;min-height:36px;max-height:96px;resize:vertical;font:inherit;line-height:1.4;color:inherit;background:transparent;border:1px solid var(--dsw-alias-border-l4,#bbb);padding:8px;border-radius:8px}
365
+ .kiokuko-intake :focus-visible,.kiokuko-intake:focus-visible{outline:2px solid Highlight;outline-offset:2px}
366
+ .kiokuko-intake footer [role=status]{flex:1;min-width:0;font-size:12px;overflow-wrap:anywhere}
367
+ `;
353
368
  document.head.appendChild(style);
354
369
  return () => style.remove();
355
370
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAKA,UAAU,wBAAwB;IAChC,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;QAAE,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAA;KAAE,CAAC,CAAA;IAC7G,QAAQ,EAAE;QAAE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACxC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;CAC3C;AAYD,UAAU,gBAAgB;IACxB,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE;YAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAAA;SAAE,CAAA;KAAE,CAAA;IACxF,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,CAAA;KAC3F,CAAA;IACD,QAAQ,CAAC,KAAK,EAAE;QACd,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,GAAG,OAAO,CAAA;QACtD,QAAQ,CACN,UAAU,EAAE;YACV,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;YACrB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;YACpB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;YACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;YAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAA;YAC7D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;YACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAChD,EACD,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,GACrD,OAAO,CAAA;KACX,CAAA;IACD,MAAM,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;IAChF,EAAE,CAAC,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAA;CACtI;AA0ED,+EAA+E;AAC/E,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,UAAU,GAAG,WAAW,CAAC,CAqBjH;AAuHD,eAAO,MAAM,MAAM,gDAAiD,CAAA;AAqKpE,mEAAmE;AACnE,wBAAgB,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CA0BjD"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAKA,UAAU,wBAAwB;IAChC,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;QAAE,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAA;KAAE,CAAC,CAAA;IAC7G,QAAQ,EAAE;QAAE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACxC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;CAC3C;AAYD,UAAU,gBAAgB;IACxB,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE;YAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAAA;SAAE,CAAA;KAAE,CAAA;IACxF,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,CAAA;KAC3F,CAAA;IACD,QAAQ,CAAC,KAAK,EAAE;QACd,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,GAAG,OAAO,CAAA;QACtD,QAAQ,CACN,UAAU,EAAE;YACV,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;YACrB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;YACpB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;YACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;YAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAA;YAC7D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;YACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAChD,EACD,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,GACrD,OAAO,CAAA;KACX,CAAA;IACD,MAAM,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;IAChF,EAAE,CAAC,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAA;CACtI;AA0ED,+EAA+E;AAC/E,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,UAAU,GAAG,WAAW,CAAC,CAqBjH;AAuHD,eAAO,MAAM,MAAM,gDAAiD,CAAA;AAoLpE,mEAAmE;AACnE,wBAAgB,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CA0BjD"}
@@ -29,6 +29,28 @@ export type OrcaConfig = z.infer<typeof OrcaConfig>;
29
29
  /** Runtime configuration accepted by the dsh bundle entrypoint. */
30
30
  export declare const Config: z.ZodObject<{
31
31
  enabled: z.ZodDefault<z.ZodBoolean>;
32
+ modelRoutes: z.ZodDefault<z.ZodArray<z.ZodObject<{
33
+ provider: z.ZodString;
34
+ family: z.ZodEnum<{
35
+ openai: "openai";
36
+ "opencode-go": "opencode-go";
37
+ "opencode-zen": "opencode-zen";
38
+ openrouter: "openrouter";
39
+ ollama: "ollama";
40
+ other: "other";
41
+ }>;
42
+ connection: z.ZodDefault<z.ZodEnum<{
43
+ api: "api";
44
+ codex: "codex";
45
+ local: "local";
46
+ }>>;
47
+ protocol: z.ZodDefault<z.ZodEnum<{
48
+ responses: "responses";
49
+ "chat-completions": "chat-completions";
50
+ messages: "messages";
51
+ unknown: "unknown";
52
+ }>>;
53
+ }, z.core.$strict>>>;
32
54
  orca: z.ZodPrefault<z.ZodObject<{
33
55
  enabled: z.ZodDefault<z.ZodBoolean>;
34
56
  storage: z.ZodDefault<z.ZodEnum<{
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/dsh/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;iBAmBrB,CAAA;AACF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAA;AACnD,mEAAmE;AACnE,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGjB,CAAA;AACF,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAA"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/dsh/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;iBAmBrB,CAAA;AACF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAA;AACnD,mEAAmE;AACnE,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIjB,CAAA;AACF,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAA"}
@@ -1,7 +1,8 @@
1
1
  import { z } from 'zod';
2
+ import { ModelRouteSchema } from './model-configuration.js';
2
3
  const limit = (value) => z.number().int().positive().max(Number.MAX_SAFE_INTEGER).default(value);
3
4
  export const OrcaConfig = z.object({
4
- enabled: z.boolean().default(false),
5
+ enabled: z.boolean().default(true),
5
6
  storage: z.enum(['project', 'data-dir']).default('project'),
6
7
  includeAuxiliary: z.boolean().default(false),
7
8
  capture: z.object({
@@ -23,6 +24,7 @@ export const OrcaConfig = z.object({
23
24
  /** Runtime configuration accepted by the dsh bundle entrypoint. */
24
25
  export const Config = z.object({
25
26
  enabled: z.boolean().default(true),
27
+ modelRoutes: z.array(ModelRouteSchema).max(128).default([]).refine(routes => new Set(routes.map(r => r.provider)).size === routes.length, 'Each DSH provider must have one route declaration'),
26
28
  orca: OrcaConfig.prefault({}),
27
29
  });
28
30
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/dsh/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AACxG,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACnC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IAC3D,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAC5C,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;QAC7D,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;KACtC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;IACf,sBAAsB,EAAE,KAAK,CAAC,SAAS,CAAC;IACxC,mBAAmB,EAAE,KAAK,CAAC,UAAU,CAAC;IACtC,aAAa,EAAE,KAAK,CAAC,WAAW,CAAC;IACjC,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC;IACxB,wBAAwB,EAAE,KAAK,CAAC,GAAG,CAAC;IACpC,2BAA2B,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7C,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACtF,uBAAuB,EAAE,KAAK,CAAC,SAAS,CAAC;IACzC,mBAAmB,EAAE,KAAK,CAAC,MAAM,CAAC;IAClC,0BAA0B,EAAE,KAAK,CAAC,MAAM,CAAC;IACzC,wBAAwB,EAAE,KAAK,CAAC,UAAU,CAAC;CAC5C,CAAC,CAAA;AAEF,mEAAmE;AACnE,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;CAC9B,CAAC,CAAA"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/dsh/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAE3D,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AACxG,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IAC3D,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAC5C,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;QAC7D,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;KACtC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;IACf,sBAAsB,EAAE,KAAK,CAAC,SAAS,CAAC;IACxC,mBAAmB,EAAE,KAAK,CAAC,UAAU,CAAC;IACtC,aAAa,EAAE,KAAK,CAAC,WAAW,CAAC;IACjC,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC;IACxB,wBAAwB,EAAE,KAAK,CAAC,GAAG,CAAC;IACpC,2BAA2B,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7C,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACtF,uBAAuB,EAAE,KAAK,CAAC,SAAS,CAAC;IACzC,mBAAmB,EAAE,KAAK,CAAC,MAAM,CAAC;IAClC,0BAA0B,EAAE,KAAK,CAAC,MAAM,CAAC;IACzC,wBAAwB,EAAE,KAAK,CAAC,UAAU,CAAC;CAC5C,CAAC,CAAA;AAEF,mEAAmE;AACnE,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,EAAE,mDAAmD,CAAC;IAC9L,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;CAC9B,CAAC,CAAA"}
@@ -0,0 +1,52 @@
1
+ import { type ModelBinding } from './model-configuration.js';
2
+ import type { RoutableAgent } from './model-routing.js';
3
+ import type { DshRuntime } from './runtime.js';
4
+ import type { DshToolHostBinding } from './tools.js';
5
+ export interface DshSpawnBackend {
6
+ start(name: 'spawn', request: {
7
+ parent: RoutableAgent;
8
+ prompt: {
9
+ type: 'text';
10
+ text: string;
11
+ }[];
12
+ signal: AbortSignal;
13
+ agentOptions: ModelBinding;
14
+ maxDepth: number;
15
+ toolFilter: {
16
+ allow: readonly string[];
17
+ };
18
+ label: string;
19
+ }): Promise<{
20
+ readonly id: string;
21
+ readonly localAgent?: RoutableAgent;
22
+ result: Promise<{
23
+ output: unknown;
24
+ stopReason: string;
25
+ }>;
26
+ dispose(): Promise<void>;
27
+ }>;
28
+ }
29
+ /** Child shells/custom execution tools cannot enforce a WorkUnit file boundary.
30
+ * The Goki head owns commands and final focused verification in this version. */
31
+ export declare function childFileScopeDenial(root: string, scope: readonly string[], name: string, args: unknown): string | undefined;
32
+ export declare class DshEnnoDelegation {
33
+ #private;
34
+ private readonly runtime;
35
+ private readonly backend;
36
+ constructor(runtime: Pick<DshRuntime, 'withDatabase'>, backend: DshSpawnBackend | undefined);
37
+ /** Called synchronously at agent/created, before session-start and followup. */
38
+ created(agent: RoutableAgent): void;
39
+ model(agent: object): ModelBinding | undefined;
40
+ isChild(agent: object): boolean;
41
+ parent(agent: object): RoutableAgent | undefined;
42
+ allows(agent: object, tool: string): boolean;
43
+ toolDenial(agent: object, name: string, args: unknown): string | undefined;
44
+ /** Durable ownership is checked again before every child request and tool,
45
+ * including after reload. Completing or replacing a lease revokes the child. */
46
+ assertCurrent(agent: object): Promise<void>;
47
+ /** Persist the created binding before the child's first request; restore only
48
+ * by its exact durable child id, never by origin/parent metadata alone. */
49
+ restoreOrPersist(agent: RoutableAgent): Promise<ModelBinding | undefined>;
50
+ execute(parent: RoutableAgent, args: unknown, binding: DshToolHostBinding, toolNames: readonly string[], signal: AbortSignal): Promise<unknown>;
51
+ }
52
+ //# sourceMappingURL=enno-delegation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enno-delegation.d.ts","sourceRoot":"","sources":["../../src/dsh/enno-delegation.ts"],"names":[],"mappings":"AAOA,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAChF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAKpD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE;QAC5B,MAAM,EAAE,aAAa,CAAC;QAAC,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAAC,MAAM,EAAE,WAAW,CAAC;QACrF,YAAY,EAAE,YAAY,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE;YAAE,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;SAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;KACvG,GAAG,OAAO,CAAC;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,aAAa,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;YAAE,MAAM,EAAE,OAAO,CAAC;YAAC,UAAU,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC,CAAA;CAC9J;AAGD;iFACiF;AACjF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAmB5H;AAMD,qBAAa,iBAAiB;;IAGhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAAoC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAnE,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,EAAmB,OAAO,EAAE,eAAe,GAAG,SAAS;IAC7H,gFAAgF;IAChF,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAMnC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAC9C,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAC/B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAChD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAC5C,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS;IAM1E;oFACgF;IAC1E,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAajD;+EAC2E;IACrE,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;IAezE,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;CAuDtJ"}
@@ -0,0 +1,194 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import { realpathSync } from 'node:fs';
3
+ import path from 'node:path';
4
+ import { z } from 'zod';
5
+ import { canonicalContentHash } from '../serialization/validate.js';
6
+ import { KiokukoError } from '../errors.js';
7
+ import { findSecretInValue } from '../memory/secrets.js';
8
+ import { ModelBindingSchema } from './model-configuration.js';
9
+ import { assertExecutionLeaseInTransaction, readEnnoSnapshot } from '../enno-oduno/store.js';
10
+ import { readExecutionSelection } from './execution-selection.js';
11
+ import { withImmediateTransaction } from '../db/transaction.js';
12
+ const CHILD_FILE_TOOLS = new Set(['read', 'write', 'edit', 'multiedit', 'str_replace_editor', 'glob', 'grep', 'skill']);
13
+ /** Child shells/custom execution tools cannot enforce a WorkUnit file boundary.
14
+ * The Goki head owns commands and final focused verification in this version. */
15
+ export function childFileScopeDenial(root, scope, name, args) {
16
+ if (!CHILD_FILE_TOOLS.has(name))
17
+ return 'Goki children use scoped file tools; the head runs commands and verifiers';
18
+ if (!args || typeof args !== 'object' || Array.isArray(args))
19
+ return 'Invalid child tool arguments';
20
+ const fields = args;
21
+ const supplied = fields.file_path ?? fields.filePath ?? fields.path;
22
+ if (name === 'skill')
23
+ return undefined;
24
+ if (typeof supplied !== 'string')
25
+ return ['glob', 'grep'].includes(name) ? undefined : 'A child file operation requires an explicit repository path';
26
+ const absolute = path.resolve(root, supplied);
27
+ let ancestor = absolute;
28
+ let canonicalTarget = absolute;
29
+ while (true) {
30
+ try {
31
+ const canonical = realpathSync(ancestor);
32
+ const relative = path.relative(root, canonical);
33
+ if (relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))
34
+ return 'Child path leaves the canonical repository';
35
+ canonicalTarget = path.resolve(canonical, path.relative(ancestor, absolute));
36
+ break;
37
+ }
38
+ catch (error) {
39
+ if (error.code !== 'ENOENT')
40
+ return 'Cannot verify the child path';
41
+ const parent = path.dirname(ancestor);
42
+ if (parent === ancestor)
43
+ return 'Cannot verify the child path';
44
+ ancestor = parent;
45
+ }
46
+ }
47
+ const relative = path.relative(root, absolute);
48
+ if (relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))
49
+ return 'Child path leaves the canonical repository';
50
+ const mutating = ['write', 'edit', 'multiedit'].includes(name) || name === 'str_replace_editor' && fields.command !== 'view';
51
+ if (mutating && ![relative, path.relative(root, canonicalTarget)].every(target => scope.some(entry => entry === '.' || target === entry || target.startsWith(`${entry}${path.sep}`) || path.matchesGlob(target, entry))))
52
+ return 'Child mutation is outside the approved WorkUnit scope';
53
+ return undefined;
54
+ }
55
+ const instructionSchema = z.object({ instruction: z.string().trim().min(1).max(16_384) }).strict();
56
+ const authoritySchema = z.object({
57
+ runId: z.string(), workspace: z.string(), orchestrationId: z.string(),
58
+ revision: z.number().int(), routeEpoch: z.number().int(), leaseToken: z.string(), workUnitId: z.string(),
59
+ }).strict();
60
+ export class DshEnnoDelegation {
61
+ runtime;
62
+ backend;
63
+ #pending = new AsyncLocalStorage();
64
+ #children = new WeakMap();
65
+ constructor(runtime, backend) {
66
+ this.runtime = runtime;
67
+ this.backend = backend;
68
+ }
69
+ /** Called synchronously at agent/created, before session-start and followup. */
70
+ created(agent) {
71
+ const binding = this.#pending.getStore();
72
+ if (!binding || binding.child)
73
+ return;
74
+ binding.child = agent;
75
+ this.#children.set(agent, binding);
76
+ }
77
+ model(agent) { return this.#children.get(agent)?.model; }
78
+ isChild(agent) { return this.#children.has(agent); }
79
+ parent(agent) { return this.#children.get(agent)?.parent; }
80
+ allows(agent, tool) { return this.#children.get(agent)?.toolNames.includes(tool) ?? true; }
81
+ toolDenial(agent, name, args) {
82
+ const binding = this.#children.get(agent);
83
+ if (!binding)
84
+ return undefined;
85
+ if (!binding.toolNames.includes(name))
86
+ return 'Tool is outside the delegated scope';
87
+ return childFileScopeDenial(binding.root, binding.scope, name, args);
88
+ }
89
+ /** Durable ownership is checked again before every child request and tool,
90
+ * including after reload. Completing or replacing a lease revokes the child. */
91
+ async assertCurrent(agent) {
92
+ const binding = this.#children.get(agent);
93
+ if (!binding)
94
+ return;
95
+ await this.runtime.withDatabase(db => {
96
+ const row = db.prepare('SELECT authority_json, status FROM dsh_enno_delegations WHERE delegation_id = ?')
97
+ .get(binding.delegationId);
98
+ if (!row || row.status !== 'started')
99
+ throw new KiokukoError('CONFLICT', 'The delegated execution is no longer active');
100
+ const authority = authoritySchema.parse(JSON.parse(row.authority_json));
101
+ const snapshot = readEnnoSnapshot(db, authority);
102
+ if (snapshot.status !== 'goki_executing' || snapshot.revision !== authority.revision || snapshot.dshSessionId !== binding.parentSessionId)
103
+ throw new KiokukoError('CONFLICT', 'The delegated WorkUnit authority is stale');
104
+ assertExecutionLeaseInTransaction(db, snapshot, authority);
105
+ });
106
+ }
107
+ /** Persist the created binding before the child's first request; restore only
108
+ * by its exact durable child id, never by origin/parent metadata alone. */
109
+ async restoreOrPersist(agent) {
110
+ const live = this.#children.get(agent);
111
+ if (live) {
112
+ await this.runtime.withDatabase(db => db.prepare('UPDATE dsh_enno_delegations SET child_session_id = ? WHERE delegation_id = ? AND (child_session_id IS NULL OR child_session_id = ?)')
113
+ .run(agent.session?.id ?? agent.id, live.delegationId, agent.session?.id ?? agent.id));
114
+ return live.model;
115
+ }
116
+ const stored = await this.runtime.withDatabase(db => db.prepare('SELECT delegation_id, parent_session_id, model_json, tools_json, repository_root, scope_json FROM dsh_enno_delegations WHERE child_session_id = ?')
117
+ .get(agent.session?.id ?? agent.id));
118
+ if (!stored)
119
+ return undefined;
120
+ const model = ModelBindingSchema.parse(JSON.parse(stored.model_json));
121
+ const toolNames = z.array(z.string()).parse(JSON.parse(stored.tools_json));
122
+ this.#children.set(agent, { model, toolNames, root: stored.repository_root, scope: z.array(z.string()).parse(JSON.parse(stored.scope_json)), delegationId: stored.delegation_id, parentSessionId: stored.parent_session_id, child: agent });
123
+ return model;
124
+ }
125
+ async execute(parent, args, binding, toolNames, signal) {
126
+ const input = instructionSchema.parse(args);
127
+ const allowedTools = toolNames.filter(name => CHILD_FILE_TOOLS.has(name));
128
+ if (this.isChild(parent) || !this.backend)
129
+ throw new KiokukoError('SERVICE_UNAVAILABLE', 'Native spawn delegation is unavailable; grandchildren are prohibited');
130
+ const admitted = await this.runtime.withDatabase(db => withImmediateTransaction(db, () => {
131
+ const snapshot = readEnnoSnapshot(db, binding);
132
+ if (snapshot.status !== 'goki_executing' || snapshot.revision !== binding.revision || snapshot.dshSessionId !== parent.session?.id || !binding.workUnitId || !binding.leaseToken)
133
+ throw new KiokukoError('CONFLICT', 'Delegation requires the current approved WorkUnit');
134
+ assertExecutionLeaseInTransaction(db, snapshot, { workUnitId: binding.workUnitId, leaseToken: binding.leaseToken, routeEpoch: binding.routeEpoch });
135
+ const selection = readExecutionSelection(db, binding.runId)?.value;
136
+ if (selection?.mode !== 'enno' || selection.status !== 'ready' || !selection.configuration)
137
+ throw new KiokukoError('CONFLICT', 'Choose the worker model before delegation');
138
+ const unit = snapshot.workUnits.find(u => u.workUnit.id === binding.workUnitId)?.workUnit;
139
+ if (!unit)
140
+ throw new KiokukoError('CONFLICT', 'WorkUnit is unavailable');
141
+ const digest = canonicalContentHash({ input, revision: binding.revision, workUnit: unit, model: selection.configuration.roles.worker });
142
+ const previous = db.prepare('SELECT input_digest, status, result_json FROM dsh_enno_delegations WHERE delegation_id = ?')
143
+ .get(binding.idempotencyKey);
144
+ if (previous) {
145
+ if (previous.input_digest !== digest)
146
+ throw new KiokukoError('CONFLICT', 'Delegation input changed under the same call identity');
147
+ if (previous.status === 'completed' && previous.result_json)
148
+ return { replay: JSON.parse(previous.result_json) };
149
+ throw new KiokukoError('CONFLICT', 'A previous delegation may have executed; inspect its child evidence before issuing new work');
150
+ }
151
+ const active = db.prepare("SELECT COUNT(*) AS count FROM dsh_enno_delegations WHERE run_id = ? AND status = 'started'").get(binding.runId)?.count ?? 0;
152
+ if (active >= selection.configuration.maxConcurrentChildren)
153
+ throw new KiokukoError('CONFLICT', 'Child concurrency limit reached; wait for or inspect the existing child');
154
+ const authority = authoritySchema.parse({ runId: binding.runId, workspace: binding.workspace, orchestrationId: binding.orchestrationId, revision: binding.revision, routeEpoch: binding.routeEpoch, leaseToken: binding.leaseToken, workUnitId: binding.workUnitId });
155
+ db.prepare("INSERT INTO dsh_enno_delegations (delegation_id, run_id, input_digest, status, parent_session_id, model_json, tools_json, repository_root, scope_json, authority_json) VALUES (?, ?, ?, 'started', ?, ?, ?, ?, ?, ?)")
156
+ .run(binding.idempotencyKey, binding.runId, digest, parent.session.id, JSON.stringify(selection.configuration.roles.worker), JSON.stringify(allowedTools), snapshot.repositoryRoot, JSON.stringify(unit.scope), JSON.stringify(authority));
157
+ return { model: selection.configuration.roles.worker, unit, root: snapshot.repositoryRoot };
158
+ }));
159
+ if ('replay' in admitted)
160
+ return admitted.replay;
161
+ const childBinding = { parent, parentSessionId: parent.session.id, toolNames: allowedTools, root: admitted.root, scope: admitted.unit.scope, model: admitted.model, delegationId: binding.idempotencyKey };
162
+ let run;
163
+ try {
164
+ run = await this.#pending.run(childBinding, () => this.backend.start('spawn', {
165
+ parent, signal, agentOptions: { ...admitted.model }, maxDepth: 1, label: 'Goki worker',
166
+ toolFilter: { allow: allowedTools },
167
+ prompt: [{ type: 'text', text: [
168
+ 'You are the Goki worker for one approved WorkUnit. Do not start Kiokuko intake, ask for orchestration selection, delegate, or report acceptance. You have no parent run or lease authority. Preserve other work. Stay within the declared scope. Return changed paths, verification evidence and unresolved issues to Goki.',
169
+ JSON.stringify({ objective: admitted.unit.objective, scope: admitted.unit.scope, acceptanceCriteria: admitted.unit.acceptanceCriteria, instruction: input.instruction }),
170
+ ].join('\n') }],
171
+ }));
172
+ if (!run.localAgent || childBinding.child !== run.localAgent || !this.isChild(run.localAgent))
173
+ throw new KiokukoError('INTEGRITY_ERROR', 'Spawn did not establish the exact managed child before first execution');
174
+ const child = await run.result;
175
+ if (findSecretInValue(child.output) !== undefined)
176
+ throw new KiokukoError('SECURITY_REJECTION', 'Child output contains secret-shaped content and was not persisted or forwarded');
177
+ const result = { childSessionId: run.id, stopReason: child.stopReason, output: child.output, accepted: false,
178
+ instruction: 'Goki must review this evidence and run the WorkUnit verifier before enno_work_report.' };
179
+ const json = JSON.stringify(result);
180
+ if (Buffer.byteLength(json) > 256 * 1024)
181
+ throw new KiokukoError('VALIDATION_ERROR', 'Child output exceeds the delegation result limit; inspect the native child session');
182
+ await this.runtime.withDatabase(db => db.prepare("UPDATE dsh_enno_delegations SET status = 'completed', result_json = ? WHERE delegation_id = ?").run(json, binding.idempotencyKey));
183
+ return result;
184
+ }
185
+ catch (error) {
186
+ await this.runtime.withDatabase(db => db.prepare("UPDATE dsh_enno_delegations SET status = 'uncertain' WHERE delegation_id = ? AND status = 'started'").run(binding.idempotencyKey));
187
+ throw error;
188
+ }
189
+ finally {
190
+ await run?.dispose();
191
+ }
192
+ }
193
+ }
194
+ //# sourceMappingURL=enno-delegation.js.map