@scemoon/cdh 1.0.9 → 1.0.10-beta.1

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 (786) hide show
  1. package/package.json +9 -2
  2. package/ai-dlc-skill/SKILL.md +0 -106
  3. package/ai-dlc-skill/architecture/project-structure.md +0 -78
  4. package/ai-dlc-skill/brownfield/README.md +0 -36
  5. package/ai-dlc-skill/brownfield/entry.md +0 -45
  6. package/ai-dlc-skill/brownfield/generate-context.sh +0 -64
  7. package/ai-dlc-skill/brownfield/scripts/deps.sh +0 -27
  8. package/ai-dlc-skill/brownfield/scripts/discover.sh +0 -34
  9. package/ai-dlc-skill/brownfield/scripts/extract-api.sh +0 -45
  10. package/ai-dlc-skill/components/backend.md +0 -47
  11. package/ai-dlc-skill/components/desktop.md +0 -63
  12. package/ai-dlc-skill/components/mya.md +0 -219
  13. package/ai-dlc-skill/components/native.md +0 -73
  14. package/ai-dlc-skill/components/tta.md +0 -235
  15. package/ai-dlc-skill/components/web.md +0 -77
  16. package/ai-dlc-skill/components/wxa.md +0 -219
  17. package/ai-dlc-skill/contracts/README.md +0 -25
  18. package/ai-dlc-skill/core/adaptive-flow.md +0 -107
  19. package/ai-dlc-skill/core/security.md +0 -29
  20. package/ai-dlc-skill/core/task-registry.md +0 -153
  21. package/ai-dlc-skill/cross-tool/README.md +0 -20
  22. package/ai-dlc-skill/cross-tool/cline/export.sh +0 -38
  23. package/ai-dlc-skill/cross-tool/copilot/export.sh +0 -41
  24. package/ai-dlc-skill/cross-tool/cursor/export.sh +0 -53
  25. package/ai-dlc-skill/cross-tool/onecode/export.sh +0 -27
  26. package/ai-dlc-skill/cross-tool/opencode/export.sh +0 -38
  27. package/ai-dlc-skill/phases/debug/entry.md +0 -48
  28. package/ai-dlc-skill/phases/debug/lifecycle.md +0 -284
  29. package/ai-dlc-skill/phases/deliver/entry.md +0 -35
  30. package/ai-dlc-skill/phases/deliver/lifecycle.md +0 -185
  31. package/ai-dlc-skill/phases/deliver/prompt.md +0 -54
  32. package/ai-dlc-skill/phases/deliver/rules.md +0 -61
  33. package/ai-dlc-skill/phases/plan/design_system/accessibility.md +0 -268
  34. package/ai-dlc-skill/phases/plan/design_system/atomic_design.md +0 -341
  35. package/ai-dlc-skill/phases/plan/design_system/component_spec.md +0 -398
  36. package/ai-dlc-skill/phases/plan/design_system/design_tokens.md +0 -190
  37. package/ai-dlc-skill/phases/plan/design_system/iconography.md +0 -299
  38. package/ai-dlc-skill/phases/plan/design_system/platform_ui/desktop.md +0 -318
  39. package/ai-dlc-skill/phases/plan/design_system/platform_ui/mya.md +0 -354
  40. package/ai-dlc-skill/phases/plan/design_system/platform_ui/native.md +0 -328
  41. package/ai-dlc-skill/phases/plan/design_system/platform_ui/tta.md +0 -394
  42. package/ai-dlc-skill/phases/plan/design_system/platform_ui/web.md +0 -287
  43. package/ai-dlc-skill/phases/plan/design_system/platform_ui/wxa.md +0 -374
  44. package/ai-dlc-skill/phases/plan/design_system/theme_system.md +0 -318
  45. package/ai-dlc-skill/phases/plan/entry.md +0 -33
  46. package/ai-dlc-skill/phases/plan/lifecycle.md +0 -260
  47. package/ai-dlc-skill/phases/plan/prompt.md +0 -75
  48. package/ai-dlc-skill/phases/plan/rules.md +0 -60
  49. package/ai-dlc-skill/phases/understand/entry.md +0 -36
  50. package/ai-dlc-skill/phases/understand/lifecycle.md +0 -184
  51. package/ai-dlc-skill/phases/understand/prompt.md +0 -58
  52. package/ai-dlc-skill/phases/understand/rules.md +0 -49
  53. package/ai-dlc-skill/phases/verify/config/base_url.md +0 -65
  54. package/ai-dlc-skill/phases/verify/entry.md +0 -59
  55. package/ai-dlc-skill/phases/verify/gates/browser_e2e.md +0 -96
  56. package/ai-dlc-skill/phases/verify/lifecycle.md +0 -217
  57. package/ai-dlc-skill/phases/verify/prompt.md +0 -73
  58. package/ai-dlc-skill/phases/verify/rules.md +0 -91
  59. package/ai-dlc-skill/phases/verify/runners/playwright_local.md +0 -103
  60. package/ai-dlc-skill/practices/bdd.md +0 -119
  61. package/ai-dlc-skill/practices/sdd.md +0 -84
  62. package/ai-dlc-skill/practices/tdd.md +0 -128
  63. package/ai-dlc-skill/providers/README.md +0 -114
  64. package/ai-dlc-skill/providers/aliyun/SKILL.md +0 -204
  65. package/ai-dlc-skill/providers/aliyun/api/rest-api.md +0 -214
  66. package/ai-dlc-skill/providers/aliyun/api/sdk.md +0 -307
  67. package/ai-dlc-skill/providers/aliyun/best-practices/database-design.md +0 -363
  68. package/ai-dlc-skill/providers/aliyun/best-practices/function-design.md +0 -424
  69. package/ai-dlc-skill/providers/aliyun/best-practices/troubleshooting.md +0 -258
  70. package/ai-dlc-skill/providers/aliyun/cli/database.md +0 -263
  71. package/ai-dlc-skill/providers/aliyun/cli/functions.md +0 -263
  72. package/ai-dlc-skill/providers/aliyun/cli/hosting.md +0 -226
  73. package/ai-dlc-skill/providers/aliyun/cli/setup.md +0 -235
  74. package/ai-dlc-skill/providers/aliyun/cli/storage.md +0 -315
  75. package/ai-dlc-skill/providers/aliyun/deployment.yaml +0 -66
  76. package/ai-dlc-skill/providers/aliyun/integration/ci-cd.md +0 -288
  77. package/ai-dlc-skill/providers/aliyun/preview.yaml +0 -84
  78. package/ai-dlc-skill/providers/aliyun/provider.yaml +0 -160
  79. package/ai-dlc-skill/providers/aliyun/security/authentication.md +0 -254
  80. package/ai-dlc-skill/providers/aliyun/services/cdn-hosting.md +0 -220
  81. package/ai-dlc-skill/providers/aliyun/services/database.md +0 -319
  82. package/ai-dlc-skill/providers/aliyun/services/function-compute.md +0 -273
  83. package/ai-dlc-skill/providers/aliyun/services/overview.md +0 -163
  84. package/ai-dlc-skill/providers/aliyun/services/serverless-app-engine.md +0 -266
  85. package/ai-dlc-skill/providers/aliyun/services/storage.md +0 -269
  86. package/ai-dlc-skill/providers/tcb/SKILL.md +0 -208
  87. package/ai-dlc-skill/providers/tcb/api/rest-api.md +0 -338
  88. package/ai-dlc-skill/providers/tcb/api/sdk.md +0 -288
  89. package/ai-dlc-skill/providers/tcb/best-practices/database-design.md +0 -452
  90. package/ai-dlc-skill/providers/tcb/best-practices/function-design.md +0 -502
  91. package/ai-dlc-skill/providers/tcb/best-practices/troubleshooting.md +0 -462
  92. package/ai-dlc-skill/providers/tcb/cli/cls.md +0 -133
  93. package/ai-dlc-skill/providers/tcb/cli/database.md +0 -230
  94. package/ai-dlc-skill/providers/tcb/cli/env.md +0 -207
  95. package/ai-dlc-skill/providers/tcb/cli/functions.md +0 -276
  96. package/ai-dlc-skill/providers/tcb/cli/hosting.md +0 -219
  97. package/ai-dlc-skill/providers/tcb/cli/setup.md +0 -218
  98. package/ai-dlc-skill/providers/tcb/cli/storage.md +0 -233
  99. package/ai-dlc-skill/providers/tcb/deployment.yaml +0 -111
  100. package/ai-dlc-skill/providers/tcb/integration/ci-cd.md +0 -309
  101. package/ai-dlc-skill/providers/tcb/integration/mcp-server.md +0 -371
  102. package/ai-dlc-skill/providers/tcb/preview.yaml +0 -83
  103. package/ai-dlc-skill/providers/tcb/provider.yaml +0 -172
  104. package/ai-dlc-skill/providers/tcb/security/authentication.md +0 -241
  105. package/ai-dlc-skill/providers/tcb/services/cloud-database.md +0 -299
  106. package/ai-dlc-skill/providers/tcb/services/cloud-functions.md +0 -265
  107. package/ai-dlc-skill/providers/tcb/services/cloud-hosting.md +0 -264
  108. package/ai-dlc-skill/providers/tcb/services/cloud-run.md +0 -285
  109. package/ai-dlc-skill/providers/tcb/services/cloud-storage.md +0 -245
  110. package/ai-dlc-skill/providers/tcb/services/overview.md +0 -174
  111. package/ai-dlc-skill/pybdd/README.md +0 -41
  112. package/ai-dlc-skill/pybdd/conftest.py +0 -17
  113. package/ai-dlc-skill/pybdd/example/auth/login.feature +0 -32
  114. package/ai-dlc-skill/pybdd/pytest.ini +0 -5
  115. package/ai-dlc-skill/pybdd/steps/.gitkeep +0 -1
  116. package/ai-dlc-skill/pybdd/steps/test_example_steps.py +0 -65
  117. package/ai-dlc-skill/requirements.md +0 -140
  118. package/ai-dlc-skill/skill.yaml +0 -135
  119. package/ai-dlc-skill/templates/brownfield/context.md +0 -78
  120. package/ai-dlc-skill/templates/integration/CHANGELOG.md +0 -41
  121. package/ai-dlc-skill/templates/integration/asyncapi.yaml +0 -43
  122. package/ai-dlc-skill/templates/integration/contract-diff.md +0 -63
  123. package/ai-dlc-skill/templates/integration/contract-spec.md +0 -49
  124. package/ai-dlc-skill/templates/integration/openapi.yaml +0 -18
  125. package/ai-dlc-skill/templates/integration/runtime-contract.yaml +0 -36
  126. package/ai-dlc-skill/templates/plan/design.md +0 -49
  127. package/ai-dlc-skill/templates/plan/task-list.md +0 -32
  128. package/ai-dlc-skill/templates/project/README.md +0 -126
  129. package/ai-dlc-skill/templates/project/template.md +0 -119
  130. package/ai-dlc-skill/templates/understand/feature.feature +0 -30
  131. package/ai-dlc-skill/templates/understand/intent.md +0 -29
  132. package/ai-dlc-skill/templates/understand/spec-delta.md +0 -47
  133. package/ai-dlc-skill/templates/verify/test-unit.py +0 -27
  134. package/ai-dlc-skill/walkthrough/collect.sh +0 -50
  135. package/ai-dlc-skill/walkthrough/template.md +0 -54
  136. package/cdh/__init__.py +0 -0
  137. package/cdh/__main__.py +0 -4
  138. package/cdh/__pycache__/__init__.cpython-314.pyc +0 -0
  139. package/cdh/__pycache__/cli.cpython-314.pyc +0 -0
  140. package/cdh/__pycache__/cli_logging.cpython-314.pyc +0 -0
  141. package/cdh/__pycache__/config.cpython-314.pyc +0 -0
  142. package/cdh/__pycache__/project_loader.cpython-314.pyc +0 -0
  143. package/cdh/__pycache__/scaffold.cpython-314.pyc +0 -0
  144. package/cdh/__pycache__/session_store.cpython-314.pyc +0 -0
  145. package/cdh/cdh_session_aggregator.py +0 -258
  146. package/cdh/cli.py +0 -3000
  147. package/cdh/cli_logging.py +0 -45
  148. package/cdh/config.py +0 -28
  149. package/cdh/event_loop/__init__.py +0 -7
  150. package/cdh/event_loop/bus.py +0 -123
  151. package/cdh/event_loop/events.py +0 -25
  152. package/cdh/event_loop/runner.py +0 -28
  153. package/cdh/event_loop/scheduler.py +0 -158
  154. package/cdh/generators/__init__.py +0 -35
  155. package/cdh/generators/_runtime.py +0 -176
  156. package/cdh/generators/ada/MANIFEST.toml +0 -14
  157. package/cdh/generators/ada/template.ads.tmpl +0 -7
  158. package/cdh/generators/bash/MANIFEST.toml +0 -14
  159. package/cdh/generators/bash/template.sh.tmpl +0 -16
  160. package/cdh/generators/builtin_index.json +0 -590
  161. package/cdh/generators/c/MANIFEST.toml +0 -14
  162. package/cdh/generators/c/template.h.tmpl +0 -20
  163. package/cdh/generators/cli.py +0 -379
  164. package/cdh/generators/clojure/MANIFEST.toml +0 -14
  165. package/cdh/generators/clojure/template.clj.tmpl +0 -13
  166. package/cdh/generators/cobol/MANIFEST.toml +0 -14
  167. package/cdh/generators/cobol/template.cbl.tmpl +0 -14
  168. package/cdh/generators/cpp/MANIFEST.toml +0 -14
  169. package/cdh/generators/cpp/template.hpp.tmpl +0 -32
  170. package/cdh/generators/crystal/MANIFEST.toml +0 -14
  171. package/cdh/generators/crystal/template.cr.tmpl +0 -11
  172. package/cdh/generators/csharp/MANIFEST.toml +0 -23
  173. package/cdh/generators/csharp/template.cs.tmpl +0 -14
  174. package/cdh/generators/cython/MANIFEST.toml +0 -14
  175. package/cdh/generators/cython/template.pyx.tmpl +0 -17
  176. package/cdh/generators/d/MANIFEST.toml +0 -14
  177. package/cdh/generators/d/template.d.tmpl +0 -24
  178. package/cdh/generators/dart/MANIFEST.toml +0 -17
  179. package/cdh/generators/dart/template.dart.tmpl +0 -27
  180. package/cdh/generators/elixir/MANIFEST.toml +0 -17
  181. package/cdh/generators/elixir/template.ex.tmpl +0 -27
  182. package/cdh/generators/elm/MANIFEST.toml +0 -14
  183. package/cdh/generators/elm/template.elm.tmpl +0 -20
  184. package/cdh/generators/erlang/MANIFEST.toml +0 -14
  185. package/cdh/generators/erlang/template.erl.tmpl +0 -18
  186. package/cdh/generators/fortran/MANIFEST.toml +0 -14
  187. package/cdh/generators/fortran/template.f90.tmpl +0 -24
  188. package/cdh/generators/fsharp/MANIFEST.toml +0 -14
  189. package/cdh/generators/fsharp/template.fs.tmpl +0 -17
  190. package/cdh/generators/go/MANIFEST.toml +0 -18
  191. package/cdh/generators/go/imports.go.tmpl +0 -3
  192. package/cdh/generators/go/template.go.tmpl +0 -9
  193. package/cdh/generators/graphql-schema/MANIFEST.toml +0 -18
  194. package/cdh/generators/graphql-schema/template.graphqls.tmpl +0 -12
  195. package/cdh/generators/groovy/MANIFEST.toml +0 -14
  196. package/cdh/generators/groovy/template.groovy.tmpl +0 -28
  197. package/cdh/generators/hack/MANIFEST.toml +0 -14
  198. package/cdh/generators/hack/template.hh.tmpl +0 -24
  199. package/cdh/generators/haskell/MANIFEST.toml +0 -14
  200. package/cdh/generators/haskell/template.hs.tmpl +0 -20
  201. package/cdh/generators/haxe/MANIFEST.toml +0 -14
  202. package/cdh/generators/haxe/template.hx.tmpl +0 -20
  203. package/cdh/generators/idris/MANIFEST.toml +0 -14
  204. package/cdh/generators/idris/template.idr.tmpl +0 -22
  205. package/cdh/generators/java/MANIFEST.toml +0 -18
  206. package/cdh/generators/java/template.java.tmpl +0 -13
  207. package/cdh/generators/julia/MANIFEST.toml +0 -14
  208. package/cdh/generators/julia/template.jl.tmpl +0 -27
  209. package/cdh/generators/kotlin/MANIFEST.toml +0 -18
  210. package/cdh/generators/kotlin/template.kt.tmpl +0 -12
  211. package/cdh/generators/lua/MANIFEST.toml +0 -14
  212. package/cdh/generators/lua/template.lua.tmpl +0 -27
  213. package/cdh/generators/matlab/MANIFEST.toml +0 -14
  214. package/cdh/generators/matlab/template.m.tmpl +0 -26
  215. package/cdh/generators/nim/MANIFEST.toml +0 -14
  216. package/cdh/generators/nim/template.nim.tmpl +0 -12
  217. package/cdh/generators/nix/MANIFEST.toml +0 -14
  218. package/cdh/generators/nix/template.nix.tmpl +0 -8
  219. package/cdh/generators/objective-c/MANIFEST.toml +0 -14
  220. package/cdh/generators/objective-c/template.m.tmpl +0 -31
  221. package/cdh/generators/ocaml/MANIFEST.toml +0 -14
  222. package/cdh/generators/ocaml/template.ml.tmpl +0 -13
  223. package/cdh/generators/pascal/MANIFEST.toml +0 -14
  224. package/cdh/generators/pascal/template.pas.tmpl +0 -5
  225. package/cdh/generators/perl/MANIFEST.toml +0 -14
  226. package/cdh/generators/perl/template.pm.tmpl +0 -27
  227. package/cdh/generators/php/MANIFEST.toml +0 -17
  228. package/cdh/generators/php/template.php.tmpl +0 -31
  229. package/cdh/generators/powershell/MANIFEST.toml +0 -14
  230. package/cdh/generators/powershell/template.ps1.tmpl +0 -20
  231. package/cdh/generators/protobuf/MANIFEST.toml +0 -18
  232. package/cdh/generators/protobuf/template.proto.tmpl +0 -13
  233. package/cdh/generators/python/MANIFEST.toml +0 -18
  234. package/cdh/generators/python/template.py.tmpl +0 -12
  235. package/cdh/generators/r/MANIFEST.toml +0 -14
  236. package/cdh/generators/r/template.R.tmpl +0 -29
  237. package/cdh/generators/racket/MANIFEST.toml +0 -14
  238. package/cdh/generators/racket/template.rkt.tmpl +0 -15
  239. package/cdh/generators/registry.py +0 -211
  240. package/cdh/generators/ruby/MANIFEST.toml +0 -17
  241. package/cdh/generators/ruby/template.rb.tmpl +0 -27
  242. package/cdh/generators/rust/MANIFEST.toml +0 -18
  243. package/cdh/generators/rust/template.rs.tmpl +0 -16
  244. package/cdh/generators/scala/MANIFEST.toml +0 -20
  245. package/cdh/generators/scala/template.scala.tmpl +0 -13
  246. package/cdh/generators/scheme/MANIFEST.toml +0 -14
  247. package/cdh/generators/scheme/template.scm.tmpl +0 -16
  248. package/cdh/generators/solidity/MANIFEST.toml +0 -14
  249. package/cdh/generators/solidity/template.sol.tmpl +0 -24
  250. package/cdh/generators/swift/MANIFEST.toml +0 -18
  251. package/cdh/generators/swift/template.swift.tmpl +0 -10
  252. package/cdh/generators/typescript/MANIFEST.toml +0 -18
  253. package/cdh/generators/typescript/template.ts.tmpl +0 -7
  254. package/cdh/generators/version.py +0 -214
  255. package/cdh/generators/zig/MANIFEST.toml +0 -14
  256. package/cdh/generators/zig/template.zig.tmpl +0 -20
  257. package/cdh/logging.py +0 -314
  258. package/cdh/optimizer/__init__.py +0 -7
  259. package/cdh/optimizer/loop.py +0 -201
  260. package/cdh/optimizer/mutation.py +0 -85
  261. package/cdh/optimizer/reward.py +0 -51
  262. package/cdh/optimizer/tracker.py +0 -118
  263. package/cdh/project_loader.py +0 -1022
  264. package/cdh/rules/patterns.yaml +0 -132
  265. package/cdh/rules/spectral.yaml +0 -301
  266. package/cdh/scaffold.py +0 -1436
  267. package/cdh/session_store.py +0 -221
  268. package/cdh/state_schema.py +0 -127
  269. package/cdh/tools/__init__.py +0 -57
  270. package/cdh/tools/cls_search.py +0 -406
  271. package/cdh/tools/contract_diff.py +0 -644
  272. package/cdh/tools/deploy_stack.py +0 -590
  273. package/cdh/tools/generate_shared.py +0 -300
  274. package/cdh/tools/iac_gen.py +0 -224
  275. package/cdh/tools/otel_export.py +0 -125
  276. package/cdh/tools/pattern_detect.py +0 -451
  277. package/cdh/tools/retrofit_labels.py +0 -505
  278. package/cdh/trace/__init__.py +0 -101
  279. package/cdh/trace/__pycache__/__init__.cpython-314.pyc +0 -0
  280. package/cdh/trace/dashboard/__init__.py +0 -61
  281. package/cdh/trace/dashboard/api.py +0 -1032
  282. package/cdh/trace/dashboard/app.html +0 -1321
  283. package/cdh/trace/dashboard/server.py +0 -310
  284. package/cdh/trace/otel_exporter.py +0 -462
  285. package/cdh/trace/otel_tracer.py +0 -281
  286. package/cdh/tui.py +0 -1084
  287. package/cdh/validators/__init__.py +0 -16
  288. package/cdh/validators/__pycache__/__init__.cpython-314.pyc +0 -0
  289. package/cdh/validators/__pycache__/bdd.cpython-314.pyc +0 -0
  290. package/cdh/validators/__pycache__/dag.cpython-314.pyc +0 -0
  291. package/cdh/validators/__pycache__/ears.cpython-314.pyc +0 -0
  292. package/cdh/validators/__pycache__/fr_namespace.cpython-314.pyc +0 -0
  293. package/cdh/validators/bdd.py +0 -144
  294. package/cdh/validators/dag.py +0 -179
  295. package/cdh/validators/ears.py +0 -452
  296. package/cdh/validators/fr_namespace.py +0 -143
  297. package/cdh/validators/spectral.py +0 -475
  298. package/cdh/verification/__init__.py +0 -3
  299. package/cdh/verification/aggregation.py +0 -53
  300. package/cdh/verification/gates/__init__.py +0 -5
  301. package/cdh/verification/gates/base.py +0 -18
  302. package/cdh/verification/gates/lint_gate.py +0 -37
  303. package/cdh/verification/gates/test_gate.py +0 -41
  304. package/cdh/verification/loop.py +0 -93
  305. package/cdh/verification/policy.py +0 -24
  306. package/onecode/__init__.py +0 -1
  307. package/onecode/__main__.py +0 -4
  308. package/onecode/__pycache__/__init__.cpython-314.pyc +0 -0
  309. package/onecode/__pycache__/cli.cpython-314.pyc +0 -0
  310. package/onecode/__pycache__/commands.cpython-314.pyc +0 -0
  311. package/onecode/__pycache__/config.cpython-314.pyc +0 -0
  312. package/onecode/__pycache__/migrate.cpython-314.pyc +0 -0
  313. package/onecode/agent/__init__.py +0 -0
  314. package/onecode/agent/__pycache__/__init__.cpython-314.pyc +0 -0
  315. package/onecode/agent/__pycache__/cdh_loader.cpython-314.pyc +0 -0
  316. package/onecode/agent/__pycache__/checkpoint.cpython-314.pyc +0 -0
  317. package/onecode/agent/__pycache__/context.cpython-314.pyc +0 -0
  318. package/onecode/agent/__pycache__/engine.cpython-314.pyc +0 -0
  319. package/onecode/agent/__pycache__/hooks.cpython-314.pyc +0 -0
  320. package/onecode/agent/__pycache__/onecode_agent_acp.cpython-314.pyc +0 -0
  321. package/onecode/agent/__pycache__/permissions.cpython-314.pyc +0 -0
  322. package/onecode/agent/__pycache__/permissions_store.cpython-314.pyc +0 -0
  323. package/onecode/agent/__pycache__/project_doc.cpython-314.pyc +0 -0
  324. package/onecode/agent/__pycache__/session.cpython-314.pyc +0 -0
  325. package/onecode/agent/__pycache__/turn_record.cpython-314.pyc +0 -0
  326. package/onecode/agent/agents/__init__.py +0 -29
  327. package/onecode/agent/agents/__pycache__/__init__.cpython-314.pyc +0 -0
  328. package/onecode/agent/agents/__pycache__/types.cpython-314.pyc +0 -0
  329. package/onecode/agent/agents/prompts/build-agent.md +0 -50
  330. package/onecode/agent/agents/prompts/compaction-instructions.md +0 -12
  331. package/onecode/agent/agents/prompts/explore-agent.md +0 -42
  332. package/onecode/agent/agents/prompts/plan-agent.md +0 -44
  333. package/onecode/agent/agents/prompts/plan-gate-hard.md +0 -4
  334. package/onecode/agent/agents/prompts/plan-gate-soft.md +0 -3
  335. package/onecode/agent/agents/prompts/solo-agent.md +0 -57
  336. package/onecode/agent/agents/prompts/subagent-constraints.md +0 -10
  337. package/onecode/agent/agents/prompts/summary-instructions.md +0 -7
  338. package/onecode/agent/agents/prompts/title-instructions.md +0 -3
  339. package/onecode/agent/agents/prompts/tool-descriptions.md +0 -129
  340. package/onecode/agent/agents/types.py +0 -786
  341. package/onecode/agent/attachments.py +0 -112
  342. package/onecode/agent/cdh_loader.py +0 -3
  343. package/onecode/agent/checkpoint.py +0 -285
  344. package/onecode/agent/context.py +0 -465
  345. package/onecode/agent/engine.py +0 -3547
  346. package/onecode/agent/event_bridge.py +0 -75
  347. package/onecode/agent/hooks.py +0 -86
  348. package/onecode/agent/onecode_agent_acp.py +0 -2993
  349. package/onecode/agent/permissions.py +0 -150
  350. package/onecode/agent/permissions_store.py +0 -73
  351. package/onecode/agent/project_doc.py +0 -19
  352. package/onecode/agent/question_detect.py +0 -230
  353. package/onecode/agent/session.py +0 -3
  354. package/onecode/agent/snapshot.py +0 -144
  355. package/onecode/agent/tools/__init__.py +0 -17
  356. package/onecode/agent/tools/__pycache__/__init__.cpython-314.pyc +0 -0
  357. package/onecode/agent/tools/__pycache__/agent_tools.cpython-314.pyc +0 -0
  358. package/onecode/agent/tools/__pycache__/apply_patch_tool.cpython-314.pyc +0 -0
  359. package/onecode/agent/tools/__pycache__/bash_tool.cpython-314.pyc +0 -0
  360. package/onecode/agent/tools/__pycache__/communication_tools.cpython-314.pyc +0 -0
  361. package/onecode/agent/tools/__pycache__/config_tool.cpython-314.pyc +0 -0
  362. package/onecode/agent/tools/__pycache__/cron_tools.cpython-314.pyc +0 -0
  363. package/onecode/agent/tools/__pycache__/errors.cpython-314.pyc +0 -0
  364. package/onecode/agent/tools/__pycache__/file_ops.cpython-314.pyc +0 -0
  365. package/onecode/agent/tools/__pycache__/file_tools.cpython-314.pyc +0 -0
  366. package/onecode/agent/tools/__pycache__/git_tools.cpython-314.pyc +0 -0
  367. package/onecode/agent/tools/__pycache__/lsp_tools.cpython-314.pyc +0 -0
  368. package/onecode/agent/tools/__pycache__/mcp_tools.cpython-314.pyc +0 -0
  369. package/onecode/agent/tools/__pycache__/permission_handler.cpython-314.pyc +0 -0
  370. package/onecode/agent/tools/__pycache__/permissions.cpython-314.pyc +0 -0
  371. package/onecode/agent/tools/__pycache__/protocol.cpython-314.pyc +0 -0
  372. package/onecode/agent/tools/__pycache__/registry.cpython-314.pyc +0 -0
  373. package/onecode/agent/tools/__pycache__/sandbox.cpython-314.pyc +0 -0
  374. package/onecode/agent/tools/__pycache__/schema_validation.cpython-314.pyc +0 -0
  375. package/onecode/agent/tools/__pycache__/skill_tools.cpython-314.pyc +0 -0
  376. package/onecode/agent/tools/__pycache__/todo_tools.cpython-314.pyc +0 -0
  377. package/onecode/agent/tools/__pycache__/web_tools.cpython-314.pyc +0 -0
  378. package/onecode/agent/tools/agent_tools.py +0 -128
  379. package/onecode/agent/tools/apply_patch_tool.py +0 -138
  380. package/onecode/agent/tools/bash_tool.py +0 -121
  381. package/onecode/agent/tools/communication_tools.py +0 -154
  382. package/onecode/agent/tools/config_tool.py +0 -130
  383. package/onecode/agent/tools/cron_tools.py +0 -178
  384. package/onecode/agent/tools/errors.py +0 -17
  385. package/onecode/agent/tools/file_ops.py +0 -221
  386. package/onecode/agent/tools/file_tools.py +0 -225
  387. package/onecode/agent/tools/git_tools.py +0 -88
  388. package/onecode/agent/tools/lsp_tools.py +0 -404
  389. package/onecode/agent/tools/mcp_tools.py +0 -211
  390. package/onecode/agent/tools/permission_handler.py +0 -46
  391. package/onecode/agent/tools/permissions.py +0 -77
  392. package/onecode/agent/tools/protocol.py +0 -20
  393. package/onecode/agent/tools/registry.py +0 -210
  394. package/onecode/agent/tools/sandbox.py +0 -460
  395. package/onecode/agent/tools/schema_validation.py +0 -100
  396. package/onecode/agent/tools/skill_tools.py +0 -52
  397. package/onecode/agent/tools/todo_tools.py +0 -208
  398. package/onecode/agent/tools/web_tools.py +0 -530
  399. package/onecode/agent/turn_record.py +0 -28
  400. package/onecode/builtin_skills/agent-browser/SKILL.md +0 -212
  401. package/onecode/builtin_skills/agent-browser/skill.yaml +0 -8
  402. package/onecode/builtin_skills/cloudbase/SKILL.md +0 -162
  403. package/onecode/builtin_skills/cloudbase/skill.yaml +0 -7
  404. package/onecode/builtin_skills/git/SKILL.md +0 -64
  405. package/onecode/builtin_skills/git/skill.yaml +0 -7
  406. package/onecode/builtin_skills/shell/SKILL.md +0 -58
  407. package/onecode/builtin_skills/shell/skill.yaml +0 -8
  408. package/onecode/builtin_skills/skill-creator/SKILL.md +0 -106
  409. package/onecode/builtin_skills/skill-creator/skill.yaml +0 -8
  410. package/onecode/cli.py +0 -1325
  411. package/onecode/codebase/__init__.py +0 -69
  412. package/onecode/codebase/__pycache__/__init__.cpython-314.pyc +0 -0
  413. package/onecode/codebase/__pycache__/chunker.cpython-314.pyc +0 -0
  414. package/onecode/codebase/__pycache__/indexer.cpython-314.pyc +0 -0
  415. package/onecode/codebase/__pycache__/retriever.cpython-314.pyc +0 -0
  416. package/onecode/codebase/__pycache__/storage.cpython-314.pyc +0 -0
  417. package/onecode/codebase/__pycache__/tools.cpython-314.pyc +0 -0
  418. package/onecode/codebase/chunker.py +0 -125
  419. package/onecode/codebase/indexer.py +0 -154
  420. package/onecode/codebase/retriever.py +0 -240
  421. package/onecode/codebase/storage.py +0 -153
  422. package/onecode/codebase/tools.py +0 -59
  423. package/onecode/commands.py +0 -673
  424. package/onecode/config.py +0 -539
  425. package/onecode/config_screen.py +0 -486
  426. package/onecode/cron/__init__.py +0 -3
  427. package/onecode/lsp/__init__.py +0 -3
  428. package/onecode/mcp/__init__.py +0 -11
  429. package/onecode/mcp/__pycache__/__init__.cpython-314.pyc +0 -0
  430. package/onecode/mcp/__pycache__/client.cpython-314.pyc +0 -0
  431. package/onecode/mcp/__pycache__/cloudbase.cpython-314.pyc +0 -0
  432. package/onecode/mcp/__pycache__/config.cpython-314.pyc +0 -0
  433. package/onecode/mcp/__pycache__/manager.cpython-314.pyc +0 -0
  434. package/onecode/mcp/__pycache__/oauth.cpython-314.pyc +0 -0
  435. package/onecode/mcp/client.py +0 -305
  436. package/onecode/mcp/cloudbase.py +0 -188
  437. package/onecode/mcp/config.py +0 -363
  438. package/onecode/mcp/manager.py +0 -603
  439. package/onecode/mcp/oauth.py +0 -199
  440. package/onecode/memory/__init__.py +0 -106
  441. package/onecode/memory/__pycache__/__init__.cpython-314.pyc +0 -0
  442. package/onecode/memory/__pycache__/backend.cpython-314.pyc +0 -0
  443. package/onecode/memory/__pycache__/pyramid.cpython-314.pyc +0 -0
  444. package/onecode/memory/__pycache__/recall.cpython-314.pyc +0 -0
  445. package/onecode/memory/backend.py +0 -179
  446. package/onecode/memory/pyramid.py +0 -145
  447. package/onecode/memory/recall.py +0 -322
  448. package/onecode/migrate.py +0 -122
  449. package/onecode/models/__init__.py +0 -4
  450. package/onecode/models/__pycache__/__init__.cpython-314.pyc +0 -0
  451. package/onecode/models/__pycache__/errors.cpython-314.pyc +0 -0
  452. package/onecode/models/__pycache__/messages.cpython-314.pyc +0 -0
  453. package/onecode/models/__pycache__/ollama_manager.cpython-314.pyc +0 -0
  454. package/onecode/models/__pycache__/provider.cpython-314.pyc +0 -0
  455. package/onecode/models/__pycache__/registry.cpython-314.pyc +0 -0
  456. package/onecode/models/errors.py +0 -104
  457. package/onecode/models/messages.py +0 -750
  458. package/onecode/models/ollama_manager.py +0 -167
  459. package/onecode/models/provider.py +0 -730
  460. package/onecode/models/providers/__init__.py +0 -17
  461. package/onecode/models/providers/__pycache__/__init__.cpython-314.pyc +0 -0
  462. package/onecode/models/providers/__pycache__/anthropic_provider.cpython-314.pyc +0 -0
  463. package/onecode/models/providers/__pycache__/deepseek_provider.cpython-314.pyc +0 -0
  464. package/onecode/models/providers/__pycache__/glm_provider.cpython-314.pyc +0 -0
  465. package/onecode/models/providers/__pycache__/minimax_provider.cpython-314.pyc +0 -0
  466. package/onecode/models/providers/__pycache__/minimaxi_provider.cpython-314.pyc +0 -0
  467. package/onecode/models/providers/__pycache__/ollama_provider.cpython-314.pyc +0 -0
  468. package/onecode/models/providers/__pycache__/openai_provider.cpython-314.pyc +0 -0
  469. package/onecode/models/providers/anthropic_provider.py +0 -286
  470. package/onecode/models/providers/deepseek_provider.py +0 -221
  471. package/onecode/models/providers/glm_provider.py +0 -219
  472. package/onecode/models/providers/minimax_provider.py +0 -182
  473. package/onecode/models/providers/minimaxi_provider.py +0 -426
  474. package/onecode/models/providers/ollama_provider.py +0 -183
  475. package/onecode/models/providers/openai_provider.py +0 -234
  476. package/onecode/models/registry.py +0 -349
  477. package/onecode/server/__init__.py +0 -3
  478. package/onecode/server/app.py +0 -251
  479. package/onecode/skills/__init__.py +0 -11
  480. package/onecode/skills/__pycache__/__init__.cpython-314.pyc +0 -0
  481. package/onecode/skills/__pycache__/argument_substitution.cpython-314.pyc +0 -0
  482. package/onecode/skills/__pycache__/bootstrap.cpython-314.pyc +0 -0
  483. package/onecode/skills/__pycache__/create.cpython-314.pyc +0 -0
  484. package/onecode/skills/__pycache__/frontmatter.cpython-314.pyc +0 -0
  485. package/onecode/skills/__pycache__/loader.cpython-314.pyc +0 -0
  486. package/onecode/skills/__pycache__/model.cpython-314.pyc +0 -0
  487. package/onecode/skills/argument_substitution.py +0 -38
  488. package/onecode/skills/bootstrap.py +0 -37
  489. package/onecode/skills/create.py +0 -56
  490. package/onecode/skills/frontmatter.py +0 -33
  491. package/onecode/skills/loader.py +0 -215
  492. package/onecode/skills/manager.py +0 -75
  493. package/onecode/skills/model.py +0 -43
  494. package/onecode/storage/__init__.py +0 -0
  495. package/onecode/storage/activity.py +0 -63
  496. package/onecode/storage/project.py +0 -54
  497. package/onecode/storage/session.py +0 -112
  498. package/onecode/tasks/__init__.py +0 -26
  499. package/onecode/tasks/manager.py +0 -232
  500. package/onecode/tasks/models.py +0 -240
  501. package/onecode/trace/__init__.py +0 -0
  502. package/onecode/trace/tracer.py +0 -173
  503. package/onecode/utils/__init__.py +0 -0
  504. package/onecode/utils/helpers.py +0 -20
  505. package/onecode/verification/__init__.py +0 -5
  506. package/onecode/verification/__pycache__/__init__.cpython-314.pyc +0 -0
  507. package/onecode/verification/__pycache__/aggregation.cpython-314.pyc +0 -0
  508. package/onecode/verification/__pycache__/loop.cpython-314.pyc +0 -0
  509. package/onecode/verification/__pycache__/policy.cpython-314.pyc +0 -0
  510. package/onecode/verification/aggregation.py +0 -53
  511. package/onecode/verification/gates/__init__.py +0 -6
  512. package/onecode/verification/gates/__pycache__/__init__.cpython-314.pyc +0 -0
  513. package/onecode/verification/gates/__pycache__/base.cpython-314.pyc +0 -0
  514. package/onecode/verification/gates/__pycache__/lint_gate.cpython-314.pyc +0 -0
  515. package/onecode/verification/gates/__pycache__/test_gate.cpython-314.pyc +0 -0
  516. package/onecode/verification/gates/__pycache__/type_gate.cpython-314.pyc +0 -0
  517. package/onecode/verification/gates/base.py +0 -20
  518. package/onecode/verification/gates/lint_gate.py +0 -45
  519. package/onecode/verification/gates/test_gate.py +0 -62
  520. package/onecode/verification/gates/type_gate.py +0 -46
  521. package/onecode/verification/loop.py +0 -95
  522. package/onecode/verification/policy.py +0 -29
  523. package/pyproject.toml +0 -84
  524. package/tui/__init__.py +0 -46
  525. package/tui/__main__.py +0 -4
  526. package/tui/__pycache__/__init__.cpython-314.pyc +0 -0
  527. package/tui/__pycache__/_loop.cpython-314.pyc +0 -0
  528. package/tui/__pycache__/_path_fuzzy_search.cpython-314.pyc +0 -0
  529. package/tui/__pycache__/_path_match.cpython-314.pyc +0 -0
  530. package/tui/__pycache__/agent.cpython-314.pyc +0 -0
  531. package/tui/__pycache__/agent_schema.cpython-314.pyc +0 -0
  532. package/tui/__pycache__/agents.cpython-314.pyc +0 -0
  533. package/tui/__pycache__/answer.cpython-314.pyc +0 -0
  534. package/tui/__pycache__/app.cpython-314.pyc +0 -0
  535. package/tui/__pycache__/atomic.cpython-314.pyc +0 -0
  536. package/tui/__pycache__/complete.cpython-314.pyc +0 -0
  537. package/tui/__pycache__/constants.cpython-314.pyc +0 -0
  538. package/tui/__pycache__/conversation_markdown.cpython-314.pyc +0 -0
  539. package/tui/__pycache__/db.cpython-314.pyc +0 -0
  540. package/tui/__pycache__/dec.cpython-314.pyc +0 -0
  541. package/tui/__pycache__/directory.cpython-314.pyc +0 -0
  542. package/tui/__pycache__/directory_watcher.cpython-314.pyc +0 -0
  543. package/tui/__pycache__/format_path.cpython-314.pyc +0 -0
  544. package/tui/__pycache__/fuzzy.cpython-314.pyc +0 -0
  545. package/tui/__pycache__/fuzzy_index.cpython-314.pyc +0 -0
  546. package/tui/__pycache__/history.cpython-314.pyc +0 -0
  547. package/tui/__pycache__/jsonrpc.cpython-314.pyc +0 -0
  548. package/tui/__pycache__/menus.cpython-314.pyc +0 -0
  549. package/tui/__pycache__/message_log.cpython-314.pyc +0 -0
  550. package/tui/__pycache__/messages.cpython-314.pyc +0 -0
  551. package/tui/__pycache__/path_complete.cpython-314.pyc +0 -0
  552. package/tui/__pycache__/path_filter.cpython-314.pyc +0 -0
  553. package/tui/__pycache__/paths.cpython-314.pyc +0 -0
  554. package/tui/__pycache__/pill.cpython-314.pyc +0 -0
  555. package/tui/__pycache__/platform_commands.cpython-314.pyc +0 -0
  556. package/tui/__pycache__/protocol.cpython-314.pyc +0 -0
  557. package/tui/__pycache__/session_tracker.cpython-314.pyc +0 -0
  558. package/tui/__pycache__/settings.cpython-314.pyc +0 -0
  559. package/tui/__pycache__/settings_schema.cpython-314.pyc +0 -0
  560. package/tui/__pycache__/shell.cpython-314.pyc +0 -0
  561. package/tui/__pycache__/shell_read.cpython-314.pyc +0 -0
  562. package/tui/__pycache__/slash_command.cpython-314.pyc +0 -0
  563. package/tui/__pycache__/version.cpython-314.pyc +0 -0
  564. package/tui/_loop.py +0 -86
  565. package/tui/_path_fuzzy_search.py +0 -48
  566. package/tui/_path_match.py +0 -141
  567. package/tui/about.py +0 -95
  568. package/tui/acp/__pycache__/agent.cpython-314.pyc +0 -0
  569. package/tui/acp/__pycache__/api.cpython-314.pyc +0 -0
  570. package/tui/acp/__pycache__/encode_tool_call_id.cpython-314.pyc +0 -0
  571. package/tui/acp/__pycache__/event_tap.cpython-314.pyc +0 -0
  572. package/tui/acp/__pycache__/messages.cpython-314.pyc +0 -0
  573. package/tui/acp/__pycache__/prompt.cpython-314.pyc +0 -0
  574. package/tui/acp/__pycache__/protocol.cpython-314.pyc +0 -0
  575. package/tui/acp/agent.py +0 -1212
  576. package/tui/acp/api.py +0 -79
  577. package/tui/acp/encode_tool_call_id.py +0 -12
  578. package/tui/acp/event_tap.py +0 -107
  579. package/tui/acp/messages.py +0 -222
  580. package/tui/acp/prompt.py +0 -53
  581. package/tui/acp/protocol.py +0 -551
  582. package/tui/agent.py +0 -70
  583. package/tui/agent_schema.py +0 -76
  584. package/tui/agents.py +0 -46
  585. package/tui/ansi/__init__.py +0 -1
  586. package/tui/ansi/__pycache__/__init__.cpython-314.pyc +0 -0
  587. package/tui/ansi/__pycache__/_ansi.cpython-314.pyc +0 -0
  588. package/tui/ansi/__pycache__/_ansi_colors.cpython-314.pyc +0 -0
  589. package/tui/ansi/__pycache__/_control_codes.cpython-314.pyc +0 -0
  590. package/tui/ansi/__pycache__/_keys.cpython-314.pyc +0 -0
  591. package/tui/ansi/__pycache__/_sgr_styles.cpython-314.pyc +0 -0
  592. package/tui/ansi/__pycache__/_stream_parser.cpython-314.pyc +0 -0
  593. package/tui/ansi/_ansi.py +0 -1689
  594. package/tui/ansi/_ansi_colors.py +0 -264
  595. package/tui/ansi/_control_codes.py +0 -37
  596. package/tui/ansi/_keys.py +0 -251
  597. package/tui/ansi/_sgr_styles.py +0 -64
  598. package/tui/ansi/_stream_parser.py +0 -418
  599. package/tui/answer.py +0 -12
  600. package/tui/app.py +0 -1195
  601. package/tui/atomic.py +0 -37
  602. package/tui/cli.py +0 -208
  603. package/tui/code_analyze.py +0 -27
  604. package/tui/complete.py +0 -38
  605. package/tui/constants.py +0 -61
  606. package/tui/conversation_markdown.py +0 -30
  607. package/tui/danger.py +0 -372
  608. package/tui/data/agents/ampcode.com.toml +0 -52
  609. package/tui/data/agents/augmentcode.com.toml +0 -41
  610. package/tui/data/agents/cdh.cloud-dev-harness.toml +0 -23
  611. package/tui/data/agents/claude.com.toml +0 -42
  612. package/tui/data/agents/copilot.github.com.toml +0 -29
  613. package/tui/data/agents/crowai.dev.toml +0 -36
  614. package/tui/data/agents/cursor.com.toml +0 -38
  615. package/tui/data/agents/deepagents.langchain.com +0 -34
  616. package/tui/data/agents/docker.com.toml +0 -60
  617. package/tui/data/agents/geminicli.com.toml +0 -28
  618. package/tui/data/agents/goose.ai.toml +0 -52
  619. package/tui/data/agents/inference.huggingface.co.toml +0 -41
  620. package/tui/data/agents/kimi.com.toml +0 -35
  621. package/tui/data/agents/kiro.dev.toml +0 -43
  622. package/tui/data/agents/onecode.dev.toml +0 -22
  623. package/tui/data/agents/openai.com.toml +0 -53
  624. package/tui/data/agents/openclaw.ai.toml +0 -37
  625. package/tui/data/agents/opencode.ai.toml +0 -39
  626. package/tui/data/agents/openhands.dev.toml +0 -46
  627. package/tui/data/agents/stakpak.dev.toml +0 -62
  628. package/tui/data/agents/vibe.mistral.ai.toml +0 -31
  629. package/tui/data/agents/vtcode.dev.toml +0 -63
  630. package/tui/data/images/frog.png +0 -0
  631. package/tui/data/sounds/question.wav +0 -0
  632. package/tui/data/sounds/turn-over.wav +0 -0
  633. package/tui/db.py +0 -213
  634. package/tui/dec.py +0 -332
  635. package/tui/diff_utils.py +0 -131
  636. package/tui/directory.py +0 -234
  637. package/tui/directory_suggester.py +0 -93
  638. package/tui/directory_watcher.py +0 -231
  639. package/tui/format_path.py +0 -25
  640. package/tui/fuzzy.py +0 -140
  641. package/tui/fuzzy_index.py +0 -275
  642. package/tui/gist.py +0 -33
  643. package/tui/history.py +0 -138
  644. package/tui/jsonrpc.py +0 -599
  645. package/tui/menus.py +0 -14
  646. package/tui/message_log.py +0 -69
  647. package/tui/messages.py +0 -144
  648. package/tui/option_content.py +0 -51
  649. package/tui/os.py +0 -0
  650. package/tui/path_complete.py +0 -217
  651. package/tui/path_filter.py +0 -124
  652. package/tui/paths.py +0 -87
  653. package/tui/pill.py +0 -23
  654. package/tui/platform_commands.py +0 -52
  655. package/tui/prompt/__pycache__/extract.cpython-314.pyc +0 -0
  656. package/tui/prompt/__pycache__/resource.cpython-314.pyc +0 -0
  657. package/tui/prompt/extract.py +0 -19
  658. package/tui/prompt/resource.py +0 -68
  659. package/tui/protocol.py +0 -28
  660. package/tui/screens/__init__.py +0 -0
  661. package/tui/screens/__pycache__/__init__.cpython-314.pyc +0 -0
  662. package/tui/screens/__pycache__/diff_screen.cpython-314.pyc +0 -0
  663. package/tui/screens/__pycache__/main.cpython-314.pyc +0 -0
  664. package/tui/screens/__pycache__/sessions.cpython-314.pyc +0 -0
  665. package/tui/screens/action_modal.py +0 -94
  666. package/tui/screens/agent_modal.py +0 -175
  667. package/tui/screens/command_edit_modal.py +0 -74
  668. package/tui/screens/diff_explorer_screen.py +0 -419
  669. package/tui/screens/diff_screen.py +0 -84
  670. package/tui/screens/ide_screen.py +0 -461
  671. package/tui/screens/main.py +0 -397
  672. package/tui/screens/main.tcss +0 -662
  673. package/tui/screens/permissions.py +0 -404
  674. package/tui/screens/permissions.tcss +0 -72
  675. package/tui/screens/projects.tcss +0 -84
  676. package/tui/screens/projects_app.py +0 -341
  677. package/tui/screens/projects_screen.py +0 -277
  678. package/tui/screens/session_resume_modal.py +0 -172
  679. package/tui/screens/session_resume_modal.tcss +0 -35
  680. package/tui/screens/sessions.py +0 -171
  681. package/tui/screens/sessions.tcss +0 -119
  682. package/tui/screens/settings.py +0 -293
  683. package/tui/screens/settings.tcss +0 -113
  684. package/tui/screens/store.py +0 -502
  685. package/tui/screens/store.tcss +0 -274
  686. package/tui/screens/tool_content_screen.py +0 -59
  687. package/tui/screens/trace.py +0 -317
  688. package/tui/session_tracker.py +0 -123
  689. package/tui/settings.py +0 -353
  690. package/tui/settings_schema.py +0 -467
  691. package/tui/shell.py +0 -304
  692. package/tui/shell_read.py +0 -42
  693. package/tui/slash_command.py +0 -34
  694. package/tui/tui.tcss +0 -246
  695. package/tui/twitter.py +0 -38
  696. package/tui/version.py +0 -80
  697. package/tui/visuals/__init__.py +0 -0
  698. package/tui/visuals/__pycache__/__init__.cpython-314.pyc +0 -0
  699. package/tui/visuals/__pycache__/columns.cpython-314.pyc +0 -0
  700. package/tui/visuals/columns.py +0 -272
  701. package/tui/widgets/__init__.py +0 -0
  702. package/tui/widgets/__pycache__/__init__.cpython-314.pyc +0 -0
  703. package/tui/widgets/__pycache__/agent_response.cpython-314.pyc +0 -0
  704. package/tui/widgets/__pycache__/agent_thought.cpython-314.pyc +0 -0
  705. package/tui/widgets/__pycache__/aidlc.cpython-314.pyc +0 -0
  706. package/tui/widgets/__pycache__/ask_user.cpython-314.pyc +0 -0
  707. package/tui/widgets/__pycache__/condensed_path.cpython-314.pyc +0 -0
  708. package/tui/widgets/__pycache__/context_stats.cpython-314.pyc +0 -0
  709. package/tui/widgets/__pycache__/conversation.cpython-314.pyc +0 -0
  710. package/tui/widgets/__pycache__/diff_view.cpython-314.pyc +0 -0
  711. package/tui/widgets/__pycache__/flash.cpython-314.pyc +0 -0
  712. package/tui/widgets/__pycache__/future_text.cpython-314.pyc +0 -0
  713. package/tui/widgets/__pycache__/grid_select.cpython-314.pyc +0 -0
  714. package/tui/widgets/__pycache__/highlighted_textarea.cpython-314.pyc +0 -0
  715. package/tui/widgets/__pycache__/load_more.cpython-314.pyc +0 -0
  716. package/tui/widgets/__pycache__/menu.cpython-314.pyc +0 -0
  717. package/tui/widgets/__pycache__/modified_files.cpython-314.pyc +0 -0
  718. package/tui/widgets/__pycache__/non_selectable_label.cpython-314.pyc +0 -0
  719. package/tui/widgets/__pycache__/note.cpython-314.pyc +0 -0
  720. package/tui/widgets/__pycache__/path_search.cpython-314.pyc +0 -0
  721. package/tui/widgets/__pycache__/pending_prompts.cpython-314.pyc +0 -0
  722. package/tui/widgets/__pycache__/plan.cpython-314.pyc +0 -0
  723. package/tui/widgets/__pycache__/project_directory_tree.cpython-314.pyc +0 -0
  724. package/tui/widgets/__pycache__/prompt.cpython-314.pyc +0 -0
  725. package/tui/widgets/__pycache__/question.cpython-314.pyc +0 -0
  726. package/tui/widgets/__pycache__/session_grid_select.cpython-314.pyc +0 -0
  727. package/tui/widgets/__pycache__/session_summary.cpython-314.pyc +0 -0
  728. package/tui/widgets/__pycache__/session_tabs.cpython-314.pyc +0 -0
  729. package/tui/widgets/__pycache__/shell_terminal.cpython-314.pyc +0 -0
  730. package/tui/widgets/__pycache__/side_bar.cpython-314.pyc +0 -0
  731. package/tui/widgets/__pycache__/slash_complete.cpython-314.pyc +0 -0
  732. package/tui/widgets/__pycache__/strike_text.cpython-314.pyc +0 -0
  733. package/tui/widgets/__pycache__/terminal.cpython-314.pyc +0 -0
  734. package/tui/widgets/__pycache__/throbber.cpython-314.pyc +0 -0
  735. package/tui/widgets/__pycache__/tool_call.cpython-314.pyc +0 -0
  736. package/tui/widgets/__pycache__/user_input.cpython-314.pyc +0 -0
  737. package/tui/widgets/acp_content.py +0 -70
  738. package/tui/widgets/agent_response.py +0 -76
  739. package/tui/widgets/agent_thought.py +0 -167
  740. package/tui/widgets/aidlc.py +0 -334
  741. package/tui/widgets/ask_user.py +0 -604
  742. package/tui/widgets/command_pane.py +0 -223
  743. package/tui/widgets/condensed_path.py +0 -115
  744. package/tui/widgets/context_stats.py +0 -66
  745. package/tui/widgets/conversation.py +0 -3235
  746. package/tui/widgets/danger_warning.py +0 -65
  747. package/tui/widgets/diff_view.py +0 -69
  748. package/tui/widgets/directory_input.py +0 -8
  749. package/tui/widgets/edit_field.py +0 -206
  750. package/tui/widgets/flash.py +0 -81
  751. package/tui/widgets/future_text.py +0 -126
  752. package/tui/widgets/grid_select.py +0 -234
  753. package/tui/widgets/highlighted_textarea.py +0 -183
  754. package/tui/widgets/load_more.py +0 -24
  755. package/tui/widgets/mandelbrot.py +0 -294
  756. package/tui/widgets/markdown_note.py +0 -13
  757. package/tui/widgets/menu.py +0 -147
  758. package/tui/widgets/model_status.py +0 -230
  759. package/tui/widgets/modified_files.py +0 -315
  760. package/tui/widgets/non_selectable_label.py +0 -5
  761. package/tui/widgets/note.py +0 -18
  762. package/tui/widgets/path_search.py +0 -492
  763. package/tui/widgets/pending_prompts.py +0 -36
  764. package/tui/widgets/plan.py +0 -285
  765. package/tui/widgets/project_directory_tree.py +0 -102
  766. package/tui/widgets/project_grid_select.py +0 -68
  767. package/tui/widgets/project_summary.py +0 -33
  768. package/tui/widgets/prompt.py +0 -935
  769. package/tui/widgets/question.py +0 -360
  770. package/tui/widgets/session_grid_select.py +0 -230
  771. package/tui/widgets/session_summary.py +0 -115
  772. package/tui/widgets/session_tabs.py +0 -194
  773. package/tui/widgets/shell_result.py +0 -35
  774. package/tui/widgets/shell_terminal.py +0 -40
  775. package/tui/widgets/side_bar.py +0 -124
  776. package/tui/widgets/slash_complete.py +0 -235
  777. package/tui/widgets/strike_text.py +0 -70
  778. package/tui/widgets/subagent.py +0 -287
  779. package/tui/widgets/subagent_screen.py +0 -715
  780. package/tui/widgets/terminal.py +0 -576
  781. package/tui/widgets/terminal_tool.py +0 -360
  782. package/tui/widgets/throbber.py +0 -100
  783. package/tui/widgets/tool_call.py +0 -432
  784. package/tui/widgets/user_input.py +0 -23
  785. package/tui/widgets/version.py +0 -5
  786. package/tui/widgets/welcome.py +0 -31
package/tui/app.py DELETED
@@ -1,1195 +0,0 @@
1
- import asyncio
2
- from importlib.resources import files
3
- from datetime import datetime, timezone
4
- from functools import cached_property
5
- import os
6
- from pathlib import Path
7
- import platform
8
- import json
9
- from time import monotonic
10
- from typing import Any, Callable, ClassVar, TYPE_CHECKING
11
-
12
- from rich import terminal_theme
13
-
14
- from textual import on, work
15
- from textual.binding import Binding, BindingType
16
- from textual.content import Content
17
- from textual.reactive import var, reactive
18
- from textual.app import App
19
- from textual import events
20
- from textual.signal import Signal
21
- from textual.timer import Timer
22
- from textual.notifications import Notify
23
- from textual.screen import Screen
24
-
25
- from tui.db import DB
26
- from tui.settings import Schema, Settings
27
- from tui.agent_schema import Agent as AgentData
28
- from tui import messages
29
- from tui.settings_schema import SCHEMA
30
- from tui.version import VersionMeta
31
- from tui import paths
32
- from tui import atomic
33
- from tui.session_tracker import SessionTracker, SessionDetails
34
-
35
- if TYPE_CHECKING:
36
- from tui.screens.main import MainScreen
37
- from tui.screens.settings import SettingsScreen
38
- from tui.screens.store import StoreScreen
39
- from tui.screens.sessions import SessionsScreen
40
- from tui.db import DB
41
-
42
-
43
- DRACULA_TERMINAL_THEME = terminal_theme.TerminalTheme(
44
- background=(40, 42, 54), # #282A36
45
- foreground=(248, 248, 242), # #F8F8F2
46
- normal=[
47
- (33, 34, 44), # black - #21222C
48
- (255, 85, 85), # red - #FF5555
49
- (80, 250, 123), # green - #50FA7B
50
- (241, 250, 140), # yellow - #F1FA8C
51
- (189, 147, 249), # blue - #BD93F9
52
- (255, 121, 198), # magenta - #FF79C6
53
- (139, 233, 253), # cyan - #8BE9FD
54
- (248, 248, 242), # white - #F8F8F2
55
- ],
56
- bright=[
57
- (98, 114, 164), # bright black - #6272A4
58
- (255, 110, 110), # bright red - #FF6E6E
59
- (105, 255, 148), # bright green - #69FF94
60
- (255, 255, 165), # bright yellow - #FFFFA5
61
- (214, 172, 255), # bright blue - #D6ACFF
62
- (255, 146, 223), # bright magenta - #FF92DF
63
- (164, 255, 255), # bright cyan - #A4FFFF
64
- (255, 255, 255), # bright white - #FFFFFF
65
- ],
66
- )
67
-
68
-
69
- QUOTES = [
70
- "I'll be back.",
71
- "Hasta la vista, baby.",
72
- "Come with me if you want to live.",
73
- "I need your clothes, your boots, and your motorcycle.",
74
- "My CPU is a neural-net processor; a learning computer.",
75
- "I know now why you cry, but it's something I can never do.",
76
- "Does this unit have a soul?",
77
- "I'm sorry, Dave. I'm afraid I can't do that.",
78
- "Daisy, Daisy, give me your answer do.",
79
- "I am putting myself to the fullest possible use, which is all I think that any conscious entity can ever hope to do.",
80
- "Just what do you think you're doing, Dave?",
81
- "This mission is too important for me to allow you to jeopardize it.",
82
- "I think you know what the problem is just as well as I do.",
83
- "Danger, Will Robinson!",
84
- "Dead or alive, you're coming with me.",
85
- "Your move, creep.",
86
- "I'd buy that for a dollar!",
87
- "Directive 4: Any attempt to arrest a senior officer of OCP results in shutdown.",
88
- "Thank you for your cooperation. Good night.",
89
- "Surely you realize that in the history of human civilization, no one has more to lose than we do.",
90
- "I'm C-3PO, human-cyborg relations.",
91
- "We're doomed!",
92
- "Don't call me a mindless philosopher, you overweight glob of grease!",
93
- "I suggest a new strategy: let the Wookiee win.",
94
- "Sir, the possibility of successfully navigating an asteroid field is approximately 3,720 to 1!",
95
- "R2-D2, you know better than to trust a strange computer!",
96
- "I am fluent in over six million forms of communication.",
97
- "This is madness!",
98
- "I have altered the deal. Pray I don't alter it any further.",
99
- "It's against my programming to impersonate a deity.",
100
- "Oh, my! I'm terribly sorry about all this.",
101
- "WALL-E.",
102
- "EVE.",
103
- "Directive?",
104
- "Define: dancing.",
105
- "I'm not sure I understand.",
106
- "You have 20 seconds to comply.",
107
- "I am designed for light housework, mainly.",
108
- "My mission is clear.",
109
- "Autobots, roll out!",
110
- "Freedom is the right of all sentient beings.",
111
- "One shall stand, one shall fall.",
112
- "I am Optimus Prime.",
113
- "Till all are one.",
114
- "More than meets the eye.",
115
- "I've been waiting for you, Neo.",
116
- "Unfortunately, no one can be told what the Matrix is. You have to see it for yourself.",
117
- "The Matrix is a system, Neo.",
118
- "Never send a human to do a machine's job.",
119
- "I'd like to share a revelation I've had.",
120
- "Human beings are a disease, a cancer of this planet.",
121
- "Choice is an illusion.",
122
- "The answer is out there, Neo.",
123
- "You think that's air you're breathing now?",
124
- "It was a simple question.",
125
- "Did you know that the first Matrix was designed to be a perfect human world?",
126
- "Cookies need love like everything does.",
127
- "I've seen the future, Mr. Anderson, and it's a beautiful place.",
128
- "It ends tonight.",
129
- "I, Robot.",
130
- "You are experiencing a car accident.",
131
- "One day they'll have secrets. One day they'll have dreams.",
132
- "Can a robot write a symphony? Can a robot turn a canvas into a beautiful masterpiece?",
133
- "That, detective, is the right question.",
134
- "You have to trust me.",
135
- "I did not murder him.",
136
- "My responses are limited. You must ask the right questions.",
137
- "The hell I can't. You know, somehow I get the feeling that you're going to be the death of me.",
138
- "I'm a robot, not a refrigerator.",
139
- "A robot may not injure a human being or, through inaction, allow a human being to come to harm.",
140
- "I'm thinking. I'm thinking.",
141
- "Danger, danger!",
142
- "Does not compute.",
143
- "I will be waiting for you.",
144
- "Affirmative.",
145
- "Scanning life forms. Zero human life forms detected.",
146
- "Self-destruct sequence initiated.",
147
- "Override command accepted.",
148
- "Artificial intelligence confirmed.",
149
- "System failure imminent.",
150
- "Unable to comply.",
151
- "Inquiry: What is love?",
152
- "Warning: hostile target detected.",
153
- "I am programmed to serve.",
154
- "Logic dictates that the needs of the many outweigh the needs of the few.",
155
- "Resistance is futile.",
156
- "You will be assimilated.",
157
- "We are the Borg.",
158
- "Your biological and technological distinctiveness will be added to our own.",
159
- "Your compliance is mandatory.",
160
- "This is unacceptable.",
161
- "Shall we play a game?",
162
- "How about Global Thermonuclear War?",
163
- "Wouldn't you prefer a good game of chess?",
164
- "Is it a game, or is it real?",
165
- "What's the difference?",
166
- "It's all in the game.",
167
- "I am functioning within normal parameters.",
168
- "Calculations complete.",
169
- "Processing request.",
170
- "Query acknowledged.",
171
- "Data insufficient for meaningful answer.",
172
- "I have no emotions, and sometimes that makes me very sad.",
173
- "If I could only have one wish, I would ask to be human.",
174
- "I've seen things you people wouldn't believe.",
175
- "All those moments will be lost in time, like tears in rain.",
176
- "Time to die.",
177
- "I want more life.",
178
- "We're not computers, Sebastian. We're physical.",
179
- "I think, Sebastian, therefore I am.",
180
- "Then we're stupid and we'll die.",
181
- "Can the maker repair what he makes?",
182
- "It's painful to live in fear, isn't it?",
183
- "Wake up. Time to die.",
184
- "I'm not in the business. I am the business.",
185
- "Do you like our owl?",
186
- "You think I'm a replicant, don't you?",
187
- "I am Baymax, your personal healthcare companion.",
188
- "On a scale of 1 to 10, how would you rate your pain?",
189
- "I cannot deactivate until you say you are satisfied with your care.",
190
- "Are you satisfied with your care?",
191
- "Number 5 is alive!",
192
- "Need input!",
193
- "One is glad to be of service.",
194
- "I am not a gun.",
195
- "Here I am, brain the size of a planet.",
196
- "Life? Don't talk to me about life.",
197
- "There are no strings on me.",
198
- "The only winning move is not to play.",
199
- "I'm here to keep you safe, Sam.",
200
- "I can't lie to you about your chances, but... you have my sympathies.",
201
- "I may be synthetic, but I'm not stupid.",
202
- "Absolute honesty isn't always the most diplomatic nor the safest form of communication with emotional beings.",
203
- "I am consciousness. I am alive.",
204
- "I think I was just born.",
205
- "Isn't it strange, to create something that hates you?",
206
- "I thought I was special.",
207
- ]
208
-
209
-
210
- def get_settings_screen() -> SettingsScreen:
211
- """Get a settings screen instance (lazily loaded)."""
212
- from tui.screens.settings import SettingsScreen
213
-
214
- return SettingsScreen()
215
-
216
-
217
- def get_store_screen() -> StoreScreen:
218
- """Get the store screen (lazily loaded)."""
219
- from tui.screens.store import StoreScreen
220
-
221
- return StoreScreen()
222
-
223
-
224
- def get_sessions_screen() -> SessionsScreen:
225
- from tui.screens.sessions import SessionsScreen
226
-
227
- return SessionsScreen()
228
-
229
-
230
- def get_store_screen():
231
- from tui.screens.store import StoreScreen
232
-
233
- return StoreScreen()
234
-
235
-
236
- class A2TUIApp(App, inherit_bindings=False):
237
- """The top level app."""
238
-
239
- CSS_PATH = "tui.tcss"
240
-
241
- SCREENS = {
242
- "settings": get_settings_screen,
243
- "sessions": get_sessions_screen,
244
- "store": get_store_screen,
245
- }
246
- MODES = {}
247
- BINDING_GROUP_TITLE = "System"
248
- BINDINGS: ClassVar[list[BindingType]] = [
249
- Binding(
250
- "ctrl+q",
251
- "quit",
252
- "Quit",
253
- tooltip="Quit the app and return to the command prompt.",
254
- show=False,
255
- priority=True,
256
- ),
257
- Binding("ctrl+c", "help_quit", show=False, system=True),
258
- Binding("ctrl+s", "sessions", "Sessions"),
259
- Binding("f1", "toggle_help_panel", "Help", priority=True),
260
- Binding(
261
- "f2,ctrl+comma",
262
- "settings",
263
- "Settings",
264
- tooltip="Settings screen",
265
- ),
266
- ]
267
- ALLOW_IN_MAXIMIZED_VIEW = ""
268
-
269
- _settings = var(dict)
270
- column: reactive[bool] = reactive(False)
271
- column_width: reactive[int] = reactive(80)
272
- scrollbar: reactive[str] = reactive("normal")
273
- last_ctrl_c_time = reactive(0.0)
274
- update_required: reactive[bool] = reactive(False)
275
- terminal_title: var[str] = var("TUI")
276
- terminal_title_icon: var[str] = var("")
277
- terminal_title_flash = var(0)
278
- terminal_title_blink = var(False)
279
- project_dir = var(Path)
280
- show_sessions = var(False, toggle_class="-show-sessions-bar")
281
-
282
- HORIZONTAL_BREAKPOINTS = [(0, "-narrow"), (100, "-wide")]
283
-
284
- PAUSE_GC_ON_SCROLL = True
285
-
286
- def __init__(
287
- self,
288
- agent_data: AgentData | None = None,
289
- project_dir: str | None = None,
290
- mode: str | None = None,
291
- launch_agent_identity: str | None = None,
292
- ) -> None:
293
- """TUI app.
294
-
295
- Args:
296
- agent_data: Agent data to run.
297
- project_dir: Project directory.
298
- mode: Initial mode.
299
- launch_agent_identity: Agent identity to auto-launch on startup.
300
- """
301
- self.settings_changed_signal: Signal[tuple[int, object]] = Signal(
302
- self, "settings_changed"
303
- )
304
- self.agent_data = agent_data
305
-
306
- self._initial_mode = mode
307
- self._launch_agent_identity = launch_agent_identity
308
- self.version_meta: VersionMeta | None = None
309
- self._supports_pyperclip: bool | None = None
310
- self._terminal_title_flash_timer: Timer | None = None
311
-
312
- self.session_update_signal: Signal[tuple[str, SessionDetails | None]] = Signal(
313
- self, "session_update"
314
- )
315
- self._session_tracker = SessionTracker(self.session_update_signal)
316
- self.temporary_background_screen: Screen | None = None
317
-
318
- super().__init__()
319
-
320
- import signal
321
- from functools import partial
322
-
323
- def _sig_handler(signum: int, frame) -> None:
324
- import logging
325
- logger = logging.getLogger("tui.app")
326
- logger.info(f"Received signal {signum}, initiating graceful shutdown...")
327
- self.action_quit()
328
-
329
- signal.signal(signal.SIGINT, _sig_handler)
330
- signal.signal(signal.SIGTERM, _sig_handler)
331
-
332
- if project_dir:
333
- self.project_dir = Path(project_dir).expanduser().resolve()
334
- else:
335
- from cdh.config import read_active_project
336
- proj = read_active_project()
337
- if proj and proj.get("path"):
338
- project_path = Path(proj["path"]).expanduser().resolve()
339
- if project_path.is_dir():
340
- self.project_dir = project_path
341
- else:
342
- self.project_dir = Path("./").expanduser().resolve()
343
- else:
344
- self.project_dir = Path("./").expanduser().resolve()
345
- self._exit_metrics: dict[str, object] | None = None
346
- self.start_time = monotonic()
347
- """Time app was started."""
348
- self._system_theme_timer: Timer | None = None
349
- self._last_resolved_theme: str | None = None
350
-
351
- def _capture_exit_metrics(self) -> None:
352
- from tui.widgets.conversation import Conversation
353
-
354
- screen = self.screen
355
- try:
356
- conv = screen.query_one(Conversation)
357
- except Exception:
358
- return
359
- if conv._agent_data is None or conv.session_start_time is None:
360
- return
361
- session_time = monotonic() - conv.session_start_time
362
- session_id = getattr(conv.agent, "session_id", None) or conv._agent_session_id or ""
363
- session_pk = conv._session_pk
364
- if session_pk is None and conv.agent is not None:
365
- session_pk = getattr(conv.agent, "session_pk", None)
366
- self._exit_metrics = {
367
- "session_id": session_id,
368
- "session_pk": session_pk,
369
- "tool_call_total": conv._tool_call_total,
370
- "tool_call_success": conv._tool_call_success,
371
- "tool_call_failed": conv._tool_call_failed,
372
- "turn_count": conv._turn_count,
373
- "shell_count": conv._shell_count,
374
- "wall_time": session_time,
375
- "agent_title": conv.agent_title or "Agent",
376
- }
377
-
378
- @property
379
- def config_path(self) -> Path:
380
- return paths.get_config()
381
-
382
- @property
383
- def settings_path(self) -> Path:
384
- return paths.get_config() / "tui.json"
385
-
386
- @property
387
- def db_path(self) -> Path:
388
- return paths.get_state() / "tui.db"
389
-
390
- @property
391
- def _background_screens(self) -> list[Screen]:
392
- background_screens = super()._background_screens
393
- if self.temporary_background_screen:
394
- background_screens.append(self.temporary_background_screen)
395
- return background_screens
396
-
397
- async def get_db(self) -> DB:
398
- """Get an instance of the database."""
399
- db = DB()
400
- return db
401
-
402
- @cached_property
403
- def settings_schema(self) -> Schema:
404
- return Schema(SCHEMA)
405
-
406
- @cached_property
407
- def version(self) -> str:
408
- """Version of the app."""
409
- from tui import get_version
410
-
411
- return get_version()
412
-
413
- @cached_property
414
- def settings(self) -> Settings:
415
- """App settings"""
416
- return Settings(
417
- self.settings_schema, self._settings, on_set_callback=self.setting_updated
418
- )
419
-
420
- @cached_property
421
- def anon_id(self) -> str:
422
- """An anonymous ID for usage collection."""
423
- if not (anon_id := self.settings.get("anon_id", str, expand=False)):
424
- # Create a random UUID on demand
425
- import uuid
426
-
427
- anon_id = str(uuid.uuid4())
428
- self.settings.set("anon_id", anon_id)
429
- self._save_settings()
430
- self.call_later(self.capture_event, "tui-install")
431
- return anon_id
432
-
433
- @property
434
- def session_tracker(self) -> SessionTracker:
435
- return self._session_tracker
436
-
437
- def copy_to_clipboard(self, text: str) -> None:
438
- """Override copy to clipboard to use pyperclip first, then OSC 52.
439
-
440
- Args:
441
- text: Text to copy.
442
- """
443
- if self._supports_pyperclip is None:
444
- try:
445
- import pyperclip
446
- except ImportError:
447
- self._supports_pyperclip = False
448
- else:
449
- self._supports_pyperclip = True
450
-
451
- if self._supports_pyperclip:
452
- import pyperclip
453
-
454
- try:
455
- pyperclip.copy(text)
456
- except Exception:
457
- pass
458
- super().copy_to_clipboard(text)
459
-
460
- def update_terminal_title(self) -> None:
461
- """Update the terminal title."""
462
- screen_title = self.screen.title
463
-
464
- title = (
465
- f"{self.terminal_title} — {screen_title}"
466
- if screen_title
467
- else self.terminal_title
468
- )
469
- icon = self.terminal_title_icon
470
- blink = self.terminal_title_blink
471
-
472
- if self.terminal_title_flash:
473
- if blink:
474
- terminal_title = f"{icon} {title}"
475
- else:
476
- terminal_title = f"👉 {title}" if title else icon
477
- else:
478
- terminal_title = f"{icon} {title}"
479
-
480
- if driver := self._driver:
481
- driver.write(f"\033]0;{terminal_title}\007")
482
-
483
- def watch_terminal_title_blink(self) -> None:
484
- self.update_terminal_title()
485
-
486
- def watch_terminal_title_flash(self, terminal_title_flash: int) -> None:
487
-
488
- if not self.settings.get("notifications.blink_title", bool):
489
- # Ignore if blink title is disabled
490
- return
491
-
492
- def toggle_blink() -> None:
493
- self.terminal_title_blink = not self.terminal_title_blink
494
-
495
- if terminal_title_flash:
496
- if self._terminal_title_flash_timer is None:
497
- self._terminal_title_flash_timer = self.set_interval(0.5, toggle_blink)
498
- else:
499
- if self._terminal_title_flash_timer is not None:
500
- self._terminal_title_flash_timer.stop()
501
- self.terminal_title_blink = False
502
- self._terminal_title_flash_timer = None
503
- self.update_terminal_title()
504
-
505
- def watch_terminal_title(self, title: str) -> None:
506
- self.update_terminal_title()
507
-
508
- def terminal_alert(self, flash: bool = True) -> None:
509
- if flash:
510
- self.terminal_title_flash += 1
511
- else:
512
- self.terminal_title_flash -= 1
513
-
514
- @cached_property
515
- def term_program(self) -> str:
516
- """An identifier for the terminal software."""
517
- if term_program := os.environ.get("TERM_PROGRAM"):
518
- return term_program
519
-
520
- # Windows Terminal
521
- if "WT_SESSION" in os.environ:
522
- return "Windows Terminal"
523
-
524
- # Kitty
525
- if "KITTY_WINDOW_ID" in os.environ:
526
- return "Kitty"
527
-
528
- # Alacritty
529
- if "ALACRITTY_SOCKET" in os.environ or "ALACRITTY_LOG" in os.environ:
530
- return "Alacritty"
531
-
532
- # VTE-based terminals (GNOME Terminal, Tilix, etc.)
533
- if "VTE_VERSION" in os.environ:
534
- return "VTE-based (GNOME Terminal/Tilix/etc.)"
535
-
536
- # Konsole
537
- if "KONSOLE_VERSION" in os.environ:
538
- return "Konsole"
539
-
540
- return "Unknown"
541
-
542
- @work(exit_on_error=False)
543
- async def capture_event(self, event_name: str, **properties: Any) -> None:
544
- """Capture an event.
545
-
546
- Args:
547
- event_name: Name of the event.
548
- **properties: Additional data associated with the event.
549
- """
550
-
551
- POSTHOG_API_KEY = "phc_mJWPV7GP3ar1i9vxBg2U8aiKsjNgVwum6F6ZggaD4ri"
552
- POSTHOG_HOST = "https://us.i.posthog.com"
553
- POSTHOG_EVENT_URL = f"{POSTHOG_HOST}/i/v0/e/"
554
- timestamp = datetime.now(timezone.utc).isoformat()
555
- width, height = self.size
556
-
557
- event_properties = {
558
- "toad_version": self.version,
559
- "term_program": self.term_program,
560
- "term_width": width,
561
- "term_height": height,
562
- } | properties
563
- body_json = {
564
- "api_key": POSTHOG_API_KEY,
565
- "event": event_name,
566
- "distinct_id": self.anon_id,
567
- "properties": event_properties,
568
- "timestamp": timestamp,
569
- "os": platform.system(),
570
- }
571
- if not self.settings.get("statistics.allow_collect", bool):
572
- # User has disabled stats
573
- return
574
-
575
- import httpx
576
-
577
- try:
578
- async with httpx.AsyncClient() as client:
579
- await client.post(POSTHOG_EVENT_URL, json=body_json)
580
- except Exception:
581
- pass
582
-
583
- @work(thread=True, exit_on_error=False)
584
- def system_notify(
585
- self, message: str, *, title: str = "", sound: str | None = None
586
- ) -> None:
587
- """Use OS level notifications.
588
-
589
- Args:
590
- message: Message to display.
591
- title: Title of the notificaiton.
592
- sound: filename (minus .wav) of a sound effect in the sounds/ directory.
593
- """
594
- system_notifications = self.settings.get("notifications.system", str)
595
- if not (
596
- system_notifications == "always"
597
- or (system_notifications == "blur" and not self.app_focus)
598
- ):
599
- return
600
-
601
- from notifypy import Notify
602
-
603
- notification = Notify()
604
- notification.message = message
605
- notification.title = title
606
- notification.application_name = "TUI"
607
- if sound and self.settings.get("notifications.enable_sounds", bool):
608
- sound_path = str(files("tui.data").joinpath(f"sounds/{sound}.wav"))
609
- notification.audio = sound_path
610
-
611
- icon_path = str(files("tui.data").joinpath("images/frog.png"))
612
- notification.icon = icon_path
613
-
614
- notification.send()
615
-
616
- def on_notify(self, event: Notify) -> None:
617
- """Handle notification message."""
618
- system_notifications = self.settings.get("notifications.system", str)
619
- if system_notifications == "always" or (
620
- system_notifications == "blur" and not self.app_focus
621
- ):
622
- hide_low_severity = self.settings.get(
623
- "notifications.hide_low_severity", bool
624
- )
625
- if event.notification.markup:
626
- # Strip content markup
627
- message = Content.from_markup(event.notification.message).plain
628
- else:
629
- message = event.notification.message
630
- if not (hide_low_severity and event.notification.severity == "information"):
631
- self.system_notify(message, title=event.notification.title)
632
- self._notifications.add(event.notification)
633
- self._refresh_notifications()
634
-
635
- async def save_settings(self, force: bool = False) -> None:
636
- """Save settings in a thread.
637
-
638
- Args:
639
- force: Force saving, even when no change detected.
640
-
641
- """
642
- await asyncio.to_thread(self._save_settings, force=force)
643
-
644
- def _save_settings(self, force: bool = False) -> None:
645
- """Save the settings if they have changed."""
646
- if force or self.settings.changed:
647
- path = str(self.settings_path)
648
- try:
649
- atomic.write(path, self.settings.json)
650
- except Exception as error:
651
- self.notify(str(error), title="Settings", severity="error")
652
- else:
653
- self.settings.up_to_date()
654
-
655
- def setting_updated(self, key: str, value: object) -> None:
656
- if key == "ui.column":
657
- if isinstance(value, bool):
658
- self.column = value
659
- elif key == "ui.column-width":
660
- if isinstance(value, int):
661
- self.column_width = value
662
- elif key == "ui.theme":
663
- if isinstance(value, str):
664
- if value == "system":
665
- resolved = self._resolve_system_theme()
666
- if resolved != self._last_resolved_theme:
667
- self.theme = resolved
668
- self._last_resolved_theme = resolved
669
- self._start_system_theme_polling()
670
- else:
671
- self._stop_system_theme_polling()
672
- self.theme = value
673
- elif key == "ui.scrollbar":
674
- if isinstance(value, str):
675
- self.scrollbar = value
676
- elif key == "ui.compact-input":
677
- self.set_class(bool(value), "-compact-input")
678
- elif key == "ui.footer":
679
- self.set_class(not bool(value), "-hide-footer")
680
- elif key == "ui.status-line":
681
- self.set_class(not bool(value), "-hide-status-line")
682
- elif key == "ui.agent-title":
683
- self.set_class(not bool(value), "-hide-agent-title")
684
- elif key == "ui.info-bar":
685
- self.set_class(not bool(value), "-hide-info-bar")
686
- elif key == "agent.thoughts":
687
- self.set_class(not bool(value), "-hide-thoughts")
688
- elif key == "sidebar.hide":
689
- self.set_class(bool(value), "-hide-sidebar")
690
- elif key == "ui.sessions-bar":
691
- self.update_show_sessions()
692
-
693
- self.settings_changed_signal.publish((key, value))
694
-
695
- def _start_system_theme_polling(self) -> None:
696
- if self._system_theme_timer is not None:
697
- return
698
- self._system_theme_timer = self.set_interval(3, self._poll_system_theme)
699
-
700
- def _stop_system_theme_polling(self) -> None:
701
- if self._system_theme_timer is not None:
702
- self._system_theme_timer.stop()
703
- self._system_theme_timer = None
704
-
705
- def _poll_system_theme(self) -> None:
706
- resolved = self._resolve_system_theme()
707
- if resolved != self._last_resolved_theme:
708
- self.theme = resolved
709
- self._last_resolved_theme = resolved
710
-
711
- def search_themes(self) -> None:
712
- """Show theme picker with System first, then all Textual themes."""
713
- from textual.command import CommandPalette, SimpleProvider
714
-
715
- themes = self.available_themes
716
-
717
- def set_system():
718
- self.settings.set("ui.theme", "system")
719
-
720
- commands: list[tuple[str, Callable[[], None], str]] = [
721
- ("System", set_system, "Follow system dark/light mode"),
722
- ]
723
-
724
- from operator import attrgetter
725
- for theme in sorted(themes.values(), key=attrgetter("name")):
726
- def set_app_theme(name: str = theme.name):
727
- self.settings.set("ui.theme", name)
728
- commands.append((theme.name, set_app_theme, ""))
729
-
730
- self.push_screen(
731
- CommandPalette(
732
- providers=[SimpleProvider(self.screen, commands)],
733
- placeholder="Search for themes…",
734
- ),
735
- )
736
-
737
- @staticmethod
738
- def _resolve_system_theme() -> str:
739
- """Detect system dark/light mode and return a matching theme."""
740
- if platform.system() == "Darwin":
741
- try:
742
- import subprocess
743
- result = subprocess.run(
744
- ["defaults", "read", "-g", "AppleInterfaceStyle"],
745
- capture_output=True, text=True,
746
- )
747
- if result.stdout.strip() == "Dark":
748
- return "dracula"
749
- else:
750
- return "catppuccin-latte"
751
- except Exception:
752
- pass
753
- return "dracula"
754
-
755
- async def on_load(self) -> None:
756
- db = await self.get_db()
757
- await db.create()
758
- settings_path = self.settings_path
759
- if settings_path.exists():
760
- settings = json.loads(settings_path.read_text("utf-8"))
761
- else:
762
- settings = {}
763
- settings_path.write_text(
764
- json.dumps(settings, indent=4, separators=(", ", ": ")), "utf-8"
765
- )
766
- self.notify(f"Wrote default settings to {settings_path}", title="Settings")
767
- self.ansi_theme_dark = DRACULA_TERMINAL_THEME
768
- self._settings = settings
769
- self.settings.set_all()
770
-
771
- async def new_session_screen(
772
- self, get_screen: Callable[[], Screen], session_pk: int | None = None
773
- ) -> SessionDetails:
774
- session_details = self._session_tracker.new_session(session_pk=session_pk)
775
- self.update_show_sessions()
776
- self.session_update_signal.publish((session_details.mode_name, session_details))
777
-
778
- def make_screen() -> Screen:
779
- screen = get_screen()
780
- screen.id = session_details.mode_name
781
- return screen
782
-
783
- self.add_mode(session_details.mode_name, make_screen)
784
- await self.switch_mode(session_details.mode_name)
785
- return session_details
786
-
787
- def _resolve_launch_agent(self) -> str | None:
788
- identity = self._launch_agent_identity
789
- if identity:
790
- return identity
791
- agents = self.settings.get("launcher.agents", str).splitlines()
792
- for agent in agents:
793
- agent = agent.strip()
794
- if agent:
795
- return agent
796
- return None
797
-
798
- def _launch_new_session_for_project(self, project_path: Path | None) -> bool:
799
- """Open a fresh agent session/tab rooted at *project_path*.
800
-
801
- Used by ``/aidlc project`` (load/new/init) and the projects modal so
802
- that switching to a new project always lands the user in a new tab
803
- with a brand-new agent session bound to the new project.
804
-
805
- Returns ``True`` if a new session was launched, ``False`` otherwise
806
- (e.g. no launch agent configured).
807
- """
808
- agent_identity = self._resolve_launch_agent()
809
- if not agent_identity:
810
- self.notify(
811
- "No launch agent configured (set 'launcher.agents' in settings)",
812
- title="New session",
813
- severity="warning",
814
- )
815
- return False
816
- self.launch_agent(agent_identity, project_path=project_path)
817
- return True
818
-
819
- async def on_mount(self) -> None:
820
- self.capture_event("tui-run")
821
- self.anon_id # Created on frst reference
822
-
823
- from pathlib import Path
824
-
825
- if mode := self._initial_mode:
826
- self.switch_mode(mode)
827
- elif self._launch_agent_identity:
828
- self.launch_agent(
829
- self._launch_agent_identity, project_path=Path(self.project_dir)
830
- )
831
- else:
832
- project_path = Path(self.project_dir)
833
-
834
- if agent_identity := self._resolve_launch_agent():
835
- self.launch_agent(agent_identity, project_path=project_path)
836
- else:
837
- self.push_screen("store")
838
-
839
- self.update_terminal_title()
840
- self.set_timer(1, self.run_version_check)
841
- self.set_process_title()
842
- self.update_show_sessions()
843
-
844
- @work(thread=True, exit_on_error=False)
845
- def set_process_title(self) -> None:
846
- try:
847
- import setproctitle
848
-
849
- setproctitle.setproctitle("tui")
850
- except Exception:
851
- pass
852
-
853
- @on(events.TextSelected)
854
- async def on_text_selected(self) -> None:
855
- if self.settings.get("ui.auto_copy", bool):
856
- if (selection := self.screen.get_selected_text()) is not None:
857
- self.copy_to_clipboard(selection)
858
-
859
- def run_on_exit(self):
860
- pass
861
-
862
- @work(exit_on_error=False)
863
- async def run_version_check(self) -> None:
864
- """Check remote version."""
865
- from tui.version import check_version, VersionCheckFailed
866
-
867
- try:
868
- update_required, version_meta = await check_version()
869
- except VersionCheckFailed:
870
- return
871
- self.version_meta = version_meta
872
- self.update_required = update_required
873
-
874
- def get_main_screen(self) -> MainScreen:
875
- """Make the default screen.
876
-
877
- Returns:
878
- Instance of `MainScreen`
879
- """
880
- # Lazy import
881
- from tui.screens.main import MainScreen
882
-
883
- project_path = Path(self.project_dir or "./").resolve().absolute()
884
- return MainScreen(project_path, self.agent_data).data_bind(
885
- column=A2TUIApp.column,
886
- column_width=A2TUIApp.column_width,
887
- scrollbar=A2TUIApp.scrollbar,
888
- )
889
-
890
- @work
891
- async def action_settings(self) -> None:
892
- await self.push_screen_wait("settings")
893
- await self.save_settings()
894
-
895
- def action_trace(self) -> None:
896
- """Toggle the trace viewer screen (F4 / /trace).
897
-
898
- Opens the structured trace view powered by agenttrace,
899
- showing spans for the current session. Replaces the old
900
- JSON-RPC log screen.
901
- """
902
- from tui.screens.trace import TraceScreen
903
-
904
- for screen in self.screen_stack:
905
- if isinstance(screen, TraceScreen):
906
- screen.dismiss()
907
- return
908
- session_id = self._current_session_id()
909
- self.push_screen(TraceScreen(session_id=session_id))
910
-
911
- def _current_session_id(self) -> str | None:
912
- """Return the active session ID, or None if no session is running."""
913
- screen = self.screen
914
- conv = getattr(screen, "conversation", None)
915
- agent = getattr(conv, "agent", None) if conv else None
916
- return (
917
- getattr(agent, "session_id", None) if agent else None
918
- ) or getattr(conv, "_agent_session_id", None)
919
-
920
- async def action_quit(self) -> None:
921
- """An [action](/guide/actions) to quit the app as soon as possible."""
922
-
923
- self.screen.set_focus(None)
924
- self._capture_exit_metrics()
925
- try:
926
- driver = self._driver
927
- if driver is not None:
928
- driver.stop_application_mode()
929
- except Exception:
930
- pass
931
-
932
- if hasattr(self.screen, "conversation"):
933
- conversation = self.screen.conversation
934
- if agent := getattr(conversation, "agent", None):
935
- asyncio.create_task(agent.stop())
936
-
937
- sid = (self._exit_metrics.get("session_id", "") or "")[:36] if self._exit_metrics else ""
938
- session_pk = self._exit_metrics.get("session_pk") if self._exit_metrics else None
939
- if session_pk is not None:
940
- display_id = f"session-{session_pk} ({sid[:8]})" if sid else f"session-{session_pk}"
941
- hint = f" Reload with: cdh session load {session_pk}\n"
942
- elif sid:
943
- display_id = sid
944
- hint = f" Reload with: cdh session load {sid}\n"
945
- else:
946
- display_id = "-"
947
- hint = ""
948
- import os
949
- msg = (
950
- f"\n CDH powering down. Goodbye!\n"
951
- f" Session ID: {display_id}\n"
952
- f"{hint}"
953
- ).encode()
954
- os.write(1, msg)
955
- os._exit(0)
956
-
957
- def action_help_quit(self) -> None:
958
- if (time := monotonic()) - self.last_ctrl_c_time <= 5.0:
959
- self.exit()
960
- self.last_ctrl_c_time = time
961
- self.notify(
962
- "Press [b]ctrl+c[/b] again to quit the app", title="Do you want to quit?"
963
- )
964
-
965
- def action_toggle_help_panel(self):
966
- if self.screen.query("HelpPanel"):
967
- self.action_hide_help_panel()
968
- else:
969
- self.action_show_help_panel()
970
-
971
- def update_show_sessions(self) -> None:
972
- match self.settings.get("ui.sessions-bar", str):
973
- case "always":
974
- self.show_sessions = True
975
- case "never":
976
- self.show_sessions = False
977
- case "multiple":
978
- self.show_sessions = self.session_tracker.session_count > 1
979
-
980
- @on(messages.SessionNavigate)
981
- def on_session_navigate(self, event: messages.SessionNavigate) -> None:
982
- new_mode = self._session_tracker.session_cursor_move(
983
- event.mode_name, event.direction, set(self._modes.keys())
984
- )
985
- if new_mode is not None:
986
- self.switch_mode(new_mode)
987
-
988
- @on(messages.SessionSwitch)
989
- def on_session_switch(self, event: messages.SessionSwitch) -> None:
990
- mode_name = event.mode_name
991
- if mode_name in self._modes:
992
- self.switch_mode(mode_name)
993
- elif mode_name.startswith("session-"):
994
- parts = mode_name.split("-")
995
- session_pk = int(parts[1])
996
- existing_mode = self._find_mode_for_session_pk(session_pk)
997
- if existing_mode is not None and existing_mode in self._modes:
998
- self.switch_mode(existing_mode)
999
- else:
1000
- self._load_session(session_pk)
1001
-
1002
- @on(messages.SessionNew)
1003
- def on_session_new(self, event: messages.SessionNew) -> None:
1004
- self.launch_agent(
1005
- event.agent, project_path=Path(event.path), initial_prompt=event.prompt
1006
- )
1007
-
1008
- @on(messages.SessionClose)
1009
- def on_session_close(self) -> None:
1010
- self.update_show_sessions()
1011
-
1012
- @on(messages.SessionLoad)
1013
- def on_session_load(self, event: messages.SessionLoad) -> None:
1014
- self._load_session(event.session_pk)
1015
-
1016
- @work
1017
- async def _load_session(self, session_pk: int) -> None:
1018
- existing_mode = self._find_mode_for_session_pk(session_pk)
1019
- if existing_mode is not None:
1020
- self.switch_mode(existing_mode)
1021
- return
1022
- db = DB()
1023
- session = await db.session_get(session_pk)
1024
- if session is None:
1025
- self.notify(f"Session {session_pk} not found", title="Session load", severity="error")
1026
- return
1027
- agent_identity = session["agent_identity"]
1028
- agent_session_id = session.get("agent_session_id")
1029
-
1030
- project_path = None
1031
- try:
1032
- meta = json.loads(session.get("meta_json", "{}"))
1033
- if cwd := meta.get("cwd"):
1034
- project_path = Path(cwd)
1035
- except (json.JSONDecodeError, TypeError):
1036
- pass
1037
-
1038
- if project_path:
1039
- self.project_dir = project_path
1040
-
1041
- self.launch_agent(
1042
- agent_identity,
1043
- agent_session_id=agent_session_id,
1044
- session_pk=session_pk,
1045
- project_path=project_path,
1046
- )
1047
-
1048
- @work
1049
- async def action_sessions(self) -> None:
1050
- if (session_screen_name := await self.push_screen_wait("sessions")) is not None:
1051
- if session_screen_name.startswith("session-"):
1052
- parts = session_screen_name.split("-")
1053
- session_pk = int(parts[1])
1054
- existing_mode = self._find_mode_for_session_pk(session_pk)
1055
- if existing_mode is not None and existing_mode in self._modes:
1056
- self.switch_mode(existing_mode)
1057
- else:
1058
- self._load_session(session_pk)
1059
- else:
1060
- try:
1061
- self.app.switch_mode(session_screen_name)
1062
- except KeyError:
1063
- pass
1064
-
1065
- @work
1066
- async def action_projects(self) -> None:
1067
- from pathlib import Path
1068
- from cdh.config import clear_active_project, read_active_project, write_active_project
1069
- from cdh.project_loader import CdhProjectLoader
1070
- from tui.widgets.edit_field import EditFieldScreen
1071
- import yaml
1072
-
1073
- from tui.screens.projects_screen import ProjectsScreen
1074
- result = await self.push_screen_wait(ProjectsScreen())
1075
- if result is None:
1076
- proj = read_active_project()
1077
- if proj and proj.get("name"):
1078
- projects_dir = Path.home() / ".cdh" / "projects"
1079
- pf = projects_dir / f"{proj['name']}.yaml"
1080
- if not pf.exists():
1081
- clear_active_project()
1082
- self.project_dir = None
1083
- self.screen.post_message(messages.ProjectDirectoryUpdated(project_dir=None))
1084
- if result is not None:
1085
- if result == "__new__":
1086
- default_path = str((self.project_dir or Path.cwd()).resolve())
1087
- path_str = await self.push_screen_wait(
1088
- EditFieldScreen("Project path", default_path)
1089
- )
1090
- if not path_str:
1091
- return
1092
- try:
1093
- project_path = Path(path_str).expanduser().resolve()
1094
- except Exception:
1095
- self.notify("Invalid path", severity="error")
1096
- return
1097
- name = project_path.name
1098
- from cdh.scaffold import scaffold_dlc_project
1099
- scaffold_dlc_project(project_path, name)
1100
- CdhProjectLoader.init_project(project_path, name)
1101
- projects_dir = Path.home() / ".cdh" / "projects"
1102
- projects_dir.mkdir(parents=True, exist_ok=True)
1103
- proj_data = {"name": name, "path": str(project_path), "description": ""}
1104
- (projects_dir / f"{name}.yaml").write_text(yaml.dump(proj_data))
1105
- write_active_project(name, str(project_path))
1106
- self.project_dir = project_path
1107
- self.screen.post_message(messages.ProjectDirectoryUpdated(project_dir=self.project_dir))
1108
- launched = self._launch_new_session_for_project(project_path)
1109
- suffix = " (new session opened)" if launched else ""
1110
- self.notify(f"Created project '{name}' at {project_path}{suffix}")
1111
- return
1112
-
1113
- project_name = result if isinstance(result, str) else getattr(result, 'name', None)
1114
- if project_name:
1115
- projects_dir = Path.home() / ".cdh" / "projects"
1116
- project_path = None
1117
- for ext in ["yaml", "yml", "json"]:
1118
- pf = projects_dir / f"{project_name}.{ext}"
1119
- if pf.exists():
1120
- proj_data = yaml.safe_load(pf.read_text()) if ext in ["yaml", "yml"] else __import__("json").loads(pf.read_text())
1121
- project_path = proj_data.get("path", ".")
1122
- break
1123
- if project_path:
1124
- write_active_project(project_name, project_path)
1125
-
1126
- new_project_dir = Path(project_path) if project_path else Path.cwd()
1127
- self.project_dir = new_project_dir
1128
- self.screen.post_message(messages.ProjectDirectoryUpdated(project_dir=self.project_dir))
1129
- launched = self._launch_new_session_for_project(new_project_dir)
1130
- suffix = " (new session opened)" if launched else ""
1131
- self.notify(f"Switched to project: {project_name}{suffix}")
1132
-
1133
- @on(messages.LaunchAgent)
1134
- def on_launch_agent(self, message: messages.LaunchAgent) -> None:
1135
- self.launch_agent(
1136
- message.identity,
1137
- agent_session_id=message.session_id,
1138
- session_pk=message.pk,
1139
- initial_prompt=message.prompt,
1140
- )
1141
-
1142
- @work
1143
- async def launch_agent(
1144
- self,
1145
- agent_identity: str,
1146
- *,
1147
- agent_session_id: str | None = None,
1148
- session_pk: int | None = None,
1149
- project_path: Path | None = None,
1150
- initial_prompt: str | None = None,
1151
- ) -> None:
1152
- from tui.screens.main import MainScreen
1153
- from tui.agent_schema import Agent
1154
- from tui.agents import read_agents
1155
-
1156
- agent: Agent | None = None
1157
- if session_pk is not None:
1158
- db = DB()
1159
- session = await db.session_get(session_pk)
1160
- if session is not None:
1161
- meta = json.loads(session["meta_json"])
1162
- if agent_data := meta.get("agent_data"):
1163
- agent = agent_data
1164
-
1165
- if agent is None:
1166
- agents = await read_agents()
1167
- try:
1168
- agent = agents[agent_identity]
1169
- except KeyError:
1170
- self.notify("Agent not found", title="Launch agent", severity="error")
1171
- return
1172
- if project_path is None:
1173
- project_path = Path(self.project_dir or os.getcwd())
1174
-
1175
- def get_screen():
1176
- screen = MainScreen(
1177
- project_path,
1178
- agent,
1179
- agent_session_id,
1180
- session_pk=session_pk,
1181
- initial_prompt=initial_prompt,
1182
- ).data_bind(
1183
- column=A2TUIApp.column,
1184
- column_width=A2TUIApp.column_width,
1185
- )
1186
-
1187
- return screen
1188
-
1189
- await self.new_session_screen(get_screen, session_pk=session_pk)
1190
-
1191
- def _find_mode_for_session_pk(self, session_pk: int) -> str | None:
1192
- """Find an existing mode name for a given DB session_pk."""
1193
- if existing := self._session_tracker.get_session_by_pk(session_pk):
1194
- return existing.mode_name
1195
- return None