Commit 14c6afb
authored
feat(kiloclaw): add openclaw doctor controller API route (#2707)
* feat(kiloclaw): add openclaw doctor controller API route
Adds POST /_kilo/doctor/run to the machine-side controller as a
replacement for the 60s-capped Fly Machines exec API. Wired end-to-end
through a new DO RPC, a worker platform route
(/api/platform/doctor-controller), the internal client, a new admin
tRPC procedure, and a new 'Run Doctor (Controller)' admin button.
Behavior:
- Synchronous buffered response with a 120s hard cap; SIGTERM then
SIGKILL after a 5s grace on timeout or client disconnect.
- Single run at a time, serialized via a runStartExclusive queue;
409 openclaw_doctor_already_active on concurrent start.
- Env parity with the live gateway: spawn inherits process.env, so
doctor sees the same decrypted secrets as 'openclaw gateway'.
- --fix defaults to true at every layer (controller, worker route,
admin tRPC) matching the Fly-exec flow and the admin checkbox.
Compatibility:
- Server: DO uses isErrorUnknownRoute to detect older controllers and
returns null, which the worker surfaces as 404
controller_route_unavailable.
- Client: admin UI uses calverAtLeast(version, '2026.4.22') to disable
the new button with an 'Unavailable until redeploy' tooltip on
stale controllers (matches supportsConfigRestore pattern).
Auth/ownership:
- Controller route uses timingSafeTokenEqual bearer middleware.
- Admin tRPC calls assertInstanceBelongsToUser so mismatched
{userId, instanceId} pairs 404 rather than acting on the wrong
instance.
Client-disconnect plumbing: handleHttpRequest now creates an
AbortController wired to the node req's 'close' event (gated on
!res.writableEnded) and passes it into the Request signal; the doctor
route observes c.req.raw.signal to SIGTERM the child if the caller
drops. Inert for existing routes since none read the signal.
The existing Fly-exec /api/platform/doctor + 'Run Doctor' button are
intentionally kept alive so both paths run side-by-side during the
migration. Deprecation of the Fly-exec path is a follow-up PR.
Dockerfile has no structural change; CI must pass
--build-arg CONTROLLER_CACHE_BUST=$(date +%s) for the new controller
code to land in the image.
* fix(kiloclaw): listen on res not req for client-disconnect abort
ServerResponse's 'close' event is the correct signal for client
disconnects. IncomingMessage's 'close' event fires as soon as the
request body stream is fully consumed — which, when we pass 'req' as
init.body for POST requests, happens mid-handler inside Hono's
c.req.json() call. That falsely tripped the AbortController before
the response was sent, and the doctor route interpreted the signal
as a real client disconnect and SIGTERMed the child.
Locally reproduced: POST /_kilo/doctor/run returned
'status: cancelled' with '[cancelled by client disconnect]' in the
output, even though the caller was still waiting.
Switching to res.on('close') + !res.writableEnded gives us the
legitimate 'connection terminated before response completed' case.
Verified via smoke container: openclaw doctor now runs to completion
and returns 'status: completed, exitCode: 0' with full output.
* test(kiloclaw): fix doctor controller expectation
* refactor(kiloclaw): make controller doctor runs async
* fix(kiloclaw): refresh doctor status after start
* fix(kiloclaw): avoid duplicate doctor log reads
* fix(kiloclaw): gate controller doctor on async route version
* fix(kiloclaw): show active doctor run on conflict
* fix(kiloclaw): harden controller doctor availability
* fix(kiloclaw): prevent overlapping doctor runs1 parent 5861891 commit 14c6afb
17 files changed
Lines changed: 1971 additions & 12 deletions
File tree
- apps/web/src
- app/admin/components/KiloclawInstances
- lib/kiloclaw
- routers
- services/kiloclaw
- controller/src
- routes
- src
- durable-objects
- kiloclaw-instance
- routes
Lines changed: 281 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
38 | 41 | | |
39 | 42 | | |
40 | 43 | | |
| |||
1301 | 1304 | | |
1302 | 1305 | | |
1303 | 1306 | | |
| 1307 | + | |
| 1308 | + | |
1304 | 1309 | | |
1305 | 1310 | | |
1306 | 1311 | | |
| |||
1482 | 1487 | | |
1483 | 1488 | | |
1484 | 1489 | | |
| 1490 | + | |
| 1491 | + | |
| 1492 | + | |
| 1493 | + | |
| 1494 | + | |
| 1495 | + | |
| 1496 | + | |
| 1497 | + | |
| 1498 | + | |
1485 | 1499 | | |
1486 | 1500 | | |
1487 | 1501 | | |
| |||
2011 | 2025 | | |
2012 | 2026 | | |
2013 | 2027 | | |
| 2028 | + | |
| 2029 | + | |
| 2030 | + | |
| 2031 | + | |
| 2032 | + | |
| 2033 | + | |
| 2034 | + | |
| 2035 | + | |
| 2036 | + | |
| 2037 | + | |
| 2038 | + | |
| 2039 | + | |
| 2040 | + | |
| 2041 | + | |
| 2042 | + | |
| 2043 | + | |
| 2044 | + | |
| 2045 | + | |
| 2046 | + | |
| 2047 | + | |
| 2048 | + | |
| 2049 | + | |
| 2050 | + | |
| 2051 | + | |
| 2052 | + | |
| 2053 | + | |
| 2054 | + | |
| 2055 | + | |
| 2056 | + | |
| 2057 | + | |
| 2058 | + | |
| 2059 | + | |
| 2060 | + | |
| 2061 | + | |
| 2062 | + | |
| 2063 | + | |
| 2064 | + | |
| 2065 | + | |
| 2066 | + | |
| 2067 | + | |
| 2068 | + | |
| 2069 | + | |
| 2070 | + | |
| 2071 | + | |
| 2072 | + | |
| 2073 | + | |
| 2074 | + | |
| 2075 | + | |
2014 | 2076 | | |
2015 | 2077 | | |
2016 | 2078 | | |
| |||
2145 | 2207 | | |
2146 | 2208 | | |
2147 | 2209 | | |
| 2210 | + | |
| 2211 | + | |
2148 | 2212 | | |
2149 | 2213 | | |
2150 | 2214 | | |
| |||
4173 | 4237 | | |
4174 | 4238 | | |
4175 | 4239 | | |
| 4240 | + | |
| 4241 | + | |
| 4242 | + | |
| 4243 | + | |
| 4244 | + | |
| 4245 | + | |
| 4246 | + | |
| 4247 | + | |
| 4248 | + | |
| 4249 | + | |
| 4250 | + | |
| 4251 | + | |
| 4252 | + | |
| 4253 | + | |
| 4254 | + | |
| 4255 | + | |
| 4256 | + | |
| 4257 | + | |
| 4258 | + | |
| 4259 | + | |
| 4260 | + | |
| 4261 | + | |
| 4262 | + | |
| 4263 | + | |
4176 | 4264 | | |
4177 | 4265 | | |
4178 | 4266 | | |
| |||
4590 | 4678 | | |
4591 | 4679 | | |
4592 | 4680 | | |
| 4681 | + | |
| 4682 | + | |
| 4683 | + | |
| 4684 | + | |
| 4685 | + | |
| 4686 | + | |
| 4687 | + | |
| 4688 | + | |
| 4689 | + | |
| 4690 | + | |
| 4691 | + | |
| 4692 | + | |
| 4693 | + | |
| 4694 | + | |
| 4695 | + | |
| 4696 | + | |
| 4697 | + | |
| 4698 | + | |
| 4699 | + | |
| 4700 | + | |
| 4701 | + | |
| 4702 | + | |
| 4703 | + | |
| 4704 | + | |
| 4705 | + | |
4593 | 4706 | | |
4594 | 4707 | | |
4595 | 4708 | | |
| |||
4737 | 4850 | | |
4738 | 4851 | | |
4739 | 4852 | | |
| 4853 | + | |
| 4854 | + | |
| 4855 | + | |
| 4856 | + | |
| 4857 | + | |
| 4858 | + | |
| 4859 | + | |
| 4860 | + | |
| 4861 | + | |
| 4862 | + | |
| 4863 | + | |
| 4864 | + | |
| 4865 | + | |
| 4866 | + | |
| 4867 | + | |
| 4868 | + | |
| 4869 | + | |
| 4870 | + | |
| 4871 | + | |
| 4872 | + | |
| 4873 | + | |
| 4874 | + | |
| 4875 | + | |
| 4876 | + | |
| 4877 | + | |
| 4878 | + | |
| 4879 | + | |
| 4880 | + | |
| 4881 | + | |
| 4882 | + | |
| 4883 | + | |
| 4884 | + | |
| 4885 | + | |
| 4886 | + | |
| 4887 | + | |
| 4888 | + | |
| 4889 | + | |
| 4890 | + | |
| 4891 | + | |
| 4892 | + | |
| 4893 | + | |
| 4894 | + | |
| 4895 | + | |
| 4896 | + | |
| 4897 | + | |
| 4898 | + | |
| 4899 | + | |
| 4900 | + | |
| 4901 | + | |
| 4902 | + | |
| 4903 | + | |
| 4904 | + | |
| 4905 | + | |
| 4906 | + | |
| 4907 | + | |
| 4908 | + | |
| 4909 | + | |
| 4910 | + | |
| 4911 | + | |
| 4912 | + | |
| 4913 | + | |
| 4914 | + | |
| 4915 | + | |
| 4916 | + | |
| 4917 | + | |
| 4918 | + | |
| 4919 | + | |
| 4920 | + | |
| 4921 | + | |
| 4922 | + | |
| 4923 | + | |
| 4924 | + | |
| 4925 | + | |
| 4926 | + | |
| 4927 | + | |
| 4928 | + | |
| 4929 | + | |
| 4930 | + | |
| 4931 | + | |
| 4932 | + | |
| 4933 | + | |
| 4934 | + | |
| 4935 | + | |
| 4936 | + | |
| 4937 | + | |
| 4938 | + | |
| 4939 | + | |
| 4940 | + | |
| 4941 | + | |
| 4942 | + | |
| 4943 | + | |
| 4944 | + | |
| 4945 | + | |
| 4946 | + | |
| 4947 | + | |
| 4948 | + | |
| 4949 | + | |
| 4950 | + | |
| 4951 | + | |
| 4952 | + | |
| 4953 | + | |
| 4954 | + | |
| 4955 | + | |
| 4956 | + | |
| 4957 | + | |
| 4958 | + | |
| 4959 | + | |
| 4960 | + | |
| 4961 | + | |
| 4962 | + | |
| 4963 | + | |
| 4964 | + | |
| 4965 | + | |
| 4966 | + | |
| 4967 | + | |
| 4968 | + | |
| 4969 | + | |
| 4970 | + | |
| 4971 | + | |
| 4972 | + | |
| 4973 | + | |
| 4974 | + | |
| 4975 | + | |
| 4976 | + | |
| 4977 | + | |
| 4978 | + | |
| 4979 | + | |
| 4980 | + | |
| 4981 | + | |
| 4982 | + | |
| 4983 | + | |
| 4984 | + | |
| 4985 | + | |
| 4986 | + | |
| 4987 | + | |
| 4988 | + | |
| 4989 | + | |
| 4990 | + | |
| 4991 | + | |
| 4992 | + | |
| 4993 | + | |
| 4994 | + | |
| 4995 | + | |
| 4996 | + | |
| 4997 | + | |
| 4998 | + | |
| 4999 | + | |
| 5000 | + | |
| 5001 | + | |
| 5002 | + | |
| 5003 | + | |
| 5004 | + | |
| 5005 | + | |
| 5006 | + | |
| 5007 | + | |
| 5008 | + | |
| 5009 | + | |
| 5010 | + | |
| 5011 | + | |
| 5012 | + | |
| 5013 | + | |
| 5014 | + | |
| 5015 | + | |
| 5016 | + | |
| 5017 | + | |
| 5018 | + | |
| 5019 | + | |
| 5020 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
31 | 34 | | |
32 | 35 | | |
33 | 36 | | |
| |||
625 | 628 | | |
626 | 629 | | |
627 | 630 | | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
628 | 673 | | |
629 | 674 | | |
630 | 675 | | |
| |||
0 commit comments