mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-18 12:02:02 +08:00
Compare commits
594 Commits
docs/plugi
...
v2026.3.22
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7d11f6c33 | ||
|
|
6f048f59cb | ||
|
|
b9efba1faf | ||
|
|
4dcc39c25c | ||
|
|
6e012d7feb | ||
|
|
2df10e81c8 | ||
|
|
9d3d7f9e65 | ||
|
|
a0ad47440a | ||
|
|
3ff2f85bad | ||
|
|
203eebec2f | ||
|
|
399fae33ca | ||
|
|
8067ae50fa | ||
|
|
d8d545bac1 | ||
|
|
e94ebfa084 | ||
|
|
95fec668a0 | ||
|
|
75b65c2a35 | ||
|
|
7a92d43d9a | ||
|
|
9516c72618 | ||
|
|
988bd782f7 | ||
|
|
7ba28d6dba | ||
|
|
2a06097184 | ||
|
|
8f8b79496f | ||
|
|
bf12835995 | ||
|
|
a835c200f3 | ||
|
|
b186d9847c | ||
|
|
a381e0d115 | ||
|
|
a4367eb656 | ||
|
|
4ea014d581 | ||
|
|
fb602c9b02 | ||
|
|
aa02b86a9e | ||
|
|
d44a399ae0 | ||
|
|
5637f9b516 | ||
|
|
c4420c0324 | ||
|
|
7cee097df9 | ||
|
|
abf2157b18 | ||
|
|
f64f3fdb53 | ||
|
|
8b02ef1332 | ||
|
|
94f397bc5f | ||
|
|
fe459c9084 | ||
|
|
6c60a3773a | ||
|
|
db5369f5f9 | ||
|
|
a60672b708 | ||
|
|
d22279d2e8 | ||
|
|
9105b3723d | ||
|
|
771a78cc77 | ||
|
|
dc90d3b1d3 | ||
|
|
eac93507c3 | ||
|
|
3fd5d13315 | ||
|
|
ff54c02b7d | ||
|
|
fe5819887b | ||
|
|
9fbb840c79 | ||
|
|
5f05c92922 | ||
|
|
93880717f1 | ||
|
|
4fd7feb0fd | ||
|
|
abbd1b6b8a | ||
|
|
deecf68b59 | ||
|
|
0b58829364 | ||
|
|
83e715cdaa | ||
|
|
b23e9c577d | ||
|
|
04c69ea3a0 | ||
|
|
6686f1cb2c | ||
|
|
43557668d2 | ||
|
|
fe3663a9fe | ||
|
|
65405edaab | ||
|
|
ddf823036b | ||
|
|
4a26f10f68 | ||
|
|
80cd8cd6be | ||
|
|
ebc2b711ea | ||
|
|
937f78b69f | ||
|
|
535263572e | ||
|
|
a600c72ed7 | ||
|
|
4580d585ff | ||
|
|
52b92f2973 | ||
|
|
47186c50a2 | ||
|
|
b62fed0ea7 | ||
|
|
202b588db5 | ||
|
|
d2a1b24b83 | ||
|
|
ed614938d7 | ||
|
|
37c2166f52 | ||
|
|
3fac0d11fa | ||
|
|
2349693924 | ||
|
|
980940aa58 | ||
|
|
651dc7450b | ||
|
|
2467fa4c5b | ||
|
|
dda347eda3 | ||
|
|
c42cb1ca66 | ||
|
|
fb6454c543 | ||
|
|
677a821a2f | ||
|
|
ea800dd4ef | ||
|
|
6c1ea41472 | ||
|
|
f3de580ca1 | ||
|
|
957fff443f | ||
|
|
cef7d14861 | ||
|
|
0b40ec38ab | ||
|
|
6ba5595004 | ||
|
|
c041f8587b | ||
|
|
97abc6db55 | ||
|
|
7ade3553b7 | ||
|
|
55ad5d7bd7 | ||
|
|
f52eb934d6 | ||
|
|
72e58ca260 | ||
|
|
4d50084c6e | ||
|
|
78175aeb0a | ||
|
|
e1d4c38cee | ||
|
|
c036e4d176 | ||
|
|
09faed6bd8 | ||
|
|
81445a9010 | ||
|
|
fd5555d5be | ||
|
|
5822892fee | ||
|
|
c82fc9a0fd | ||
|
|
a55f371cc5 | ||
|
|
be3a2e2eb6 | ||
|
|
39409b6a6d | ||
|
|
af9de86286 | ||
|
|
7fcbf383d8 | ||
|
|
ea579ef858 | ||
|
|
c5a941a506 | ||
|
|
6b9915a106 | ||
|
|
5ff60cc39f | ||
|
|
91f2c92960 | ||
|
|
2fe1ff8ea8 | ||
|
|
30ed4342b3 | ||
|
|
5730865f08 | ||
|
|
d43e26e399 | ||
|
|
8791aaae2b | ||
|
|
c15282062f | ||
|
|
c6ca11e5a5 | ||
|
|
827c441902 | ||
|
|
dc6c22b812 | ||
|
|
dd860e76aa | ||
|
|
77ec7b4adf | ||
|
|
3afb6a2b95 | ||
|
|
8a59b09fc8 | ||
|
|
97e4f37171 | ||
|
|
03c4bacbfb | ||
|
|
0e1da034c2 | ||
|
|
46a455d9e3 | ||
|
|
9378b31e08 | ||
|
|
e001e8f2f8 | ||
|
|
8e568142f6 | ||
|
|
85023d6f9c | ||
|
|
7818344f82 | ||
|
|
7909236bd1 | ||
|
|
1c60e00a34 | ||
|
|
09cb77ed38 | ||
|
|
6eafa2ec87 | ||
|
|
df3f9bb555 | ||
|
|
c11f95eced | ||
|
|
0a8eb7fdf0 | ||
|
|
a45ebf74bb | ||
|
|
0d161069f2 | ||
|
|
ee749b520e | ||
|
|
5f746422aa | ||
|
|
faae3e155d | ||
|
|
218663c956 | ||
|
|
1042b59471 | ||
|
|
5213382195 | ||
|
|
f69062c16e | ||
|
|
8b667cbe44 | ||
|
|
50bc625203 | ||
|
|
1354f37c88 | ||
|
|
daa3b4ba89 | ||
|
|
06ddfb7e5f | ||
|
|
04cd389ef8 | ||
|
|
d949dffc6e | ||
|
|
5f3753c9ab | ||
|
|
828afd39ec | ||
|
|
28f48a2dfd | ||
|
|
59105fd614 | ||
|
|
afb4b1173b | ||
|
|
ac0fd26e16 | ||
|
|
dbeac0763c | ||
|
|
af333f3a2c | ||
|
|
f1bff0b9d6 | ||
|
|
32fdd21c80 | ||
|
|
feea4763fb | ||
|
|
bbd4b39afb | ||
|
|
ac7b7f5536 | ||
|
|
a9f4cb7544 | ||
|
|
742c005ac8 | ||
|
|
a83b7bca15 | ||
|
|
02f8a86e5c | ||
|
|
3ad652fa9e | ||
|
|
c0933e2fc8 | ||
|
|
009980465f | ||
|
|
f8731b3d9d | ||
|
|
22c75a55b0 | ||
|
|
339a67262d | ||
|
|
24f77d7457 | ||
|
|
a02499b335 | ||
|
|
b2107d3503 | ||
|
|
52acc57a61 | ||
|
|
3595ecba45 | ||
|
|
042669d8c8 | ||
|
|
2131981230 | ||
|
|
9ffde8efb2 | ||
|
|
7bfa261c42 | ||
|
|
462d7ad9c0 | ||
|
|
f04b49ee3e | ||
|
|
8ff277d2a2 | ||
|
|
3ccf1bee2c | ||
|
|
74cb08bede | ||
|
|
9aafff7378 | ||
|
|
96d61aa50c | ||
|
|
7d11f6cf69 | ||
|
|
1ea2593362 | ||
|
|
2fcd6507ec | ||
|
|
3392558b42 | ||
|
|
05055e200a | ||
|
|
562e4a1791 | ||
|
|
103098513f | ||
|
|
5051a37de4 | ||
|
|
16de5a7b41 | ||
|
|
e5be5c1b99 | ||
|
|
f56edd62f0 | ||
|
|
5c8ea0a175 | ||
|
|
583bea001c | ||
|
|
7d032ed38c | ||
|
|
956fe72b39 | ||
|
|
6237cfc6a6 | ||
|
|
b12dc4d04d | ||
|
|
d264c761cb | ||
|
|
3547b5fd1e | ||
|
|
54213b587f | ||
|
|
2e6f2b0f07 | ||
|
|
9a07187339 | ||
|
|
a960cba2db | ||
|
|
8a7ae5b67e | ||
|
|
7d8daa7173 | ||
|
|
ee362b7e38 | ||
|
|
ee1001d0ae | ||
|
|
7a0781a367 | ||
|
|
a437f0417e | ||
|
|
3f002feffb | ||
|
|
263d5ea687 | ||
|
|
aaba1ae653 | ||
|
|
55e0c6380a | ||
|
|
6e9cf81a8b | ||
|
|
29f3b7f6eb | ||
|
|
94f36bf373 | ||
|
|
654089320b | ||
|
|
a59db4c9f4 | ||
|
|
2dd3425584 | ||
|
|
b07312c55b | ||
|
|
329e539796 | ||
|
|
ca778b3f3c | ||
|
|
a05a251be0 | ||
|
|
20f758d4cb | ||
|
|
4e92807f10 | ||
|
|
5e64265537 | ||
|
|
69217164f7 | ||
|
|
248caf09f5 | ||
|
|
653d69ede7 | ||
|
|
f3650b466f | ||
|
|
75835fc664 | ||
|
|
c43bfcbbec | ||
|
|
8ef36e228f | ||
|
|
39752e7921 | ||
|
|
a40f781cbe | ||
|
|
383d5ac476 | ||
|
|
2db10fb1d4 | ||
|
|
bad9c8c223 | ||
|
|
4f0bb7594b | ||
|
|
f580b68380 | ||
|
|
639470c52c | ||
|
|
23c8af3d24 | ||
|
|
d1404014d9 | ||
|
|
ecdf5d457a | ||
|
|
774a2064c9 | ||
|
|
645c9210b3 | ||
|
|
0a329b2c9f | ||
|
|
2619f5fe55 | ||
|
|
1b53918d4f | ||
|
|
125e778fe6 | ||
|
|
3b32c41718 | ||
|
|
2df229cf8d | ||
|
|
fe867c2467 | ||
|
|
6fde263046 | ||
|
|
a753ee064d | ||
|
|
8b5eeba386 | ||
|
|
71113ea0cb | ||
|
|
cbf9cd0acb | ||
|
|
25f05612ee | ||
|
|
f9a063ee2d | ||
|
|
75ab4db87d | ||
|
|
05088eebdc | ||
|
|
b5b193d5ca | ||
|
|
fdcf26ffd3 | ||
|
|
3dcc802fe5 | ||
|
|
0f54ca20aa | ||
|
|
3fe96c7b9e | ||
|
|
a61e5d17f0 | ||
|
|
45ede8729e | ||
|
|
dc2013aae5 | ||
|
|
0743368013 | ||
|
|
bb8e2fceff | ||
|
|
d38cda5aab | ||
|
|
e3c7a05cb5 | ||
|
|
bd28eb9f5b | ||
|
|
88859c974f | ||
|
|
8eb7d3543e | ||
|
|
7dc1389d55 | ||
|
|
de6bf58e79 | ||
|
|
1d08ad4bac | ||
|
|
a8b9763d66 | ||
|
|
52538575c3 | ||
|
|
2ce79428c5 | ||
|
|
a8f7c274bc | ||
|
|
ac6542584b | ||
|
|
e1c0e94d0c | ||
|
|
dcef96e6d4 | ||
|
|
100d9a7a23 | ||
|
|
b21bcf6eb6 | ||
|
|
976eefe373 | ||
|
|
7bd12f4b37 | ||
|
|
aaa6068c08 | ||
|
|
a2999c6cfb | ||
|
|
a5ace56a19 | ||
|
|
047a01f9e2 | ||
|
|
38ee17145b | ||
|
|
b00306a75b | ||
|
|
797f3cc377 | ||
|
|
841add8414 | ||
|
|
f76e653776 | ||
|
|
550deb8c18 | ||
|
|
80e9737db4 | ||
|
|
165aeccd24 | ||
|
|
4e531d382b | ||
|
|
85f8437399 | ||
|
|
0684d887f6 | ||
|
|
ac8e81a5cd | ||
|
|
39faf4725d | ||
|
|
2cfc7bca10 | ||
|
|
f0ab31366c | ||
|
|
d9a2666ee1 | ||
|
|
72bfaf6ee2 | ||
|
|
4cc0d05cfb | ||
|
|
023394bc0b | ||
|
|
bca7787f92 | ||
|
|
60273758f8 | ||
|
|
63130118ba | ||
|
|
d73852ff21 | ||
|
|
d0f5e7cb2d | ||
|
|
4ee41cc6f3 | ||
|
|
274af0486a | ||
|
|
6245b4f3d8 | ||
|
|
4f11982ae6 | ||
|
|
8701a224f8 | ||
|
|
cac9de5326 | ||
|
|
e0273bb1e9 | ||
|
|
e0463331bb | ||
|
|
8c7d603f25 | ||
|
|
c0cbc7403b | ||
|
|
ec51ee1af5 | ||
|
|
d02ef5ae02 | ||
|
|
1eba6f830c | ||
|
|
c454fe0fb3 | ||
|
|
ec232aca39 | ||
|
|
854f3ad0f8 | ||
|
|
091b811a61 | ||
|
|
19c85cf44f | ||
|
|
bd1c6efca5 | ||
|
|
e0af23106c | ||
|
|
ca3165a3e7 | ||
|
|
5b42754afd | ||
|
|
d84b3f5d5d | ||
|
|
f8ff2a4f38 | ||
|
|
377be1329d | ||
|
|
bd8ca6dbd7 | ||
|
|
efcf3c9f16 | ||
|
|
f1603314f0 | ||
|
|
833d0dfeb0 | ||
|
|
59be2c8679 | ||
|
|
82508e3931 | ||
|
|
5c8e1275a0 | ||
|
|
a9b20e5de9 | ||
|
|
a89d9f491b | ||
|
|
1ad47b8fa1 | ||
|
|
d91913c207 | ||
|
|
ed6b894873 | ||
|
|
3a949646da | ||
|
|
18c4a00b6f | ||
|
|
7f65b3463b | ||
|
|
3365f2e157 | ||
|
|
ad5e3f0cd5 | ||
|
|
7709aa33d8 | ||
|
|
5a8f77aa6a | ||
|
|
bdd35a6239 | ||
|
|
81b498b2b6 | ||
|
|
5bba1b45bc | ||
|
|
ebb4cc0128 | ||
|
|
b863e1c315 | ||
|
|
9653c47133 | ||
|
|
b93a045a96 | ||
|
|
6e7855fdf5 | ||
|
|
9c0983618e | ||
|
|
2e2f7c844f | ||
|
|
4ed69e4314 | ||
|
|
77cbbae81b | ||
|
|
c3f1d43a10 | ||
|
|
72d775e069 | ||
|
|
58c3f8673a | ||
|
|
6df6a691fc | ||
|
|
196c07cac6 | ||
|
|
d9de38e0f8 | ||
|
|
24b9baebab | ||
|
|
d907ebffc5 | ||
|
|
ad01465318 | ||
|
|
47e8ffc2e9 | ||
|
|
d6c63163b4 | ||
|
|
d1ad48cb50 | ||
|
|
24032dcc0e | ||
|
|
6d34d62795 | ||
|
|
91cd38f4d4 | ||
|
|
030e950e5f | ||
|
|
a81e671509 | ||
|
|
8395d5cca2 | ||
|
|
6ba9764b0f | ||
|
|
b5ea31ff1c | ||
|
|
eca0809a6d | ||
|
|
8eadc2f43b | ||
|
|
6a228d9145 | ||
|
|
e06b8d3e62 | ||
|
|
601f560682 | ||
|
|
66743b84fa | ||
|
|
cfd9242e5d | ||
|
|
e15f156f85 | ||
|
|
ee077804b0 | ||
|
|
31ee442d3f | ||
|
|
c0d4abc59e | ||
|
|
3faaf8984f | ||
|
|
44bbd2d83d | ||
|
|
bb3e565487 | ||
|
|
3a68e87f84 | ||
|
|
cb4ae1a56d | ||
|
|
d868ee0882 | ||
|
|
a6f918731f | ||
|
|
523b76c6c1 | ||
|
|
f1975c0c0a | ||
|
|
f7bc9818b5 | ||
|
|
57267b23d5 | ||
|
|
ef3f64952a | ||
|
|
30090e4895 | ||
|
|
055f62e43e | ||
|
|
1e1372027e | ||
|
|
f075e2eebd | ||
|
|
5d379f92a3 | ||
|
|
4235fb16d6 | ||
|
|
abd948f2b7 | ||
|
|
3e10d4c33d | ||
|
|
ae6f42484f | ||
|
|
9d7719e8f0 | ||
|
|
fa0a9ce2af | ||
|
|
af4f2a8028 | ||
|
|
77bdb33735 | ||
|
|
11ca41f457 | ||
|
|
dcd5473283 | ||
|
|
99462776d1 | ||
|
|
87b2672126 | ||
|
|
29c0e783b1 | ||
|
|
a8e10d9dc4 | ||
|
|
f0dc42a9c5 | ||
|
|
9e0d298a08 | ||
|
|
2773f33084 | ||
|
|
9267e694f7 | ||
|
|
46876edd86 | ||
|
|
ca99163b98 | ||
|
|
593e333c10 | ||
|
|
171b24c5c5 | ||
|
|
3ca7922dfe | ||
|
|
78399c67e9 | ||
|
|
8745132f9c | ||
|
|
6dd4aff64a | ||
|
|
2c05e07f68 | ||
|
|
2e246b47b9 | ||
|
|
7babb4583b | ||
|
|
0df0c9f601 | ||
|
|
201124e183 | ||
|
|
ff6e0bed5f | ||
|
|
26db578edc | ||
|
|
0a20c5c8b3 | ||
|
|
1efda3d041 | ||
|
|
2a1acec6a7 | ||
|
|
87722d6327 | ||
|
|
00b2f10dec | ||
|
|
11c66b36fd | ||
|
|
7a3346871e | ||
|
|
773fb9cead | ||
|
|
822c68a2d0 | ||
|
|
8eb881ef18 | ||
|
|
8d27617918 | ||
|
|
7a2709c391 | ||
|
|
fa13c2960e | ||
|
|
8aca2fdc73 | ||
|
|
5369ea53be | ||
|
|
3025760867 | ||
|
|
e04d203bff | ||
|
|
cf8891a824 | ||
|
|
43ee9fff48 | ||
|
|
4bd90f24d1 | ||
|
|
b369397b43 | ||
|
|
ff941b0193 | ||
|
|
6fa0027c61 | ||
|
|
9bb5eb6c7f | ||
|
|
0404c16217 | ||
|
|
16616e21df | ||
|
|
3c071a397f | ||
|
|
bddb6fca7b | ||
|
|
66beff726b | ||
|
|
bd108dfe00 | ||
|
|
59837b25bd | ||
|
|
285f903462 | ||
|
|
0329412af2 | ||
|
|
c1067e90c9 | ||
|
|
fdc993e779 | ||
|
|
5f723ecd7f | ||
|
|
c26655d397 | ||
|
|
4240c64491 | ||
|
|
52b9d2091e | ||
|
|
c0f107e246 | ||
|
|
5b2ff17d3c | ||
|
|
dbd26e49f1 | ||
|
|
26d400bea6 | ||
|
|
e39d5b9ef8 | ||
|
|
e64dbb00b3 | ||
|
|
f85cfc8b6c | ||
|
|
aef2c60aa5 | ||
|
|
e80d456608 | ||
|
|
c69b1da6a0 | ||
|
|
2ef4d472f2 | ||
|
|
1822db9227 | ||
|
|
1b1167012f | ||
|
|
e3151af6bc | ||
|
|
5696e24c3f | ||
|
|
145e514bb5 | ||
|
|
5920ea838d | ||
|
|
c74a50e4f1 | ||
|
|
d06413e335 | ||
|
|
017d295edb | ||
|
|
ff759f991e | ||
|
|
7ae09410b7 | ||
|
|
8e09568bc7 | ||
|
|
412a3eb1ac | ||
|
|
4113db7d78 | ||
|
|
dbf3dd6559 | ||
|
|
6d9d9319b2 | ||
|
|
1f93a99f47 | ||
|
|
8f12303a72 | ||
|
|
c40488453e | ||
|
|
7d1ab5baca | ||
|
|
75692249d2 | ||
|
|
28838802d4 | ||
|
|
1ed40cdf54 | ||
|
|
b79560c7f0 | ||
|
|
59b5583e0a | ||
|
|
04b283ffc2 | ||
|
|
95ae8aabb7 | ||
|
|
aa80b1eb7c | ||
|
|
b44152fcc8 | ||
|
|
8d9686bd0f | ||
|
|
13c239039a | ||
|
|
23a6e0ccd3 | ||
|
|
17739910e9 | ||
|
|
2c919078e1 | ||
|
|
88d39b1542 | ||
|
|
89d65521fe | ||
|
|
f095bbd7b0 | ||
|
|
9428b38452 | ||
|
|
ca986d05aa | ||
|
|
1ceaad18a6 | ||
|
|
719bfb46ff | ||
|
|
047485dda6 | ||
|
|
405d808409 | ||
|
|
5863ce1f78 | ||
|
|
2a66eaf473 | ||
|
|
c8a36c621e | ||
|
|
14074d3337 | ||
|
|
0ac939059e | ||
|
|
d551d8b8f7 | ||
|
|
af90ddd8d3 | ||
|
|
36c951769c | ||
|
|
689a7342c2 | ||
|
|
090ac8831f | ||
|
|
6c2a3b74e3 | ||
|
|
91b2800241 | ||
|
|
c7788773bf | ||
|
|
5cb2f45585 | ||
|
|
c96c319db3 | ||
|
|
8a111f1cb9 | ||
|
|
b0176f626c | ||
|
|
279c0c621f | ||
|
|
68170f99ac | ||
|
|
42f23619e3 | ||
|
|
1ee9611079 |
@@ -16,11 +16,21 @@ Use this skill for Parallels guest workflows and smoke interpretation. Do not lo
|
||||
- Pass `--json` for machine-readable summaries.
|
||||
- Per-phase logs land under `/tmp/openclaw-parallels-*`.
|
||||
- Do not run local and gateway agent turns in parallel on the same fresh workspace or session.
|
||||
- For `prlctl exec`, pass the VM name before `--current-user` (`prlctl exec "$VM" --current-user ...`), not the other way around.
|
||||
|
||||
## npm install then update
|
||||
|
||||
- Preferred entrypoint: `pnpm test:parallels:npm-update`
|
||||
- Flow: fresh snapshot -> install npm package baseline -> smoke -> install current main tgz on the same guest -> smoke again.
|
||||
- Same-guest update verification should set the default model explicitly to `openai/gpt-5.4` before the agent turn and use a fresh explicit `--session-id` so old session model state does not leak into the check.
|
||||
- On Windows same-guest update checks, restart the gateway after the npm upgrade before `gateway status` / `agent`; in-place global npm updates can otherwise leave stale hashed `dist/*` module imports alive in the running service.
|
||||
- Linux same-guest update verification should also export `HOME=/root`, pass `OPENAI_API_KEY` via `prlctl exec ... /usr/bin/env`, and use `openclaw agent --local`; the fresh Linux baseline does not rely on persisted gateway credentials.
|
||||
|
||||
## macOS flow
|
||||
|
||||
- Preferred entrypoint: `pnpm test:parallels:macos`
|
||||
- Target the snapshot closest to `macOS 26.3.1 fresh`.
|
||||
- Default to the snapshot closest to `macOS 26.3.1 latest`.
|
||||
- On Peter's Tahoe VM, `fresh-latest-march-2026` can hang in `prlctl snapshot-switch`; if restore times out there, rerun with `--snapshot-hint 'macOS 26.3.1 latest'` before blaming auth or the harness.
|
||||
- `prlctl exec` is fine for deterministic repo commands, but use the guest Terminal or `prlctl enter` when installer parity or shell-sensitive behavior matters.
|
||||
- On the fresh Tahoe snapshot, `brew` exists but `node` may be missing from PATH in noninteractive exec. Use `/opt/homebrew/bin/node` when needed.
|
||||
- Fresh host-served tgz installs should install as guest root with `HOME=/var/root`, then run onboarding as the desktop user via `prlctl exec --current-user`.
|
||||
@@ -33,17 +43,21 @@ Use this skill for Parallels guest workflows and smoke interpretation. Do not lo
|
||||
- Always use `prlctl exec --current-user`; plain `prlctl exec` lands in `NT AUTHORITY\\SYSTEM`.
|
||||
- Prefer explicit `npm.cmd` and `openclaw.cmd`.
|
||||
- Use PowerShell only as the transport with `-ExecutionPolicy Bypass`, then call the `.cmd` shims from inside it.
|
||||
- Windows installer/tgz phases now retry once after guest-ready recheck; keep new Windows smoke steps idempotent so a transport-flake retry is safe.
|
||||
- Keep onboarding and status output ASCII-clean in logs; fancy punctuation becomes mojibake in current capture paths.
|
||||
- If you hit an older run with `rc=255` plus an empty `fresh.install-main.log` or `upgrade.install-main.log`, treat it as a likely `prlctl exec` transport drop after guest start-up, not immediate proof of an npm/package failure.
|
||||
|
||||
## Linux flow
|
||||
|
||||
- Preferred entrypoint: `pnpm test:parallels:linux`
|
||||
- Use the snapshot closest to fresh `Ubuntu 24.04.3 ARM64`.
|
||||
- If that exact VM is missing on the host, fall back to the closest Ubuntu guest with a fresh poweroff snapshot. On Peter's host today, that is `Ubuntu 25.10`.
|
||||
- Use plain `prlctl exec`; `--current-user` is not the right transport on this snapshot.
|
||||
- Fresh snapshots may be missing `curl`, and `apt-get update` can fail on clock skew. Bootstrap with `apt-get -o Acquire::Check-Date=false update` and install `curl ca-certificates`.
|
||||
- Fresh `main` tgz smoke still needs the latest-release installer first because the snapshot has no Node or npm before bootstrap.
|
||||
- This snapshot does not have a usable `systemd --user` session; managed daemon install is unsupported.
|
||||
- `prlctl exec` reaps detached Linux child processes on this snapshot, so detached background gateway runs are not trustworthy smoke signals.
|
||||
- Treat `gateway=skipped-no-detached-linux-gateway` plus `daemon=systemd-user-unavailable` as baseline on that Linux lane, not a regression.
|
||||
|
||||
## Discord roundtrip
|
||||
|
||||
|
||||
4
.github/labeler.yml
vendored
4
.github/labeler.yml
vendored
@@ -229,6 +229,10 @@
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "extensions/device-pair/**"
|
||||
"extensions: duckduckgo":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "extensions/duckduckgo/**"
|
||||
"extensions: acpx":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
|
||||
449
.github/workflows/ci.yml
vendored
449
.github/workflows/ci.yml
vendored
@@ -7,21 +7,34 @@ on:
|
||||
types: [opened, reopened, synchronize, ready_for_review, converted_to_draft]
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
group: ${{ github.event_name == 'pull_request' && format('ci-pr-{0}', github.event.pull_request.number) || format('ci-push-{0}', github.run_id) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
# Preflight: establish the fast global truth for this revision before the
|
||||
# expensive platform and test lanes fan out.
|
||||
# Detect docs-only changes to skip heavy jobs (test, build, Windows, macOS, Android).
|
||||
# Lint and format always run. Fail-safe: if detection fails, run everything.
|
||||
docs-scope:
|
||||
# Run scope detection, changed-extension detection, and fast security checks in
|
||||
# one visible job so operators have a single preflight box to inspect and rerun.
|
||||
# Fail-safe: if detection steps are skipped, downstream outputs fall back to
|
||||
# conservative defaults that keep heavy lanes enabled.
|
||||
preflight:
|
||||
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
outputs:
|
||||
docs_only: ${{ steps.check.outputs.docs_only }}
|
||||
docs_changed: ${{ steps.check.outputs.docs_changed }}
|
||||
docs_only: ${{ steps.docs_scope.outputs.docs_only }}
|
||||
docs_changed: ${{ steps.docs_scope.outputs.docs_changed }}
|
||||
run_node: ${{ steps.changed_scope.outputs.run_node || 'false' }}
|
||||
run_macos: ${{ steps.changed_scope.outputs.run_macos || 'false' }}
|
||||
run_android: ${{ steps.changed_scope.outputs.run_android || 'false' }}
|
||||
run_skills_python: ${{ steps.changed_scope.outputs.run_skills_python || 'false' }}
|
||||
run_windows: ${{ steps.changed_scope.outputs.run_windows || 'false' }}
|
||||
has_changed_extensions: ${{ steps.changed_extensions.outputs.has_changed_extensions || 'false' }}
|
||||
changed_extensions_matrix: ${{ steps.changed_extensions.outputs.changed_extensions_matrix || '{"include":[]}' }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
@@ -30,44 +43,21 @@ jobs:
|
||||
fetch-tags: false
|
||||
submodules: false
|
||||
|
||||
- name: Ensure docs-scope base commit
|
||||
- name: Ensure preflight base commit
|
||||
uses: ./.github/actions/ensure-base-commit
|
||||
with:
|
||||
base-sha: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
|
||||
fetch-ref: ${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.base.ref }}
|
||||
|
||||
- name: Detect docs-only changes
|
||||
id: check
|
||||
id: docs_scope
|
||||
uses: ./.github/actions/detect-docs-changes
|
||||
|
||||
# Detect which heavy areas are touched so CI can skip unrelated expensive jobs.
|
||||
# Fail-safe: if detection fails, downstream jobs run.
|
||||
changed-scope:
|
||||
needs: [docs-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
outputs:
|
||||
run_node: ${{ steps.scope.outputs.run_node }}
|
||||
run_macos: ${{ steps.scope.outputs.run_macos }}
|
||||
run_android: ${{ steps.scope.outputs.run_android }}
|
||||
run_skills_python: ${{ steps.scope.outputs.run_skills_python }}
|
||||
run_windows: ${{ steps.scope.outputs.run_windows }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
submodules: false
|
||||
|
||||
- name: Ensure changed-scope base commit
|
||||
uses: ./.github/actions/ensure-base-commit
|
||||
with:
|
||||
base-sha: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
|
||||
fetch-ref: ${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.base.ref }}
|
||||
|
||||
# Detect which heavy areas are touched so CI can skip unrelated expensive jobs.
|
||||
# Fail-safe: if skipped, downstream lanes run.
|
||||
- name: Detect changed scopes
|
||||
id: scope
|
||||
id: changed_scope
|
||||
if: steps.docs_scope.outputs.docs_only != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@@ -80,28 +70,8 @@ jobs:
|
||||
|
||||
node scripts/ci-changed-scope.mjs --base "$BASE" --head HEAD
|
||||
|
||||
changed-extensions:
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
outputs:
|
||||
has_changed_extensions: ${{ steps.changed.outputs.has_changed_extensions }}
|
||||
changed_extensions_matrix: ${{ steps.changed.outputs.changed_extensions_matrix }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
submodules: false
|
||||
|
||||
- name: Ensure changed-extensions base commit
|
||||
uses: ./.github/actions/ensure-base-commit
|
||||
with:
|
||||
base-sha: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
|
||||
fetch-ref: ${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.base.ref }}
|
||||
|
||||
- name: Setup Node environment
|
||||
if: steps.docs_scope.outputs.docs_only != 'true'
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
@@ -109,26 +79,92 @@ jobs:
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Detect changed extensions
|
||||
id: changed
|
||||
id: changed_extensions
|
||||
if: steps.docs_scope.outputs.docs_only != 'true' && steps.changed_scope.outputs.run_node == 'true'
|
||||
env:
|
||||
BASE_SHA: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
|
||||
BASE_REF: ${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.base.ref }}
|
||||
run: |
|
||||
node --input-type=module <<'EOF'
|
||||
import { appendFileSync } from "node:fs";
|
||||
import { listChangedExtensionIds } from "./scripts/test-extension.mjs";
|
||||
|
||||
const extensionIds = listChangedExtensionIds({ base: process.env.BASE_SHA, head: "HEAD" });
|
||||
const extensionIds = listChangedExtensionIds({
|
||||
base: process.env.BASE_SHA,
|
||||
head: "HEAD",
|
||||
fallbackBaseRef: process.env.BASE_REF,
|
||||
unavailableBaseBehavior: "all",
|
||||
});
|
||||
const matrix = JSON.stringify({ include: extensionIds.map((extension) => ({ extension })) });
|
||||
|
||||
appendFileSync(process.env.GITHUB_OUTPUT, `has_changed_extensions=${extensionIds.length > 0}\n`, "utf8");
|
||||
appendFileSync(process.env.GITHUB_OUTPUT, `changed_extensions_matrix=${matrix}\n`, "utf8");
|
||||
EOF
|
||||
|
||||
- name: Setup Python
|
||||
id: setup-python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
cache: "pip"
|
||||
cache-dependency-path: |
|
||||
pyproject.toml
|
||||
.pre-commit-config.yaml
|
||||
.github/workflows/ci.yml
|
||||
|
||||
- name: Restore pre-commit cache
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ~/.cache/pre-commit
|
||||
key: pre-commit-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
|
||||
- name: Install pre-commit
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install pre-commit
|
||||
|
||||
- name: Detect committed private keys
|
||||
run: pre-commit run --all-files detect-private-key
|
||||
|
||||
- name: Audit changed GitHub workflows with zizmor
|
||||
env:
|
||||
BASE_SHA: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ -z "${BASE_SHA:-}" ] || [ "${BASE_SHA}" = "0000000000000000000000000000000000000000" ]; then
|
||||
echo "No usable base SHA detected; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null; then
|
||||
echo "Base SHA ${BASE_SHA} is unavailable; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mapfile -t workflow_files < <(
|
||||
git diff --name-only "${BASE_SHA}" HEAD -- '.github/workflows/*.yml' '.github/workflows/*.yaml'
|
||||
)
|
||||
if [ "${#workflow_files[@]}" -eq 0 ]; then
|
||||
echo "No workflow changes detected; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf 'Auditing workflow files:\n%s\n' "${workflow_files[@]}"
|
||||
pre-commit run zizmor --files "${workflow_files[@]}"
|
||||
|
||||
- name: Audit production dependencies
|
||||
if: steps.docs_scope.outputs.docs_only != 'true'
|
||||
run: pre-commit run --all-files pnpm-audit-prod
|
||||
|
||||
# Fanout: downstream lanes branch from preflight outputs instead of waiting
|
||||
# on unrelated Linux checks.
|
||||
# Build dist once for Node-relevant changes and share it with downstream jobs.
|
||||
build-artifacts:
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: github.event_name == 'push' && needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true'
|
||||
needs: [preflight]
|
||||
if: github.event_name == 'push' && needs.preflight.outputs.docs_only != 'true' && needs.preflight.outputs.run_node == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
@@ -160,9 +196,10 @@ jobs:
|
||||
|
||||
# Validate npm pack contents after build (only on push to main, not PRs).
|
||||
release-check:
|
||||
needs: [docs-scope, build-artifacts]
|
||||
if: github.event_name == 'push' && needs.docs-scope.outputs.docs_only != 'true'
|
||||
needs: [preflight, build-artifacts]
|
||||
if: github.event_name == 'push' && needs.preflight.outputs.docs_only != 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
@@ -185,9 +222,10 @@ jobs:
|
||||
run: pnpm release:check
|
||||
|
||||
checks:
|
||||
needs: [docs-scope, changed-scope, build-artifacts]
|
||||
if: always() && needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true' && (github.event_name != 'push' || needs.build-artifacts.result == 'success')
|
||||
needs: [preflight, build-artifacts]
|
||||
if: always() && needs.preflight.outputs.docs_only != 'true' && needs.preflight.outputs.run_node == 'true' && (github.event_name != 'push' || needs.build-artifacts.result == 'success')
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -280,12 +318,13 @@ jobs:
|
||||
|
||||
extension-fast:
|
||||
name: "extension-fast"
|
||||
needs: [docs-scope, changed-scope, changed-extensions]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true' && needs.changed-extensions.outputs.has_changed_extensions == 'true'
|
||||
needs: [preflight]
|
||||
if: needs.preflight.outputs.docs_only != 'true' && needs.preflight.outputs.run_node == 'true' && needs.preflight.outputs.has_changed_extensions == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.changed-extensions.outputs.changed_extensions_matrix) }}
|
||||
matrix: ${{ fromJson(needs.preflight.outputs.changed_extensions_matrix) }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
@@ -306,9 +345,10 @@ jobs:
|
||||
# Types, lint, and format check.
|
||||
check:
|
||||
name: "check"
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true'
|
||||
needs: [preflight]
|
||||
if: needs.preflight.outputs.docs_only != 'true' && needs.preflight.outputs.run_node == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
@@ -329,9 +369,10 @@ jobs:
|
||||
|
||||
check-additional:
|
||||
name: "check-additional"
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true'
|
||||
needs: [preflight]
|
||||
if: needs.preflight.outputs.docs_only != 'true' && needs.preflight.outputs.run_node == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
@@ -426,9 +467,10 @@ jobs:
|
||||
|
||||
build-smoke:
|
||||
name: "build-smoke"
|
||||
needs: [docs-scope, changed-scope, build-artifacts]
|
||||
if: always() && needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true' && (github.event_name != 'push' || needs.build-artifacts.result == 'success')
|
||||
needs: [preflight, build-artifacts]
|
||||
if: always() && needs.preflight.outputs.docs_only != 'true' && needs.preflight.outputs.run_node == 'true' && (github.event_name != 'push' || needs.build-artifacts.result == 'success')
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
@@ -466,9 +508,10 @@ jobs:
|
||||
|
||||
# Validate docs (format, lint, broken links) only when docs files changed.
|
||||
check-docs:
|
||||
needs: [docs-scope]
|
||||
if: needs.docs-scope.outputs.docs_changed == 'true'
|
||||
needs: [preflight]
|
||||
if: needs.preflight.outputs.docs_changed == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
@@ -485,9 +528,10 @@ jobs:
|
||||
run: pnpm check:docs
|
||||
|
||||
skills-python:
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && (github.event_name == 'push' || needs.changed-scope.outputs.run_skills_python == 'true')
|
||||
needs: [preflight]
|
||||
if: needs.preflight.outputs.docs_only != 'true' && (github.event_name == 'push' || needs.preflight.outputs.run_skills_python == 'true')
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
@@ -510,88 +554,11 @@ jobs:
|
||||
- name: Test skill Python scripts
|
||||
run: python -m pytest -q skills
|
||||
|
||||
secrets:
|
||||
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: Ensure secrets base commit
|
||||
uses: ./.github/actions/ensure-base-commit
|
||||
with:
|
||||
base-sha: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
|
||||
fetch-ref: ${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.base.ref }}
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
use-sticky-disk: "false"
|
||||
install-deps: "false"
|
||||
|
||||
- name: Setup Python
|
||||
id: setup-python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
cache: "pip"
|
||||
cache-dependency-path: |
|
||||
pyproject.toml
|
||||
.pre-commit-config.yaml
|
||||
.github/workflows/ci.yml
|
||||
|
||||
- name: Restore pre-commit cache
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ~/.cache/pre-commit
|
||||
key: pre-commit-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
|
||||
- name: Install pre-commit
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install pre-commit
|
||||
|
||||
- name: Detect committed private keys
|
||||
run: pre-commit run --all-files detect-private-key
|
||||
|
||||
- name: Audit changed GitHub workflows with zizmor
|
||||
env:
|
||||
BASE_SHA: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ -z "${BASE_SHA:-}" ] || [ "${BASE_SHA}" = "0000000000000000000000000000000000000000" ]; then
|
||||
echo "No usable base SHA detected; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null; then
|
||||
echo "Base SHA ${BASE_SHA} is unavailable; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mapfile -t workflow_files < <(
|
||||
git diff --name-only "${BASE_SHA}" HEAD -- '.github/workflows/*.yml' '.github/workflows/*.yaml'
|
||||
)
|
||||
if [ "${#workflow_files[@]}" -eq 0 ]; then
|
||||
echo "No workflow changes detected; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf 'Auditing workflow files:\n%s\n' "${workflow_files[@]}"
|
||||
pre-commit run zizmor --files "${workflow_files[@]}"
|
||||
|
||||
- name: Audit production dependencies
|
||||
run: pre-commit run --all-files pnpm-audit-prod
|
||||
|
||||
checks-windows:
|
||||
needs: [docs-scope, changed-scope, build-artifacts]
|
||||
if: always() && needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_windows == 'true' && (github.event_name != 'push' || needs.build-artifacts.result == 'success')
|
||||
needs: [preflight, build-artifacts]
|
||||
if: always() && needs.preflight.outputs.docs_only != 'true' && needs.preflight.outputs.run_windows == 'true' && (github.event_name != 'push' || needs.build-artifacts.result == 'success')
|
||||
runs-on: blacksmith-32vcpu-windows-2025
|
||||
timeout-minutes: 45
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
NODE_OPTIONS: --max-old-space-size=6144
|
||||
# Keep total concurrency predictable on the 32 vCPU runner.
|
||||
@@ -728,9 +695,10 @@ jobs:
|
||||
# running 4 separate jobs per PR (as before) starved the queue. One job
|
||||
# per PR allows 5 PRs to run macOS checks simultaneously.
|
||||
macos:
|
||||
needs: [docs-scope, changed-scope, check]
|
||||
if: github.event_name == 'pull_request' && needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_macos == 'true'
|
||||
needs: [preflight]
|
||||
if: github.event_name == 'pull_request' && needs.preflight.outputs.docs_only != 'true' && needs.preflight.outputs.run_macos == 'true'
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
@@ -803,170 +771,11 @@ jobs:
|
||||
done
|
||||
exit 1
|
||||
|
||||
ios:
|
||||
if: false # ignore iOS in CI for now
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: Select Xcode 26.1
|
||||
run: |
|
||||
sudo xcode-select -s /Applications/Xcode_26.1.app
|
||||
xcodebuild -version
|
||||
|
||||
- name: Install XcodeGen
|
||||
run: brew install xcodegen
|
||||
|
||||
- name: Install SwiftLint / SwiftFormat
|
||||
run: brew install swiftlint swiftformat
|
||||
|
||||
- name: Show toolchain
|
||||
run: |
|
||||
sw_vers
|
||||
xcodebuild -version
|
||||
swift --version
|
||||
|
||||
- name: Generate iOS project
|
||||
run: |
|
||||
cd apps/ios
|
||||
xcodegen generate
|
||||
|
||||
- name: iOS tests
|
||||
run: |
|
||||
set -euo pipefail
|
||||
RESULT_BUNDLE_PATH="$RUNNER_TEMP/Clawdis-iOS.xcresult"
|
||||
DEST_ID="$(
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
def sh(args: list[str]) -> str:
|
||||
return subprocess.check_output(args, text=True).strip()
|
||||
|
||||
# Prefer an already-created iPhone simulator if it exists.
|
||||
devices = json.loads(sh(["xcrun", "simctl", "list", "devices", "-j"]))
|
||||
candidates: list[tuple[str, str]] = []
|
||||
for runtime, devs in (devices.get("devices") or {}).items():
|
||||
for dev in devs or []:
|
||||
if not dev.get("isAvailable"):
|
||||
continue
|
||||
name = str(dev.get("name") or "")
|
||||
udid = str(dev.get("udid") or "")
|
||||
if not udid or not name.startswith("iPhone"):
|
||||
continue
|
||||
candidates.append((name, udid))
|
||||
|
||||
candidates.sort(key=lambda it: (0 if "iPhone 16" in it[0] else 1, it[0]))
|
||||
if candidates:
|
||||
print(candidates[0][1])
|
||||
sys.exit(0)
|
||||
|
||||
# Otherwise, create one from the newest available iOS runtime.
|
||||
runtimes = json.loads(sh(["xcrun", "simctl", "list", "runtimes", "-j"])).get("runtimes") or []
|
||||
ios = [rt for rt in runtimes if rt.get("platform") == "iOS" and rt.get("isAvailable")]
|
||||
if not ios:
|
||||
print("No available iOS runtimes found.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
def version_key(rt: dict) -> tuple[int, ...]:
|
||||
parts: list[int] = []
|
||||
for p in str(rt.get("version") or "0").split("."):
|
||||
try:
|
||||
parts.append(int(p))
|
||||
except ValueError:
|
||||
parts.append(0)
|
||||
return tuple(parts)
|
||||
|
||||
ios.sort(key=version_key, reverse=True)
|
||||
runtime = ios[0]
|
||||
runtime_id = str(runtime.get("identifier") or "")
|
||||
if not runtime_id:
|
||||
print("Missing iOS runtime identifier.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
supported = runtime.get("supportedDeviceTypes") or []
|
||||
iphones = [dt for dt in supported if dt.get("productFamily") == "iPhone"]
|
||||
if not iphones:
|
||||
print("No iPhone device types for iOS runtime.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
iphones.sort(
|
||||
key=lambda dt: (
|
||||
0 if "iPhone 16" in str(dt.get("name") or "") else 1,
|
||||
str(dt.get("name") or ""),
|
||||
)
|
||||
)
|
||||
device_type_id = str(iphones[0].get("identifier") or "")
|
||||
if not device_type_id:
|
||||
print("Missing iPhone device type identifier.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
sim_name = f"CI iPhone {uuid.uuid4().hex[:8]}"
|
||||
udid = sh(["xcrun", "simctl", "create", sim_name, device_type_id, runtime_id])
|
||||
if not udid:
|
||||
print("Failed to create iPhone simulator.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
print(udid)
|
||||
PY
|
||||
)"
|
||||
echo "Using iOS Simulator id: $DEST_ID"
|
||||
xcodebuild test \
|
||||
-project apps/ios/Clawdis.xcodeproj \
|
||||
-scheme Clawdis \
|
||||
-destination "platform=iOS Simulator,id=$DEST_ID" \
|
||||
-resultBundlePath "$RESULT_BUNDLE_PATH" \
|
||||
-enableCodeCoverage YES
|
||||
|
||||
- name: iOS coverage summary
|
||||
run: |
|
||||
set -euo pipefail
|
||||
RESULT_BUNDLE_PATH="$RUNNER_TEMP/Clawdis-iOS.xcresult"
|
||||
xcrun xccov view --report --only-targets "$RESULT_BUNDLE_PATH"
|
||||
|
||||
- name: iOS coverage gate (43%)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
RESULT_BUNDLE_PATH="$RUNNER_TEMP/Clawdis-iOS.xcresult"
|
||||
RESULT_BUNDLE_PATH="$RESULT_BUNDLE_PATH" python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
target_name = "Clawdis.app"
|
||||
minimum = 0.43
|
||||
|
||||
report = json.loads(
|
||||
subprocess.check_output(
|
||||
["xcrun", "xccov", "view", "--report", "--json", os.environ["RESULT_BUNDLE_PATH"]],
|
||||
text=True,
|
||||
)
|
||||
)
|
||||
|
||||
target_coverage = None
|
||||
for target in report.get("targets", []):
|
||||
if target.get("name") == target_name:
|
||||
target_coverage = float(target["lineCoverage"])
|
||||
break
|
||||
|
||||
if target_coverage is None:
|
||||
print(f"Could not find coverage for target: {target_name}")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"{target_name} line coverage: {target_coverage * 100:.2f}% (min {minimum * 100:.2f}%)")
|
||||
if target_coverage + 1e-12 < minimum:
|
||||
sys.exit(1)
|
||||
PY
|
||||
|
||||
android:
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_android == 'true'
|
||||
needs: [preflight]
|
||||
if: needs.preflight.outputs.docs_only != 'true' && needs.preflight.outputs.run_android == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
||||
2
.github/workflows/docker-release.yml
vendored
2
.github/workflows/docker-release.yml
vendored
@@ -15,7 +15,7 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: Existing release tag to backfill (for example v2026.3.13)
|
||||
description: Existing release tag to backfill (for example v2026.3.22)
|
||||
required: true
|
||||
type: string
|
||||
|
||||
|
||||
61
.github/workflows/install-smoke.yml
vendored
61
.github/workflows/install-smoke.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: install-smoke-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
group: ${{ github.event_name == 'pull_request' && format('install-smoke-pr-{0}', github.event.pull_request.number) || format('install-smoke-push-{0}', github.run_id) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
env:
|
||||
@@ -37,10 +37,46 @@ jobs:
|
||||
id: check
|
||||
uses: ./.github/actions/detect-docs-changes
|
||||
|
||||
install-smoke:
|
||||
changed-smoke:
|
||||
needs: [docs-scope]
|
||||
if: (github.event_name != 'pull_request' || !github.event.pull_request.draft) && needs.docs-scope.outputs.docs_only != 'true'
|
||||
if: needs.docs-scope.outputs.docs_only != 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
outputs:
|
||||
run_changed_smoke: ${{ steps.scope.outputs.run_changed_smoke }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
|
||||
- name: Ensure changed-smoke base commit
|
||||
uses: ./.github/actions/ensure-base-commit
|
||||
with:
|
||||
base-sha: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
|
||||
fetch-ref: ${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.base.ref }}
|
||||
|
||||
- name: Detect changed smoke scope
|
||||
id: scope
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ "${{ github.event_name }}" = "push" ]; then
|
||||
BASE="${{ github.event.before }}"
|
||||
else
|
||||
BASE="${{ github.event.pull_request.base.sha }}"
|
||||
fi
|
||||
|
||||
node scripts/ci-changed-scope.mjs --base "$BASE" --head HEAD
|
||||
|
||||
install-smoke:
|
||||
needs: [docs-scope, changed-smoke]
|
||||
if: (github.event_name != 'pull_request' || !github.event.pull_request.draft) && needs.docs-scope.outputs.docs_only != 'true' && needs.changed-smoke.outputs.run_changed_smoke == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: "false"
|
||||
DOCKER_BUILD_RECORD_UPLOAD: "false"
|
||||
steps:
|
||||
- name: Checkout CLI
|
||||
uses: actions/checkout@v6
|
||||
@@ -55,6 +91,8 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
build-args: |
|
||||
OPENCLAW_DOCKER_APT_UPGRADE=0
|
||||
tags: openclaw-dockerfile-smoke:local
|
||||
load: true
|
||||
push: false
|
||||
@@ -73,6 +111,7 @@ jobs:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
build-args: |
|
||||
OPENCLAW_DOCKER_APT_UPGRADE=0
|
||||
OPENCLAW_EXTENSIONS=matrix
|
||||
tags: openclaw-ext-smoke:local
|
||||
load: true
|
||||
@@ -147,12 +186,12 @@ jobs:
|
||||
|
||||
- name: Run installer docker tests
|
||||
env:
|
||||
CLAWDBOT_INSTALL_URL: https://openclaw.ai/install.sh
|
||||
CLAWDBOT_INSTALL_CLI_URL: https://openclaw.ai/install-cli.sh
|
||||
CLAWDBOT_NO_ONBOARD: "1"
|
||||
CLAWDBOT_INSTALL_SMOKE_SKIP_CLI: "1"
|
||||
CLAWDBOT_INSTALL_SMOKE_SKIP_IMAGE_BUILD: "1"
|
||||
CLAWDBOT_INSTALL_NONROOT_SKIP_IMAGE_BUILD: ${{ github.event_name == 'pull_request' && '0' || '1' }}
|
||||
CLAWDBOT_INSTALL_SMOKE_SKIP_NONROOT: ${{ github.event_name == 'pull_request' && '1' || '0' }}
|
||||
CLAWDBOT_INSTALL_SMOKE_SKIP_PREVIOUS: "1"
|
||||
OPENCLAW_INSTALL_URL: https://openclaw.ai/install.sh
|
||||
OPENCLAW_INSTALL_CLI_URL: https://openclaw.ai/install-cli.sh
|
||||
OPENCLAW_NO_ONBOARD: "1"
|
||||
OPENCLAW_INSTALL_SMOKE_SKIP_CLI: "1"
|
||||
OPENCLAW_INSTALL_SMOKE_SKIP_IMAGE_BUILD: "1"
|
||||
OPENCLAW_INSTALL_NONROOT_SKIP_IMAGE_BUILD: ${{ github.event_name == 'pull_request' && '0' || '1' }}
|
||||
OPENCLAW_INSTALL_SMOKE_SKIP_NONROOT: ${{ github.event_name == 'pull_request' && '1' || '0' }}
|
||||
OPENCLAW_INSTALL_SMOKE_SKIP_PREVIOUS: "1"
|
||||
run: bash scripts/test-install-sh-docker.sh
|
||||
|
||||
2
.github/workflows/openclaw-npm-release.yml
vendored
2
.github/workflows/openclaw-npm-release.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: Release tag to publish (for example v2026.3.14, v2026.3.14-beta.1, or fallback v2026.3.14-1)
|
||||
description: Release tag to publish (for example v2026.3.22, v2026.3.22-beta.1, or fallback v2026.3.22-1)
|
||||
required: true
|
||||
type: string
|
||||
|
||||
|
||||
3
.github/workflows/workflow-sanity.yml
vendored
3
.github/workflows/workflow-sanity.yml
vendored
@@ -72,6 +72,9 @@ jobs:
|
||||
- name: Disallow direct inputs interpolation in composite run blocks
|
||||
run: python3 scripts/check-composite-action-input-interpolation.py
|
||||
|
||||
- name: Disallow tracked merge conflict markers
|
||||
run: node scripts/check-no-conflict-markers.mjs
|
||||
|
||||
generated-doc-baselines:
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
- Tests: colocated `*.test.ts`.
|
||||
- Docs: `docs/` (images, queue, Pi config). Built output lives in `dist/`.
|
||||
- Nomenclature: use "plugin" / "plugins" in docs, UI, changelogs, and contributor guidance. `extensions/*` remains the internal directory/package path to avoid repo-wide churn from a rename.
|
||||
- Bundled plugin naming: for repo-owned workspace plugins, keep the canonical plugin id aligned across `openclaw.plugin.json:id`, `extensions/<id>` by default, and package names anchored to the same id (`@openclaw/<id>` or approved suffix forms like `-provider`, `-plugin`, `-speech`, `-sandbox`, `-media-understanding`). Keep `openclaw.install.npmSpec` equal to the package name and `openclaw.channel.id` equal to the plugin id when present. Exceptions must be explicit and covered by the repo invariant test.
|
||||
- Plugins: live under `extensions/*` (workspace packages). Keep plugin-only deps in the extension `package.json`; do not add them to the root `package.json` unless core uses them.
|
||||
- Plugins: install runs `npm install --omit=dev` in plugin dir; runtime deps must live in `dependencies`. Avoid `workspace:*` in `dependencies` (npm install breaks); put `openclaw` in `devDependencies` or `peerDependencies` instead (runtime resolves `openclaw/plugin-sdk` via jiti alias).
|
||||
- Import boundaries: extension production code should treat `openclaw/plugin-sdk/*` plus local `api.ts` / `runtime-api.ts` barrels as the public surface. Do not import core `src/**`, `src/plugin-sdk-internal/**`, or another extension's `src/**` directly.
|
||||
@@ -28,7 +29,7 @@
|
||||
- For docs, UI copy, and picker lists, order services/providers alphabetically unless the section is explicitly describing runtime behavior (for example auto-detection or execution order).
|
||||
- Section cross-references: use anchors on root-relative paths (example: `[Hooks](/configuration#hooks)`).
|
||||
- Doc headings and anchors: avoid em dashes and apostrophes in headings because they break Mintlify anchor links.
|
||||
- When Peter asks for links, reply with full `https://docs.openclaw.ai/...` URLs (not root-relative).
|
||||
- When the user asks for links, reply with full `https://docs.openclaw.ai/...` URLs (not root-relative).
|
||||
- When you touch docs, end the reply with the `https://docs.openclaw.ai/...` URLs you referenced.
|
||||
- README (GitHub): keep absolute docs URLs (`https://docs.openclaw.ai/...`) so links work on GitHub.
|
||||
- Docs content must be generic: no personal device names/hostnames/paths; use placeholders like `user@gateway-host` and “gateway host”.
|
||||
@@ -112,13 +113,15 @@
|
||||
|
||||
- Framework: Vitest with V8 coverage thresholds (70% lines/branches/functions/statements).
|
||||
- Naming: match source names with `*.test.ts`; e2e in `*.e2e.test.ts`.
|
||||
- When tests need example Anthropic/OpenAI model constants, prefer `sonnet-4.6` and `gpt-5.4`; update older Anthropic/GPT examples when you touch those tests.
|
||||
- Run `pnpm test` (or `pnpm test:coverage`) before pushing when you touch logic.
|
||||
- Write tests to clean up timers, env, globals, mocks, sockets, temp dirs, and module state so `--isolate=false` stays green.
|
||||
- Agents MUST NOT modify baseline, inventory, ignore, snapshot, or expected-failure files to silence failing checks without explicit approval in this chat.
|
||||
- For targeted/local debugging, keep using the wrapper: `pnpm test -- <path-or-filter> [vitest args...]` (for example `pnpm test -- src/commands/onboard-search.test.ts -t "shows registered plugin providers"`); do not default to raw `pnpm vitest run ...` because it bypasses wrapper config/profile/pool routing.
|
||||
- Do not set test workers above 16; tried already.
|
||||
- Do not switch CI `pnpm test` lanes back to Vitest `vmForks` by default without fresh green evidence on current `main`; keep CI on `forks` unless explicitly re-validated.
|
||||
- Do not reintroduce Vitest VM pools by default without fresh green evidence on current `main`; keep CI on `forks`.
|
||||
- If local Vitest runs cause memory pressure (common on non-Mac-Studio hosts), use `OPENCLAW_TEST_PROFILE=low OPENCLAW_TEST_SERIAL_GATEWAY=1 pnpm test` for land/gate runs.
|
||||
- Live tests (real keys): `CLAWDBOT_LIVE_TEST=1 pnpm test:live` (OpenClaw-only) or `LIVE=1 pnpm test:live` (includes provider live tests). Docker: `pnpm test:docker:live-models`, `pnpm test:docker:live-gateway`. Onboarding Docker E2E: `pnpm test:docker:onboard`.
|
||||
- Live tests (real keys): `OPENCLAW_LIVE_TEST=1 pnpm test:live` (OpenClaw-only) or `LIVE=1 pnpm test:live` (includes provider live tests). Docker: `pnpm test:docker:live-models`, `pnpm test:docker:live-gateway`. Onboarding Docker E2E: `pnpm test:docker:onboard`.
|
||||
- Full kit + what’s covered: `docs/help/testing.md`.
|
||||
- Changelog: user-facing changes only; no internal/meta notes (version alignment, appcast reminders, release process).
|
||||
- Changelog placement: in the active version block, append new entries to the end of the target section (`### Changes` or `### Fixes`); do not insert new entries at the top of a section.
|
||||
|
||||
358
CHANGELOG.md
358
CHANGELOG.md
@@ -4,103 +4,212 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Breaking
|
||||
|
||||
- Plugins/install: bare `openclaw plugins install <package>` now prefers ClawHub before npm for npm-safe names, and only falls back to npm when ClawHub does not have that package or version. Docs: https://docs.openclaw.ai/tools/clawhub
|
||||
- Browser/Chrome MCP: remove the legacy Chrome extension relay path, bundled extension assets, `driver: "extension"`, and `browser.relayBindHost`. Run `openclaw doctor --fix` to migrate host-local browser config to `existing-session` / `user`; Docker, headless, sandbox, and remote browser flows still use raw CDP. Docs: https://docs.openclaw.ai/gateway/doctor and https://docs.openclaw.ai/tools/browser (#47893) Thanks @vincentkoc.
|
||||
- Tools/image generation: standardize the stock image create/edit path on the core `image_generate` tool. The old `nano-banana-pro` docs/examples are gone; if you previously copied that sample-skill config, switch to `agents.defaults.imageGenerationModel` for built-in image generation or install a separate third-party skill explicitly.
|
||||
- Skills/image generation: remove the bundled `nano-banana-pro` skill wrapper. Use `agents.defaults.imageGenerationModel.primary: "google/gemini-3-pro-image-preview"` for the native Nano Banana-style path instead.
|
||||
- Plugins/SDK: the new public plugin SDK surface is `openclaw/plugin-sdk/*`; `openclaw/extension-api` is removed with no compatibility shim. Bundled plugins must use injected runtime for host-side operations (for example `api.runtime.agent.runEmbeddedPiAgent`) and any remaining direct imports must come from narrow `openclaw/plugin-sdk/*` subpaths instead of the monolithic SDK root. Docs: https://docs.openclaw.ai/plugins/sdk-migration and https://docs.openclaw.ai/plugins/sdk-overview
|
||||
- Plugins/message discovery: require `ChannelMessageActionAdapter.describeMessageTool(...)` for shared `message` tool discovery. The legacy `listActions`, `getCapabilities`, and `getToolSchema` adapter methods are removed. Plugin authors should migrate message discovery to `describeMessageTool(...)` and keep channel-specific action runtime code inside the owning plugin package. Thanks @gumadeiras.
|
||||
- Plugins/Matrix: add a new Matrix plugin backed by the official `matrix-js-sdk`. If you are upgrading from the previous public Matrix plugin, follow the migration guide: https://docs.openclaw.ai/install/migrating-matrix Thanks @gumadeiras.
|
||||
- Config/env: remove legacy `CLAWDBOT_*` and `MOLTBOT_*` compatibility env names across runtime, installers, and test tooling. Use the matching `OPENCLAW_*` env names instead.
|
||||
- Config/state: remove legacy `.moltbot` state-dir and `moltbot.json` auto-detection/migration fallback. If you still keep state under `~/.moltbot`, move it to `~/.openclaw` or set `OPENCLAW_STATE_DIR` / `OPENCLAW_CONFIG_PATH` explicitly. Docs: https://docs.openclaw.ai/install/migrating and https://docs.openclaw.ai/start/getting-started
|
||||
- Exec/env sandbox: block build-tool JVM injection (`MAVEN_OPTS`, `SBT_OPTS`, `GRADLE_OPTS`, `ANT_OPTS`), glibc tunable exploitation (`GLIBC_TUNABLES`), and .NET dependency resolution hijack (`DOTNET_ADDITIONAL_DEPS`) from the host exec environment, and restrict Gradle init script redirect (`GRADLE_USER_HOME`) as an override-only block so user-configured Gradle homes still propagate. (#49702)
|
||||
- Discord/commands: switch native command deployment to Carbon reconcile by default so Discord restarts stop churning slash commands through OpenClaw’s local deploy path. (#46597) Thanks @huntharo and @thewilloftheshadow.
|
||||
- Security/exec approvals: treat `time` as a transparent dispatch wrapper during allowlist evaluation and allow-always persistence so approved `time ...` commands bind the inner executable instead of the wrapper path. Thanks @YLChen-007 for reporting.
|
||||
- Voice-call/webhooks: reject missing provider signature headers before body reads, drop the pre-auth body budget to `64 KB` / `5s`, and cap concurrent pre-auth requests per source IP so unauthenticated callers cannot force the old `1 MB` / `30s` buffering path. Thanks @SEORY0 for reporting.
|
||||
- Plugins/Matrix: stop mention-gated or otherwise dropped room chatter from refreshing focused thread bindings before the message is actually routed, so idle ACP and session bindings can still expire normally in mention-required rooms. Thanks @vincentkoc, @dinakars777 and @mvanhorn.
|
||||
- Plugins/Matrix: durably dedupe inbound room events across gateway restarts so previously handled Matrix messages are not replayed as new, while preserving clean-restart backlog delivery for unseen events. (#50922) thanks @gumadeiras
|
||||
- Agents/media replies: migrate the remaining browser, canvas, and nodes snapshot outputs onto `details.media` so generated media keeps attaching to assistant replies after the collect-then-attach refactor. (#51731) Thanks @christianklotz.
|
||||
- Android/contacts search: escape literal `%` and `_` in contact-name queries so searches like `100%` or `_id` no longer match unrelated contacts through SQL `LIKE` wildcards. (#41891) Thanks @Kaneki-x.
|
||||
- Gateway/usage: include reset and deleted archived session transcripts in usage totals, session discovery, and archived-only session detail fallback so the Usage view no longer undercounts rotated sessions. (#43215) Thanks @rcrick.
|
||||
|
||||
### Changes
|
||||
|
||||
- Models/Anthropic Vertex: add core `anthropic-vertex` provider support for Claude via Google Vertex AI, including GCP auth/discovery and main run-path routing. (#43356) Thanks @sallyom and @yossiovadia.
|
||||
- Commands/btw: add `/btw` side questions for quick tool-less answers about the current session without changing future session context, with dismissible in-session TUI answers and explicit BTW replies on external channels. (#45444) Thanks @ngutman.
|
||||
- Gateway/docs: clarify that empty URL input allowlists are treated as unset, document `allowUrl: false` as the deny-all switch, and add regression coverage for the normalization path.
|
||||
- Sandbox/runtime: add pluggable sandbox backends, ship an OpenShell backend with `mirror` and `remote` workspace modes, and make sandbox list/recreate/prune backend-aware instead of Docker-only.
|
||||
- Sandbox/SSH: add a core SSH sandbox backend with secret-backed key, certificate, and known_hosts inputs, move shared remote exec/filesystem tooling into core, and keep OpenShell focused on sandbox lifecycle plus optional `mirror` mode.
|
||||
- Web tools/Firecrawl: add Firecrawl as an `onboard`/configure search provider via a bundled plugin, expose explicit `firecrawl_search` and `firecrawl_scrape` tools, and align core `web_fetch` fallback behavior with Firecrawl base-URL/env fallback plus guarded endpoint fetches.
|
||||
- Plugins/bundles: add compatible Codex, Claude, and Cursor bundle discovery/install support, map bundle skills into OpenClaw skills, and apply Claude bundle `settings.json` defaults to embedded Pi with shell overrides sanitized.
|
||||
- Plugins/providers: move OpenRouter, GitHub Copilot, and OpenAI Codex provider/runtime logic into bundled plugins, including dynamic model fallback, runtime auth exchange, stream wrappers, capability hints, and cache-TTL policy.
|
||||
- Plugins/agent integrations: broaden the plugin surface for app-server integrations with channel-aware commands, interactive callbacks, inbound claims, and Discord/Telegram conversation binding support. (#45318) Thanks @huntharo and @vincentkoc.
|
||||
- Install/update: allow package-manager installs from GitHub `main` via `openclaw update --tag main`, installer `--version main`, or direct npm/pnpm git specs. (#47630) Thanks @vincentkoc.
|
||||
- Gateway/health monitor: add configurable stale-event thresholds and restart limits, plus per-channel and per-account `healthMonitor.enabled` overrides, while keeping the existing global disable path on `gateway.channelHealthCheckMinutes=0`. (#42107) Thanks @rstar327.
|
||||
- Android/mobile: add a system-aware dark theme across onboarding and post-onboarding screens so the app follows the device theme through setup, chat, and voice flows. (#46249) Thanks @sibbl.
|
||||
- Feishu/ACP: add current-conversation ACP and subagent session binding for supported DMs and topic conversations, including completion delivery back to the originating Feishu conversation. (#46819) Thanks @Takhoffman.
|
||||
- ClawHub/install: add native `openclaw skills search|install|update` flows plus `openclaw plugins install clawhub:<package>` with tracked update metadata, gateway skill-install/update support for ClawHub-backed requests, and regression coverage/docs for the new source path.
|
||||
- Plugins/marketplaces: add Claude marketplace registry resolution, `plugin@marketplace` installs, marketplace listing, and update support, plus Docker E2E coverage for local and official marketplace flows. (#48058) Thanks @vincentkoc.
|
||||
- Commands/plugins: add owner-gated `/plugins` and `/plugin` chat commands for plugin list/show and enable/disable flows, alongside explicit `commands.plugins` config gating. Thanks @vincentkoc.
|
||||
- Feishu/cards: add structured interactive approval and quick-action launcher cards, preserve callback user and conversation context through routing, and keep legacy card-action fallback behavior so common actions can run without typing raw commands. (#47873) Thanks @Takhoffman.
|
||||
- Feishu/streaming: add `onReasoningStream` and `onReasoningEnd` support to streaming cards, so `/reasoning stream` renders thinking tokens as markdown blockquotes in the same card — matching the Telegram channel's reasoning lane behavior. (#46029) Thanks @day253.
|
||||
- Feishu/cards: add identity-aware structured card headers and note footers for Feishu replies and direct sends, while keeping that presentation wired through the shared outbound identity path. (#29938) Thanks @nszhsl.
|
||||
- Install/update: allow package-manager installs from GitHub `main` via `openclaw update --tag main`, installer `--version main`, or direct npm/pnpm git specs. (#47630) Thanks @vincentkoc.
|
||||
- Plugins/bundles: add compatible Codex, Claude, and Cursor bundle discovery/install support, map bundle skills into OpenClaw skills, and apply Claude bundle `settings.json` defaults to embedded Pi with shell overrides sanitized.
|
||||
- CLI/hooks: route hook-pack install and update through `openclaw plugins`, keep `openclaw hooks` focused on hook visibility and per-hook controls, and show plugin-managed hook details in CLI output.
|
||||
- Models/OpenAI: switch the default OpenAI setup model to `openai/gpt-5.4`, keep Codex on `openai-codex/gpt-5.4`, and centralize OpenAI chat, image, TTS, transcription, and embedding defaults in one shared module so future default-model updates stay low-churn. Thanks @vincentkoc.
|
||||
- Agents: add per-agent thinking/reasoning/fast defaults and auto-revert disallowed model overrides to the agent's default selection. Thanks @xuanmingguo and @vincentkoc.
|
||||
- Commands/btw: add `/btw` side questions for quick tool-less answers about the current session without changing future session context, with dismissible in-session TUI answers and explicit BTW replies on external channels. (#45444) Thanks @ngutman.
|
||||
- Sandbox/runtime: add pluggable sandbox backends, ship an OpenShell backend with `mirror` and `remote` workspace modes, and make sandbox list/recreate/prune backend-aware instead of Docker-only.
|
||||
- Sandbox/SSH: add a core SSH sandbox backend with secret-backed key, certificate, and known_hosts inputs, move shared remote exec/filesystem tooling into core, and keep OpenShell focused on sandbox lifecycle plus optional `mirror` mode.
|
||||
- Browser/existing-session: support `browser.profiles.<name>.userDataDir` so Chrome DevTools MCP can attach to Brave, Edge, and other Chromium-based browsers through their own user data directories. (#48170) Thanks @velvet-shark.
|
||||
- Plugins/bundles: make enabled bundle MCP servers expose runnable tools in embedded Pi, and default relative bundle MCP launches to the bundle root so marketplace bundles like Context7 work through Pi instead of stopping at config import.
|
||||
- Plugins/providers: move OpenRouter, GitHub Copilot, and OpenAI Codex provider/runtime logic into bundled plugins, including dynamic model fallback, runtime auth exchange, stream wrappers, capability hints, and cache-TTL policy.
|
||||
- Models/Anthropic Vertex: add core `anthropic-vertex` provider support for Claude via Google Vertex AI, including GCP auth/discovery and main run-path routing. (#43356) Thanks @sallyom and @yossiovadia.
|
||||
- Plugins/Chutes: add a bundled Chutes provider with plugin-owned OAuth/API-key auth, dynamic model discovery, and default-on extension wiring. (#41416) Thanks @Veightor.
|
||||
- Web tools/Exa: add Exa as a bundled web-search plugin with Exa-native date filters, search-mode selection, and optional content extraction under `plugins.entries.exa.config.webSearch.*`. Thanks @V-Gutierrez and @vincentkoc.
|
||||
- Web tools/Tavily: add Tavily as a bundled web-search provider with dedicated `tavily_search` and `tavily_extract` tools, using canonical plugin-owned config under `plugins.entries.tavily.config.webSearch.*`. (#49200) thanks @lakshyaag-tavily.
|
||||
- Web tools/Firecrawl: add Firecrawl as an `onboard`/configure search provider via a bundled plugin, expose explicit `firecrawl_search` and `firecrawl_scrape` tools, and align core `web_fetch` fallback behavior with Firecrawl base-URL/env fallback plus guarded endpoint fetches.
|
||||
- Models/OpenAI: add native forward-compat support for `gpt-5.4-mini` and `gpt-5.4-nano` in the OpenAI provider catalog, runtime resolution, and reasoning capability gates. Thanks @vincentkoc.
|
||||
- Control UI/chat: add an expand-to-canvas button on assistant chat bubbles and in-app session navigation from Sessions and Cron views. Thanks @BunsDev.
|
||||
- Control UI/appearance: unify theme border radii across Claw, Knot, and Dash, and add a Roundness slider to the Appearance settings so users can adjust corner radius from sharp to fully rounded. Thanks @BunsDev.
|
||||
- Control UI/usage: improve usage overview styling, localization, and responsive chat/context-notice presentation, including safer theme color handling and unclipped usage-header menus. (#51951) Thanks @BunsDev.
|
||||
- Control UI/usage: drop the empty session-detail placeholder card so the usage view stays single-column until a real session detail panel is selected. (#52013) Thanks @BunsDev.
|
||||
- Android/mobile: add a system-aware dark theme across onboarding and post-onboarding screens so the app follows the device theme through setup, chat, and voice flows. (#46249) Thanks @sibbl.
|
||||
- Android/Talk: move Talk speech synthesis behind gateway `talk.speak`, keep Talk secrets on the gateway, and switch Android playback to final-response audio instead of device-local ElevenLabs streaming. (#50849)
|
||||
- Android/nodes: add `callLog.search` plus shared Call Log permission wiring so Android nodes can search recent call history through the gateway. (#44073) Thanks @lixuankai.
|
||||
- Android/nodes: add `sms.search` plus shared SMS permission wiring so Android nodes can search device text messages through the gateway. (#48299) Thanks @lixuankai.
|
||||
- Plugins/MiniMax: merge the bundled MiniMax API and MiniMax OAuth plugin surfaces into a single default-on `minimax` plugin, while keeping legacy `minimax-portal-auth` config ids aliased for compatibility.
|
||||
- Telegram/apiRoot: add per-account custom Bot API endpoint support across send, probe, setup, doctor repair, and inbound media download paths so proxied or self-hosted Telegram deployments work end to end. (#48842) Thanks @Cypherm.
|
||||
- Telegram/topics: auto-rename DM forum topics on first message with LLM-generated labels, with per-account and per-DM `autoTopicLabel` overrides. (#51502) Thanks @Lukavyi.
|
||||
- Telegram/actions: add `topic-edit` for forum-topic renames and icon updates while sharing the same Telegram topic-edit transport used by the plugin runtime. (#47798) Thanks @obviyus.
|
||||
- Telegram/error replies: add a default-off `channels.telegram.silentErrorReplies` setting so bot error replies can be delivered silently across regular replies, native commands, and fallback sends. (#19776) Thanks @ImLukeF.
|
||||
- Feishu/cards: add structured interactive approval and quick-action launcher cards, preserve callback user and conversation context through routing, and keep legacy card-action fallback behavior so common actions can run without typing raw commands. (#47873) Thanks @Takhoffman.
|
||||
- Feishu/ACP: add current-conversation ACP and subagent session binding for supported DMs and topic conversations, including completion delivery back to the originating Feishu conversation. (#46819) Thanks @Takhoffman.
|
||||
- Feishu/streaming: add `onReasoningStream` and `onReasoningEnd` support to streaming cards, so `/reasoning stream` renders thinking tokens as markdown blockquotes in the same card — matching the Telegram channel's reasoning lane behavior. (#46029) Thanks @day253.
|
||||
- Feishu/cards: add identity-aware structured card headers and note footers for Feishu replies and direct sends, while keeping that presentation wired through the shared outbound identity path. (#29938) Thanks @nszhsl.
|
||||
- Plugins/Matrix: add `allowBots` room policy so configured Matrix bot accounts can talk to each other, with optional mention-only gating. Thanks @gumadeiras.
|
||||
- Plugins/Matrix: add per-account `allowPrivateNetwork` opt-in for private/internal homeservers, while keeping public cleartext homeservers blocked. Thanks @gumadeiras.
|
||||
- Plugins/MiniMax: add MiniMax-M2.7 and MiniMax-M2.7-highspeed models and update the default model from M2.5 to M2.7. (#49691) Thanks @liyuan97.
|
||||
- MiniMax/fast mode: map shared `/fast` and `params.fastMode` to MiniMax `-highspeed` models for M2.1, M2.5, and M2.7 API-key and OAuth runs. Thanks @vincentkoc.
|
||||
- Models/MiniMax defaults: raise bundled MiniMax M2.5/M2.7 context-window, max-token, and pricing metadata to the higher defaults shipped by the current upstream Pi SDK. Thanks @vincentkoc.
|
||||
- Models/MiniMax: add bundled `MiniMax-M2`, `MiniMax-M2.1`, and `MiniMax-M2.1-highspeed` catalog entries so OpenClaw's provider metadata and OAuth aliases stay aligned with the current upstream Pi SDK. Thanks @vincentkoc.
|
||||
- Plugins/MiniMax: merge the bundled MiniMax API and MiniMax OAuth plugin surfaces into a single default-on `minimax` plugin, while keeping legacy `minimax-portal-auth` config ids aliased for compatibility.
|
||||
- Agents/Pi compatibility: align OpenClaw's bundled MiniMax runtime behavior with the current upstream Pi 0.61.1 release so embedded runs stay in sync with the latest published Pi SDK semantics. Thanks @vincentkoc.
|
||||
- Models/GitHub Copilot: allow forward-compat dynamic model ids without code updates, while preserving configured provider and per-model overrides for those synthetic models. (#51325) Thanks @fuller-stack-dev.
|
||||
- xAI/models: sync the bundled Grok catalog to current Pi-backed IDs, limits, and pricing metadata, while keeping older Grok fast and 4.20 aliases resolving cleanly at runtime. Thanks @vincentkoc.
|
||||
- xAI/fast mode: map shared `/fast` and `params.fastMode` to the current xAI Grok fast model family so direct Grok runs can opt into the faster Pi-backed variants. Thanks @vincentkoc.
|
||||
- CLI/config: expand `config set` with SecretRef and provider builder modes, JSON/batch assignment support, and `--dry-run` validation with structured JSON output. (#49296) Thanks @joshavant.
|
||||
- Z.AI/models: sync the bundled GLM catalog to current Pi metadata, including newer 4.5/4.6 model families, updated multimodal entries, and current pricing and token limits. Thanks @vincentkoc.
|
||||
- Mistral/models: sync the bundled default Mistral metadata to current Pi pricing so the built-in default no longer advertises zero-cost usage. Thanks @vincentkoc.
|
||||
- Plugins/Xiaomi: switch the bundled Xiaomi provider to the `/v1` OpenAI-compatible endpoint and add MiMo V2 Pro plus MiMo V2 Omni to the built-in catalog. (#49214) thanks @DJjjjhao.
|
||||
- Agents/compaction: notify users when followup auto-compaction starts and finishes, keeping those notices out of TTS and preserving reply threading for the real assistant reply. (#38805) Thanks @zidongdesign.
|
||||
- Memory/plugins: let the active memory plugin register its own system-prompt section while preserving cache-clear and snapshot-load prompt isolation. (#40126) Thanks @jarimustonen.
|
||||
- Gateway/health monitor: add configurable stale-event thresholds and restart limits, plus per-channel and per-account `healthMonitor.enabled` overrides, while keeping the existing global disable path on `gateway.channelHealthCheckMinutes=0`. (#42107) Thanks @rstar327.
|
||||
- Plugins/agent integrations: broaden the plugin surface for app-server integrations with channel-aware commands, interactive callbacks, inbound claims, and Discord/Telegram conversation binding support. (#45318) Thanks @huntharo and @vincentkoc.
|
||||
- Plugins/binding: add `onConversationBindingResolved(...)` so plugins can react immediately after bind approvals or denies without blocking channel interaction acknowledgements. (#48678) Thanks @huntharo.
|
||||
- Plugins/context engines: expose `delegateCompactionToRuntime(...)` on the public plugin SDK, refactor the legacy engine to use the shared helper, and clarify `ownsCompaction` delegation semantics for non-owning engines. (#49061) Thanks @jalehman.
|
||||
- Plugins/context engines: pass the embedded runner `modelId` into context-engine `assemble()` so plugins can adapt context formatting per model. (#47437) thanks @jscianna.
|
||||
- Plugins/context engines: add transcript maintenance rewrites for context engines, preserve active-branch transcript metadata during rewrites, and harden overflow-recovery truncation to rewrite sessions under the normal session write lock. (#51191) Thanks @jalehman.
|
||||
- Skills/prompt budget: preserve all registered skills via a compact catalog fallback before dropping entries when the full prompt format exceeds `maxSkillsPromptChars`. (#47553) Thanks @snese.
|
||||
- Hooks/workspace: keep repo-local `<workspace>/hooks` disabled until explicitly enabled, block workspace hook name collisions from shadowing bundled/managed/plugin hooks, and treat `hooks.internal.load.extraDirs` as trusted managed hook sources.
|
||||
- Security/plugins: reject remote marketplace manifest entries that expand installation outside the cloned marketplace repo, including external git/GitHub sources, HTTP archives, and absolute paths.
|
||||
- Gateway/docs: clarify that empty URL input allowlists are treated as unset, document `allowUrl: false` as the deny-all switch, and add regression coverage for the normalization path.
|
||||
- secrets: harden read-only SecretRef command paths and diagnostics. (#47794) Thanks @joshavant.
|
||||
- Scope message SecretRef resolution and harden doctor/status paths. (#48728) Thanks @joshavant.
|
||||
- Build/memory tools: emit `dist/cli/memory-cli.js` as a stable core entry so runtime `memory_search` loading no longer depends on hashed `memory-cli-*` bundle names. (#51759) Thanks @oliviareid-svg.
|
||||
- Plugins/testing: add a public `openclaw/plugin-sdk/testing` surface for plugin-author test helpers, and move bundled-extension-only test bridges out of `extensions/` into private repo test helpers.
|
||||
- Agents/steering docs: update embedded Pi steering docs and runner comments for the current upstream behavior, where queued steering is injected after the active assistant turn finishes its tool calls instead of skipping the remaining tools mid-turn. Thanks @vincentkoc.
|
||||
- Doctor/refactor: start splitting doctor provider checks into `src/commands/doctor/providers/*` by extracting Telegram first-run and group allowlist warnings into a provider-specific module, keeping the current setup guidance and warning behavior intact. Thanks @vincentkoc.
|
||||
- Refactor/channels: remove the legacy channel shim directories and point channel-specific imports directly at the extension-owned implementations. (#45967) Thanks @scoootscooob.
|
||||
- Docs/Zalo: clarify the Marketplace-bot support matrix and config guidance so the Zalo channel docs match current Bot Creator behavior more closely. (#47552) Thanks @No898.
|
||||
- secrets: harden read-only SecretRef command paths and diagnostics. (#47794) Thanks @joshavant.
|
||||
- Browser/existing-session: support `browser.profiles.<name>.userDataDir` so Chrome DevTools MCP can attach to Brave, Edge, and other Chromium-based browsers through their own user data directories. (#48170) Thanks @velvet-shark.
|
||||
- Skills/prompt budget: preserve all registered skills via a compact catalog fallback before dropping entries when the full prompt format exceeds `maxSkillsPromptChars`. (#47553) Thanks @snese.
|
||||
- Models/OpenAI: add native forward-compat support for `gpt-5.4-mini` and `gpt-5.4-nano` in the OpenAI provider catalog, runtime resolution, and reasoning capability gates. Thanks @vincentkoc.
|
||||
- Plugins/bundles: make enabled bundle MCP servers expose runnable tools in embedded Pi, and default relative bundle MCP launches to the bundle root so marketplace bundles like Context7 work through Pi instead of stopping at config import.
|
||||
- Scope message SecretRef resolution and harden doctor/status paths. (#48728) Thanks @joshavant.
|
||||
- Plugins/testing: add a public `openclaw/plugin-sdk/testing` surface for plugin-author test helpers, and move bundled-extension-only test bridges out of `extensions/` into private repo test helpers.
|
||||
- Plugins/Chutes: add a bundled Chutes provider with plugin-owned OAuth/API-key auth, dynamic model discovery, and default-on extension wiring. (#41416) Thanks @Veightor.
|
||||
- Plugins/binding: add `onConversationBindingResolved(...)` so plugins can react immediately after bind approvals or denies without blocking channel interaction acknowledgements. (#48678) Thanks @huntharo.
|
||||
- CLI/config: expand `config set` with SecretRef and provider builder modes, JSON/batch assignment support, and `--dry-run` validation with structured JSON output. (#49296) Thanks @joshavant.
|
||||
- Control UI/appearance: unify theme border radii across Claw, Knot, and Dash, and add a Roundness slider to the Appearance settings so users can adjust corner radius from sharp to fully rounded. Thanks @BunsDev.
|
||||
- Control UI/chat: add an expand-to-canvas button on assistant chat bubbles and in-app session navigation from Sessions and Cron views. Thanks @BunsDev.
|
||||
- Plugins/context engines: expose `delegateCompactionToRuntime(...)` on the public plugin SDK, refactor the legacy engine to use the shared helper, and clarify `ownsCompaction` delegation semantics for non-owning engines. (#49061) Thanks @jalehman.
|
||||
- Plugins/MiniMax: add MiniMax-M2.7 and MiniMax-M2.7-highspeed models and update the default model from M2.5 to M2.7. (#49691) Thanks @liyuan97.
|
||||
- Plugins/Xiaomi: switch the bundled Xiaomi provider to the `/v1` OpenAI-compatible endpoint and add MiMo V2 Pro plus MiMo V2 Omni to the built-in catalog. (#49214) thanks @DJjjjhao.
|
||||
- Android/Talk: move Talk speech synthesis behind gateway `talk.speak`, keep Talk secrets on the gateway, and switch Android playback to final-response audio instead of device-local ElevenLabs streaming. (#50849)
|
||||
- Plugins/Matrix: add `allowBots` room policy so configured Matrix bot accounts can talk to each other, with optional mention-only gating. Thanks @gumadeiras.
|
||||
- Plugins/Matrix: add per-account `allowPrivateNetwork` opt-in for private/internal homeservers, while keeping public cleartext homeservers blocked. Thanks @gumadeiras.
|
||||
- Web tools/Tavily: add Tavily as a bundled web-search provider with dedicated `tavily_search` and `tavily_extract` tools, using canonical plugin-owned config under `plugins.entries.tavily.config.webSearch.*`. (#49200) thanks @lakshyaag-tavily.
|
||||
- Docs/plugins: add the community DingTalk plugin listing to the docs catalog. (#29913) Thanks @sliverp.
|
||||
- Docs/plugins: add the community QQbot plugin listing to the docs catalog. (#29898) Thanks @sliverp.
|
||||
- Plugins/context engines: pass the embedded runner `modelId` into context-engine `assemble()` so plugins can adapt context formatting per model. (#47437) thanks @jscianna.
|
||||
- Plugins/context engines: add transcript maintenance rewrites for context engines, preserve active-branch transcript metadata during rewrites, and harden overflow-recovery truncation to rewrite sessions under the normal session write lock. (#51191) Thanks @jalehman.
|
||||
- Telegram/apiRoot: add per-account custom Bot API endpoint support across send, probe, setup, doctor repair, and inbound media download paths so proxied or self-hosted Telegram deployments work end to end. (#48842) Thanks @Cypherm.
|
||||
- Telegram/topics: auto-rename DM forum topics on first message with LLM-generated labels, with per-account and per-DM `autoTopicLabel` overrides. (#51502) Thanks @Lukavyi.
|
||||
- Docs/plugins: add the community wecom plugin listing to the docs catalog. (#29905) Thanks @sliverp.
|
||||
- Models/GitHub Copilot: allow forward-compat dynamic model ids without code updates, while preserving configured provider and per-model overrides for those synthetic models. (#51325) Thanks @fuller-stack-dev.
|
||||
- Agents/compaction: notify users when followup auto-compaction starts and finishes, keeping those notices out of TTS and preserving reply threading for the real assistant reply. (#38805) Thanks @zidongdesign.
|
||||
- Models/OpenAI: switch the default OpenAI setup model to `openai/gpt-5.4`, keep Codex on `openai-codex/gpt-5.4`, and centralize OpenAI chat, image, TTS, transcription, and embedding defaults in one shared module so future default-model updates stay low-churn. Thanks @vincentkoc.
|
||||
- Memory/plugins: let the active memory plugin register its own system-prompt section while preserving cache-clear and snapshot-load prompt isolation. (#40126) Thanks @jarimustonen.
|
||||
- Control UI/usage: improve usage overview styling, localization, and responsive chat/context-notice presentation, including safer theme color handling and unclipped usage-header menus. (#51951) Thanks @BunsDev.
|
||||
- Agents: add per-agent thinking/reasoning/fast defaults and auto-revert disallowed model overrides to the agent's default selection. Thanks @xuanmingguo and @vincentkoc.
|
||||
- Control UI/usage: drop the empty session-detail placeholder card so the usage view stays single-column until a real session detail panel is selected. (#52013) Thanks @BunsDev.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Web tools/search provider lists: keep onboarding, configure, and docs provider lists alphabetical while preserving the separate runtime auto-detect precedence used for credential-based provider selection.
|
||||
- Media/Windows security: block remote-host `file://` media URLs and UNC/network paths before local filesystem resolution in core media loading and adjacent prompt/sandbox attachment seams, so the next release no longer allows structured local-media inputs to trigger outbound SMB credential handshakes on Windows. Thanks @RacerZ-fighting for reporting.
|
||||
- Gateway/discovery: fail closed on unresolved Bonjour and DNS-SD service endpoints in CLI discovery, onboarding, and `gateway status` so TXT-only hints can no longer steer routing or SSH auto-target selection. Thanks @nexrin for reporting.
|
||||
- Security/pairing: bind iOS setup codes to the intended node profile and reject first-use bootstrap redemption that asks for broader roles or scopes. Thanks @tdjackey.
|
||||
- Memory/core tools: register `memory_search` and `memory_get` independently so one unavailable memory tool no longer suppresses the other in new sessions. (#50198) Thanks @artwalker.
|
||||
- Web tools/Exa: align the bundled Exa plugin with the current Exa API by supporting newer search types and richer `contents` options, while fixing the result-count cap to honor Exa's higher limit. Thanks @vincentkoc.
|
||||
- Plugins/Matrix: move bundled plugin `KeyedAsyncQueue` imports onto the stable `plugin-sdk/core` surface so Matrix Docker/runtime builds do not depend on the brittle keyed-async-queue subpath. Thanks @ecohash-co and @vincentkoc.
|
||||
- Nostr/security: enforce inbound DM policy before decrypt, route Nostr DMs through the standard reply pipeline, and add pre-crypto rate and size guards so unknown senders cannot bypass pairing or force unbounded crypto work. Thanks @kuranikaran.
|
||||
- Synology Chat/security: keep reply delivery bound to stable numeric `user_id` by default, and gate mutable username/nickname recipient lookup behind `dangerouslyAllowNameMatching` with new regression coverage. Thanks @nexrin.
|
||||
- Agents/default timeout: raise the shared default agent timeout from `600s` to `48h` so long-running ACP and agent sessions do not fail unless you configure a shorter limit.
|
||||
- Gateway/Linux: auto-detect nvm-managed Node TLS CA bundle needs before CLI startup and refresh installed services that are missing `NODE_EXTRA_CA_CERTS`. (#51146) Thanks @GodsBoy.
|
||||
- Gateway/startup: load bundled channel plugins from compiled `dist/extensions` entries in built installs, so gateway boot no longer recompiles bundled extension TypeScript on every startup and WhatsApp-class cold starts drop back to seconds instead of tens of seconds or worse. (#47560) Thanks @ngutman.
|
||||
- Gateway/startup: prewarm the configured primary model before channel startup and retry one transient provider-runtime miss so the first Telegram or Discord message after boot no longer fails with `Unknown model: openai-codex/gpt-5.4`. Thanks @vincentkoc.
|
||||
- CLI/startup: lazy-load channel add and root help startup paths to trim avoidable RSS and help latency on constrained hosts. (#46784) Thanks @vincentkoc.
|
||||
- Configure/startup: move outbound send-deps resolution into a lightweight helper so `openclaw configure` no longer stalls after the banner while eagerly loading channel plugins. (#46301) Thanks @scoootscooob.
|
||||
- CLI/auth choice: lazy-load plugin/provider fallback resolution so mapped auth choices stay on the static path and only unknown choices pay the heavy provider load. (#47495) Thanks @vincentkoc.
|
||||
- Gateway/Discord startup: load only configured channel plugins during gateway boot, and lazy-load Discord provider/session runtime setup so startup stops importing unrelated providers and trims cold-start delay. Thanks @vincentkoc.
|
||||
- Agents/inbound: lazy-load media and link understanding for plain-text turns and cache synced auth stores by auth-file state so ordinary inbound replies avoid unnecessary startup churn. Thanks @vincentkoc.
|
||||
- Agents/openai-compatible tool calls: deduplicate repeated tool call ids across live assistant messages and replayed history so OpenAI-compatible backends no longer reject duplicate `tool_call_id` values with HTTP 400. (#40996) Thanks @xaeon2026.
|
||||
- Agents/openai-responses: strip `prompt_cache_key` and `prompt_cache_retention` for non-OpenAI-compatible Responses endpoints while keeping them on direct OpenAI and Azure OpenAI paths, so third-party OpenAI-compatible providers no longer reject those requests with HTTP 400. (#49877) Thanks @ShaunTsai.
|
||||
- Models/openai-completions: default non-native OpenAI-compatible providers to omit tool-definition `strict` fields unless users explicitly opt back in, so tool calling keeps working on providers that reject that option. (#45497) Thanks @sahancava.
|
||||
- Models/OpenRouter runtime capabilities: fetch uncatalogued OpenRouter model metadata on first use so newly added vision models keep image input instead of silently degrading to text-only, with top-level capability field fallbacks for `/api/v1/models`. (#45824) Thanks @DJjjjhao.
|
||||
- Control UI/session routing: preserve established external delivery routes when webchat views or sends in externally originated sessions, so subagent completions still return to the original channel instead of the dashboard. (#47797) Thanks @brokemac79.
|
||||
- Telegram/replies: set `allow_sending_without_reply` on reply-targeted sends and media-error notices so deleted parent messages no longer drop otherwise valid replies. (#52524) Thanks @moltbot886.
|
||||
- Telegram/polling: hard-timeout stuck `getUpdates` requests so wedged network paths fail over sooner instead of waiting for the polling stall watchdog. Thanks @vincentkoc.
|
||||
- Android/location: make current-location requests drop late callbacks after timeout instead of crashing with `Already resumed`. (#52318) Thanks @Kaneki-x.
|
||||
- Android/pairing: resolve portless secure setup URLs to `443` while preserving direct cleartext gateway defaults and explicit `:80` manual endpoints in onboarding. (#43540) Thanks @fmercurio.
|
||||
- Android/canvas: ignore bridge messages from pages outside the bundled scaffold and trusted A2UI surfaces. Thanks @vincentkoc.
|
||||
- CLI/status: keep `status --json` stdout clean by skipping plugin compatibility scans that were not rendered in the JSON payload. (#52449) Thanks @cgdusek.
|
||||
- WhatsApp/reconnect: restore the append recency filter in the extension inbox monitor and handle protobuf `Long` timestamps correctly, so fresh post-reconnect append messages are processed while stale history sync stays suppressed. (#42588) Thanks @MonkeyLeeT.
|
||||
- WhatsApp/login: wait for pending creds writes before reopening after Baileys `515` pairing restarts in both QR login and `channels login` flows, and keep the restart coverage pinned to the real wrapped error shape plus per-account creds queues. (#27910) Thanks @asyncjason.
|
||||
- Android/canvas: serialize A2UI action-status event strings before evaluating WebView JS, so action ids and multiline errors do not break the callback dispatch. (#43784) Thanks @Kaneki-x.
|
||||
- Android/camera: recycle intermediate and final snap bitmaps in `camera.snap` so repeated captures do not leak native image memory. (#41902) Thanks @Kaneki-x.
|
||||
- Control UI/logging: make browser-safe logger imports avoid eager temp-dir resolution so the bundled Control UI no longer crashes to a blank screen when logging reaches `tmp-openclaw-dir`. (#48469) Fixes #48062. Thanks @7inspire.
|
||||
- Control UI/chat sessions: show human-readable labels in the grouped session dropdown again, keep unique scoped fallbacks when metadata is missing, and disambiguate duplicate labels only when needed. (#45130) Thanks @luzhidong.
|
||||
- Telegram/replies: ignore malformed non-string reply text and caption fields when describing reply context, so unexpected Telegram reply payloads no longer break inbound context assembly. (#50500) Thanks @p3nchan.
|
||||
- Control UI/dashboard: preserve structured gateway shutdown reasons across restart disconnects so config-triggered restarts no longer fall back to `disconnected (1006): no reason`. (#46580) Fixes #46532. Thanks @vincentkoc.
|
||||
- Android/chat: theme the thinking dropdown and TLS trust dialogs explicitly so popup surfaces match the active app theme instead of falling back to mismatched Material defaults.
|
||||
- Node/startup: remove leftover debug `console.log("node host PATH: ...")` that printed the resolved PATH on every `openclaw node run` invocation. (#46515) Fixes #46411. Thanks @ademczuk.
|
||||
- Slack/startup: harden `@slack/bolt` import interop across current bundled runtime shapes so Slack monitors no longer crash with `App is not a constructor` after plugin-sdk bundling changes. (#45953) Thanks @merc1305.
|
||||
- Control UI/model switching: preserve the selected provider prefix when switching models from the chat dropdown, so multi-provider setups no longer send `anthropic/gpt-5.2`-style mismatches when the user picked `openai/gpt-5.2`. (#47581) Thanks @chrishham.
|
||||
- Control UI/storage: scope persisted settings keys by gateway base path, with migration from the legacy shared key, so multiple gateways under one domain stop overwriting each other's dashboard preferences. (#47932) Thanks @bobBot-claw.
|
||||
- Control UI/overview: keep the language dropdown aligned with the persisted locale during dashboard startup so refreshing the page does not fall back to English before locale hydration completes. (#48019) Thanks @git-jxj.
|
||||
- macOS/node service startup: use `openclaw node start/stop --json` from the Mac app instead of the removed `openclaw service node ...` command shape, so current CLI installs expose the full node exec surface again. (#46843) Fixes #43171. Thanks @Br1an67.
|
||||
- ACP/gateway startup: use direct Telegram and Discord startup/status helpers instead of routing probes through the plugin runtime, and prepend the selected daemon Node bin dir to service PATH so plugin-local installs can still find `npm` and `pnpm`.
|
||||
- WhatsApp/active-listener: pin the active listener registry to a `globalThis` singleton so split WhatsApp bundle chunks share one listener map and outbound sends stop missing the registered session. (#47433) Thanks @clawdia67.
|
||||
- Gateway/probe: honor caller `--timeout` for active local loopback probes in `gateway status`, keep inactive remote-mode loopback probes fast, and clamp probe timers to JS-safe bounds so slow local/container gateways stop reporting false timeouts. (#47533) Thanks @MonkeyLeeT.
|
||||
- Config/startup: keep bundled web-search allowlist compatibility on a lightweight manifest path so config validation no longer pulls bundled web-search registry imports into startup, while still avoiding accidental auto-allow of config-loaded override plugins. (#51574) Thanks @RichardCao.
|
||||
- Gateway/chat.send: persist uploaded image references across reloads and compaction without delaying first-turn dispatch or double-submitting the same image to vision models. (#51324) Thanks @fuller-stack-dev.
|
||||
- Android/canvas: recycle captured and scaled snapshot bitmaps so repeated canvas snapshots do not leak native image memory. (#41889) Thanks @Kaneki-x.
|
||||
- Android/theme: switch status bar icon contrast with the active system theme so Android light mode no longer leaves unreadable light icons over the app header. (#51098) Thanks @goweii.
|
||||
- Gateway/openresponses: preserve assistant commentary and session continuity across hosted-tool `/v1/responses` turns, and emit streamed tool-call payloads before finalization so client tool loops stay resumable. (#52171) Thanks @CharZhou.
|
||||
- Android/Talk: serialize `TalkModeManager` player teardown so rapid interrupt/restart cycles stop double-releasing or overlapping TTS playback. (#52310) Thanks @Kaneki-x.
|
||||
- WhatsApp/reconnect: preserve the last inbound timestamp across reconnect attempts so the watchdog can still recycle linked-but-dead listeners after a restart instead of leaving them stuck connected forever.
|
||||
- Gateway/network discovery: guard LAN, tailnet, and pairing interface enumeration so WSL2 and restricted hosts degrade to missing-address fallbacks instead of crashing on `uv_interface_addresses` errors. (#44180, #47590)
|
||||
- Gateway/bonjour: suppress the non-fatal `@homebridge/ciao` IPv4-loss assertion during interface churn so WiFi/VPN/sleep-wake changes no longer take down the gateway. (#38628, #47159, #52431)
|
||||
- Browser/launch: stop forcing an extra blank tab on browser launch so managed browser startup no longer opens an unwanted empty page. (#52451) Thanks @rogerdigital.
|
||||
- CLI/onboarding: import static provider definitions directly for onboarding model/config helpers so those paths no longer pull provider discovery just for built-in defaults. (#47467) Thanks @vincentkoc.
|
||||
- Agents/exec: return plain-text failed tool output for timeouts and other non-success exec outcomes so models no longer parrot raw JSON error payloads back to users. (#52508) Thanks @martingarramon.
|
||||
- CLI/config: make `config set --strict-json` enforce real JSON, prefer `JSON.parse` with JSON5 fallback for machine-written cron/subagent stores, and relabel raw config surfaces as `JSON/JSON5` to match actual compatibility. Related: #48415, #43127, #14529, #21332. Thanks @adhitShet and @vincentkoc.
|
||||
- CLI/Ollama onboarding: keep the interactive model picker for explicit `openclaw onboard --auth-choice ollama` runs so setup still selects a default model without reintroducing pre-picker auto-pulls. (#49249) Thanks @BruceMacD.
|
||||
- Plugins/bundler TDZ: fix `RESERVED_COMMANDS` temporal dead zone error that prevented device-pair, phone-control, and talk-voice plugins from registering when the bundler placed the commands module after call sites in the same output chunk. Thanks @BunsDev.
|
||||
- Plugins/imports: fix stale googlechat runtime-api import paths and signal SDK circular re-exports broken by recent plugin-sdk refactors. Thanks @BunsDev.
|
||||
- Telegram/setup: seed fresh setups with `channels.telegram.groups["*"].requireMention=true` so new bots stay mention-gated in groups unless you explicitly open them up. Thanks @vincentkoc.
|
||||
- Google auth/Node 25: patch `gaxios` to use native fetch without injecting `globalThis.window`, while translating proxy and mTLS transport settings so Google Vertex and Google Chat auth keep working on Node 25. (#47914) Thanks @pdd-cli.
|
||||
- Gateway/startup: load bundled channel plugins from compiled `dist/extensions` entries in built installs, so gateway boot no longer recompiles bundled extension TypeScript on every startup and WhatsApp-class cold starts drop back to seconds instead of tens of seconds or worse. (#47560) Thanks @ngutman.
|
||||
- Agents/openai-responses: strip `prompt_cache_key` and `prompt_cache_retention` for non-OpenAI-compatible Responses endpoints while keeping them on direct OpenAI and Azure OpenAI paths, so third-party OpenAI-compatible providers no longer reject those requests with HTTP 400. (#49877) Thanks @ShaunTsai.
|
||||
- Plugins/context engines: enforce owner-aware context-engine registration on both loader and public SDK paths so plugins cannot spoof privileged ownership, claim the core `legacy` engine id, or overwrite an existing engine id through direct SDK imports. (#47595) Thanks @vincentkoc.
|
||||
- Browser/remote CDP: honor strict browser SSRF policy during remote CDP reachability and `/json/version` discovery checks, redact sensitive `cdpUrl` tokens from status output, and warn when remote CDP targets private/internal hosts.
|
||||
- Gateway/plugins: pin runtime webhook routes to the gateway startup registry so channel webhooks keep working across plugin-registry churn, and make plugin auth + dispatch resolve routes from the same live HTTP-route registry. (#47902) Fixes #46924 and #47041. Thanks @steipete.
|
||||
- Gateway/auth: ignore spoofed loopback hops in trusted forwarding chains and block device approvals that request scopes above the caller session. (#46800) Thanks @vincentkoc.
|
||||
- Gateway/restart: defer externally signaled unmanaged restarts through the in-process idle drain, and preserve the restored subagent run as remap fallback during orphan recovery so resumed sessions do not duplicate work. (#47719) Thanks @joeykrug.
|
||||
- Control UI/session routing: preserve established external delivery routes when webchat views or sends in externally originated sessions, so subagent completions still return to the original channel instead of the dashboard. (#47797) Thanks @brokemac79.
|
||||
- Configure/startup: move outbound send-deps resolution into a lightweight helper so `openclaw configure` no longer stalls after the banner while eagerly loading channel plugins. (#46301) Thanks @scoootscooob.
|
||||
- CLI/startup: lazy-load channel add and root help startup paths to trim avoidable RSS and help latency on constrained hosts. (#46784) Thanks @vincentkoc.
|
||||
- CLI/onboarding: import static provider definitions directly for onboarding model/config helpers so those paths no longer pull provider discovery just for built-in defaults. (#47467) Thanks @vincentkoc.
|
||||
- CLI/configure: clarify fresh-setup memory-search warnings so they say semantic recall needs at least one embedding provider, and scope the initial model allowlist picker to the provider selected in configure. Thanks @vincentkoc.
|
||||
- CLI/auth choice: lazy-load plugin/provider fallback resolution so mapped auth choices stay on the static path and only unknown choices pay the heavy provider load. (#47495) Thanks @vincentkoc.
|
||||
- Mattermost/threading: honor `replyToMode: "off"` for already-threaded inbound posts so threaded follow-ups can fall back to top-level replies when configured. (#52543) Thanks @RichardCao.
|
||||
- Onboarding/custom providers: store Azure OpenAI and Azure AI Foundry custom endpoints with the Responses API config shape, normalized `/openai/v1` base URLs, and Azure-safe defaults so TUI and agent runs work after setup. (#49543) Thanks @kunalk16.
|
||||
- CLI/completion: reduce recursive completion-script string churn and fix nested PowerShell command-path matching so generated nested completions resolve on PowerShell too. (#45537) Thanks @yiShanXin and @vincentkoc.
|
||||
- macOS/launch at login: stop emitting `KeepAlive` for the desktop app launch agent so OpenClaw no longer relaunches immediately after a manual quit while launch at login remains enabled. (#40213) Thanks @stablegenius49.
|
||||
- Mattermost/DM send: retry transient direct-channel creation failures for DM deliveries, with configurable backoff and per-request timeout. (#42398) Thanks @JonathanJing.
|
||||
- Secrets/exec refs: require explicit `--allow-exec` for `secrets apply` write plans that contain exec SecretRefs/providers, and align audit/configure/apply dry-run behavior to skip exec checks unless opted in to prevent unexpected command side effects. (#49417) Thanks @restriction and @joshavant.
|
||||
- Signal/runtime API: re-export `SignalAccountConfig` so Signal account resolution type-checks again. (#49470) Thanks @scoootscooob.
|
||||
- Google Chat/runtime API: thin the private runtime barrel onto the curated public SDK surface while keeping public Google Chat exports intact. (#49504) Thanks @scoootscooob.
|
||||
- Onboarding/custom providers: keep Azure AI Foundry `*.services.ai.azure.com` custom endpoints on the selected compatibility path instead of forcing Responses, so chat-completions Foundry models still work after setup. Fixes #50528. (#50535) Thanks @obviyus.
|
||||
- make `openclaw update status` explicitly say `up to date` when the local version already matches npm latest, while keeping the availability logic unchanged. (#51409) Thanks @dongzhenye.
|
||||
- Agents/embedded transport errors: distinguish common network failures like connection refused, DNS lookup failure, and interrupted sockets from true timeouts in embedded-run user messaging and lifecycle diagnostics. (#51419) Thanks @scoootscooob.
|
||||
- Security/pairing: bind iOS setup codes to the intended node profile and reject first-use bootstrap redemption that asks for broader roles or scopes. Thanks @tdjackey.
|
||||
- Nostr/security: enforce inbound DM policy before decrypt, route Nostr DMs through the standard reply pipeline, and add pre-crypto rate and size guards so unknown senders cannot bypass pairing or force unbounded crypto work. Thanks @kuranikaran.
|
||||
- Synology Chat/security: keep reply delivery bound to stable numeric `user_id` by default, and gate mutable username/nickname recipient lookup behind `dangerouslyAllowNameMatching` with new regression coverage. Thanks @nexrin.
|
||||
- Browser/node proxy: enforce `nodeHost.browserProxy.allowProfiles` across `query.profile` and `body.profile`, block proxy-side profile create/delete when the allowlist is set, and keep the default full proxy surface when the allowlist is empty.
|
||||
- Security/device pairing: harden `device.token.rotate` deny handling by keeping public failures generic while logging internal deny reasons and preserving approved-baseline enforcement. (`GHSA-7jrw-x62h-64p8`)
|
||||
- Security/exec safe bins: remove `jq` from the default safe-bin allowlist and fail closed on the `jq` `env` builtin when operators explicitly opt `jq` back in, so `jq -n env` cannot dump host secrets without an explicit trust path. Thanks @gladiator9797 for reporting.
|
||||
- Security/exec approvals: escape blank Hangul filler code points in approval prompts across gateway/chat and the macOS native approval UI so visually empty Unicode padding cannot hide reviewed command text.
|
||||
- Security/exec approvals: unify transparent dispatch-wrapper handling across resolution and allow-always persistence so wrapper metadata cannot silently drift and broaden approvals.
|
||||
- Security/exec: harden macOS allowlist resolution against wrapper and `env` spoofing, require fresh approval for inline interpreter eval with `tools.exec.strictInlineEval`, wrap Discord guild message bodies as untrusted external content, and add audit findings for risky exec approval and open-channel combinations.
|
||||
- Security/network: harden explicit-proxy SSRF pinning by translating target-hop transport hints onto HTTPS proxy tunnels and failing closed for plain HTTP guarded fetches that cannot preserve pinned DNS.
|
||||
- Security/Synology Chat: require explicit per-account webhook paths for multi-account setups by default, reject duplicate exact webhook paths fail-closed, and keep inherited-path behavior behind an explicit dangerous opt-in so shared routes can no longer collapse DM policy contexts across accounts. Thanks @tdjackey for reporting.
|
||||
- Browser/remote CDP: honor strict browser SSRF policy during remote CDP reachability and `/json/version` discovery checks, redact sensitive `cdpUrl` tokens from status output, and warn when remote CDP targets private/internal hosts.
|
||||
- Media/security: bound remote-media error-body snippets with the same streaming caps and idle timeouts as successful downloads, so malicious HTTP error responses cannot force unbounded buffering before OpenClaw throws.
|
||||
- Gateway/auth: ignore spoofed loopback hops in trusted forwarding chains and block device approvals that request scopes above the caller session. (#46800) Thanks @vincentkoc.
|
||||
- Gateway/auth: clear self-declared scopes for device-less trusted-proxy Control UI sessions so proxy-authenticated connects cannot claim admin or secrets scopes without a bound device identity.
|
||||
- Hardening: refresh stale device pairing requests and pending metadata (#50695) Thanks @smaeljaish771 and @joshavant.
|
||||
- Gateway/auth: add regression coverage that keeps device-less trusted-proxy Control UI sessions off privileged pairing approval RPCs. Thanks @vincentkoc.
|
||||
- Media/Windows security: block remote-host `file://` media URLs and UNC/network paths before local filesystem resolution in core media loading and adjacent prompt/sandbox attachment seams, so the next release no longer allows structured local-media inputs to trigger outbound SMB credential handshakes on Windows. Thanks @RacerZ-fighting for reporting.
|
||||
- Web tools/Exa: align the bundled Exa plugin with the current Exa API by supporting newer search types and richer `contents` options, while fixing the result-count cap to honor Exa's higher limit. Thanks @vincentkoc.
|
||||
- Agents/default timeout: raise the shared default agent timeout from `600s` to `48h` so long-running ACP and agent sessions do not fail unless you configure a shorter limit.
|
||||
- CLI: avoid loading provider discovery during startup model normalization. (#46522) Thanks @ItsAditya-xyz and @vincentkoc.
|
||||
- Agents/Telegram: avoid rebuilding the full model catalog on ordinary inbound replies so Telegram message handling no longer pays multi-second core startup latency before reply generation. Thanks @vincentkoc.
|
||||
- Gateway/Discord startup: load only configured channel plugins during gateway boot, and lazy-load Discord provider/session runtime setup so startup stops importing unrelated providers and trims cold-start delay. Thanks @vincentkoc.
|
||||
- Security/exec: harden macOS allowlist resolution against wrapper and `env` spoofing, require fresh approval for inline interpreter eval with `tools.exec.strictInlineEval`, wrap Discord guild message bodies as untrusted external content, and add audit findings for risky exec approval and open-channel combinations.
|
||||
- Agents/inbound: lazy-load media and link understanding for plain-text turns and cache synced auth stores by auth-file state so ordinary inbound replies avoid unnecessary startup churn. Thanks @vincentkoc.
|
||||
- Telegram/polling: hard-timeout stuck `getUpdates` requests so wedged network paths fail over sooner instead of waiting for the polling stall watchdog. Thanks @vincentkoc.
|
||||
- Agents/models: cache `models.json` readiness by config and auth-file state so embedded runner turns stop paying repeated model-catalog startup work before replies. Thanks @vincentkoc.
|
||||
- Security/device pairing: harden `device.token.rotate` deny handling by keeping public failures generic while logging internal deny reasons and preserving approved-baseline enforcement. (`GHSA-7jrw-x62h-64p8`)
|
||||
- Gateway/status: tolerate network interface discovery failures in status, onboarding control-UI links, and self-presence display paths so those surfaces fall back cleanly instead of crashing. (#52195) Thanks @meng-clb.
|
||||
- Gateway/Linux: auto-detect nvm-managed Node TLS CA bundle needs before CLI startup and refresh installed services that are missing `NODE_EXTRA_CA_CERTS`. (#51146) Thanks @GodsBoy.
|
||||
- Google auth/Node 25: patch `gaxios` to use native fetch without injecting `globalThis.window`, while translating proxy and mTLS transport settings so Google Vertex and Google Chat auth keep working on Node 25. (#47914) Thanks @pdd-cli.
|
||||
- Gateway/status: resolve env-backed `gateway.auth.*` SecretRefs before read-only probe auth checks so status no longer reports false probe failures when auth is configured through SecretRef. (#52513) Thanks @CodeForgeNet.
|
||||
- Gateway/plugins: pin runtime webhook routes to the gateway startup registry so channel webhooks keep working across plugin-registry churn, and make plugin auth + dispatch resolve routes from the same live HTTP-route registry. (#47902) Fixes #46924 and #47041. Thanks @steipete.
|
||||
- Gateway/restart: defer externally signaled unmanaged restarts through the in-process idle drain, and preserve the restored subagent run as remap fallback during orphan recovery so resumed sessions do not duplicate work. (#47719) Thanks @joeykrug.
|
||||
- Telegram/setup: seed fresh setups with `channels.telegram.groups["*"].requireMention=true` so new bots stay mention-gated in groups unless you explicitly open them up. Thanks @vincentkoc.
|
||||
- Inbound policy hardening: tighten callback and webhook sender checks across Mattermost and Google Chat, match Nextcloud Talk rooms by stable room token, and treat explicit empty Twitch allowlists as deny-all. (#46787) Thanks @zpbrent, @ijxpwastaken and @vincentkoc.
|
||||
- Webhooks/runtime: move auth earlier and tighten pre-auth body limits and timeouts across bundled webhook handlers, including slow-body handling for Mattermost slash commands. (#46802) Thanks @vincentkoc.
|
||||
- Email/webhook wrapping: sanitize sender and subject metadata before external-content wrapping so metadata fields cannot break the wrapper structure. (#46816) Thanks @vincentkoc.
|
||||
- Gateway/chat: only reap orphaned stale chat buffers after the abort controller is gone, and clear abort-time streaming metadata so long-running sessions do not lose buffered output while stale maps still get reclaimed. (#52428) Thanks @karanuppal.
|
||||
- Tools/apply-patch: revalidate workspace-only delete and directory targets immediately before mutating host paths. (#46803) Thanks @vincentkoc.
|
||||
- Gateway/config views: strip embedded credentials from URL-based endpoint fields before returning read-only account and config snapshots. (#46799) Thanks @vincentkoc.
|
||||
- ACP/approvals: use canonical tool identity for prompting decisions and fail closed when conflicting tool identity hints are present. (#46817) Thanks @zpbrent and @vincentkoc.
|
||||
@@ -109,154 +218,109 @@ Docs: https://docs.openclaw.ai
|
||||
- Web search/onboarding: clarify provider labels, key prompts, and missing-key notes so setup/configure more clearly names the required provider credential for Gemini, Kimi, Grok, Brave Search, Firecrawl, Perplexity, and Tavily. Thanks @vincentkoc.
|
||||
- macOS/canvas actions: keep unattended local agent actions on trusted in-app canvas surfaces only, and stop exposing the deep-link fallback key to arbitrary page scripts. (#46790) Thanks @vincentkoc.
|
||||
- Agents/compaction: extend the enclosing run deadline once while compaction is actively in flight, and abort the underlying SDK compaction on timeout/cancel so large-session compactions stop freezing mid-run. (#46889) Thanks @asyncjason.
|
||||
- Agents/openai-compatible tool calls: deduplicate repeated tool call ids across live assistant messages and replayed history so OpenAI-compatible backends no longer reject duplicate `tool_call_id` values with HTTP 400. (#40996) Thanks @xaeon2026.
|
||||
- Models/openai-completions: default non-native OpenAI-compatible providers to omit tool-definition `strict` fields unless users explicitly opt back in, so tool calling keeps working on providers that reject that option. (#45497) Thanks @sahancava.
|
||||
- Gateway/Telegram shutdown: abort stalled Telegram polling fetches on shutdown, clean up per-cycle abort listeners, and keep the in-process watchdog ahead of supervisor stop timeouts so SIGTERM no longer leaves zombie gateways behind. (#51242) Thanks @juliabush.
|
||||
- Telegram/setup: warn when setup leaves DMs on pairing without an allowlist, and show valid account-scoped remediation commands. (#50710) Thanks @ernestodeoliveira.
|
||||
- Doctor/Telegram: replace the fresh-install empty group-allowlist false positive with first-run guidance that explains DM pairing approval and the next group setup steps, so new Telegram installs get actionable setup help instead of a broken-config warning. Thanks @vincentkoc.
|
||||
- Doctor/extensions: keep Matrix DM `allowFrom` repairs on the canonical `dm.allowFrom` path and stop treating Zalouser group sender gating as if it fell back to `allowFrom`, so doctor warnings and `--fix` stay aligned with runtime access control. Thanks @vincentkoc.
|
||||
- Doctor/refactor: centralize built-in channel doctor semantics in one static capability registry with conservative fallback behavior for unknown/external channels, so future extension changes stop depending on scattered shared string checks. Thanks @vincentkoc.
|
||||
- Models/OpenRouter runtime capabilities: fetch uncatalogued OpenRouter model metadata on first use so newly added vision models keep image input instead of silently degrading to text-only, with top-level capability field fallbacks for `/api/v1/models`. (#45824) Thanks @DJjjjhao.
|
||||
- Channels/plugins: keep shared interactive payloads merge-ready by fixing Slack custom callback routing and repeat-click dedupe, allowing interactive-only sends, and preserving ordered Discord shared text blocks. (#47715) Thanks @vincentkoc.
|
||||
- Slack/interactive replies: preserve `channelData.slack.blocks` through live DM delivery and preview-finalized edits so Block Kit button and select directives render instead of falling back to raw text. (#45890) Thanks @vincentkoc.
|
||||
- Feishu/actions: expand the runtime action surface with message read/edit, explicit thread replies, pinning, and operator-facing chat/member inspection so Feishu can operate more of the workspace directly. (#47968) Thanks @Takhoffman.
|
||||
- Feishu/topic threads: fetch full thread context, including prior bot replies, when starting a topic-thread session so follow-up turns in Feishu topics keep the right conversation state. (#45254) Thanks @Coobiw.
|
||||
- Feishu/media: keep native image, file, audio, and video/media handling aligned across outbound sends, inbound downloads, thread replies, directory/action aliases, and capability docs so unsupported areas are explicit instead of implied. (#47968) Thanks @Takhoffman.
|
||||
- Feishu/webhooks: harden signed webhook verification to use constant-time signature comparison and keep malformed short signatures fail-closed in webhook E2E coverage.
|
||||
- WhatsApp/reconnect: restore the append recency filter in the extension inbox monitor and handle protobuf `Long` timestamps correctly, so fresh post-reconnect append messages are processed while stale history sync stays suppressed. (#42588) Thanks @MonkeyLeeT.
|
||||
- WhatsApp/login: wait for pending creds writes before reopening after Baileys `515` pairing restarts in both QR login and `channels login` flows, and keep the restart coverage pinned to the real wrapped error shape plus per-account creds queues. (#27910) Thanks @asyncjason.
|
||||
- Telegram/message send: forward `--force-document` through the `sendPayload` path as well as `sendMedia`, so Telegram payload sends with `channelData` keep uploading images as documents instead of silently falling back to compressed photo sends. (#47119) Thanks @thepagent.
|
||||
- Android/canvas: serialize A2UI action-status event strings before evaluating WebView JS, so action ids and multiline errors do not break the callback dispatch. (#43784) Thanks @Kaneki-x.
|
||||
- Android/camera: recycle intermediate and final snap bitmaps in `camera.snap` so repeated captures do not leak native image memory. (#41902) Thanks @Kaneki-x.
|
||||
- Telegram/message chunking: preserve spaces, paragraph separators, and word boundaries when HTML overflow rechunking splits formatted replies. (#47274) Thanks @obviyus.
|
||||
- Z.AI/onboarding: detect a working default model even for explicit `zai-coding-*` endpoint choices, so Coding Plan setup can keep the selected endpoint while defaulting to `glm-5` when available or `glm-4.7` as fallback. (#45969) Thanks @obviyus.
|
||||
- CI/onboarding smoke: surface `ensure-base-commit` fetch failures as workflow warnings and fail the onboarding Docker smoke when expected setup prompts drift instead of continuing silently. Thanks @Takhoffman.
|
||||
- Z.AI/onboarding: add `glm-5-turbo` to the default Z.AI provider catalog so onboarding-generated configs expose the new model alongside the existing GLM defaults. (#46670) Thanks @tomsun28.
|
||||
- Zalo Personal/group gating: stop reapplying `dmPolicy.allowFrom` as a sender gate for already-allowlisted groups when `groupAllowFrom` is unset, so any member of an allowed group can trigger replies while DMs stay restricted. (#46663) Fixes #40146. Thanks @Takhoffman.
|
||||
- Zalo/plugin runtime: export `resolveClientIp` from `openclaw/plugin-sdk/zalo` so installed builds no longer crash on startup when the webhook monitor loads from the packaged extension instead of the monorepo source tree. (#46549) Thanks @No898.
|
||||
- Onboarding/custom providers: store Azure OpenAI and Azure AI Foundry custom endpoints with the Responses API config shape, normalized `/openai/v1` base URLs, and Azure-safe defaults so TUI and agent runs work after setup. (#49543) Thanks @kunalk16.
|
||||
- Docker/live tests: mount external CLI auth homes into writable container copies, derive Codex OAuth expiry from JWT `exp`, refresh synced CLI creds instead of trusting stale cached expiry, and make gateway live probes wait on transcript output so `pnpm test:docker:all` stays green in Linux.
|
||||
- Plugins/install precedence: keep bundled plugins ahead of auto-discovered globals by default, but let an explicitly installed plugin record win its own duplicate-id tie so installed channel plugins load from `~/.openclaw/extensions` after `openclaw plugins install`. (#46722) Thanks @Takhoffman.
|
||||
- Control UI/logging: make browser-safe logger imports avoid eager temp-dir resolution so the bundled Control UI no longer crashes to a blank screen when logging reaches `tmp-openclaw-dir`. (#48469) Fixes #48062. Thanks @7inspire.
|
||||
- Plugins/scoped ids: preserve scoped plugin ids during install and config keying, and keep bundled plugins ahead of discovered duplicate ids by default so `@scope/name` plugins no longer collide with unscoped installs. (#47413) Thanks @vincentkoc.
|
||||
- Gateway/watch mode: restart on bundled-plugin package and manifest metadata changes, rebuild `dist` for extension source and `tsdown.config.ts` changes, and still ignore extension docs. (#47571) Thanks @gumadeiras.
|
||||
- Gateway/watch mode: recreate bundled plugin runtime metadata after clean or stale `dist` states, so `pnpm gateway:watch` no longer fails on missing `dist/extensions/*/openclaw.plugin.json` manifests after a rebuild. Thanks @gumadeiras.
|
||||
- Control UI/chat sessions: show human-readable labels in the grouped session dropdown again, keep unique scoped fallbacks when metadata is missing, and disambiguate duplicate labels only when needed. (#45130) Thanks @luzhidong.
|
||||
- Control UI: scope persisted session selection per gateway, prevent stale session bleed across tokenized gateway opens, and cap stored gateway session history. (#47453) Thanks @sallyom.
|
||||
- Control UI/dashboard: preserve structured gateway shutdown reasons across restart disconnects so config-triggered restarts no longer fall back to `disconnected (1006): no reason`. (#46580) Fixes #46532. Thanks @vincentkoc.
|
||||
- Models/OpenAI Codex OAuth: start the remote manual-input race for Codex login and keep the pasted-input prompt aligned with the actual accepted values, so remote/VPS auth no longer stalls waiting on an unreachable localhost callback. (#51631) Thanks @cash-echo-bot.
|
||||
- Android/chat: theme the thinking dropdown and TLS trust dialogs explicitly so popup surfaces match the active app theme instead of falling back to mismatched Material defaults.
|
||||
- Group mention gating: reject invalid and unsafe nested-repetition `mentionPatterns`, reuse the shared safe config-regex compiler across mention stripping and detection, and cache strip-time regex compilation so noisy groups avoid repeated recompiles.
|
||||
- Browser/profiles: drop the auto-created `chrome-relay` browser profile; users who need the Chrome extension relay must now create their own profile via `openclaw browser create-profile`. (#46596) Fixes #45777. Thanks @odysseus0.
|
||||
- CI/channel test routing: move the built-in channel suites into `test:channels` and keep them out of `test:extensions`, so extension CI no longer fails after the channel migration while targeted test routing still sends Slack, Signal, and iMessage suites to the right lane. (#46066) Thanks @scoootscooob.
|
||||
- Docs/Mintlify: fix MDX marker syntax on Perplexity, Model Providers, Moonshot, and exec approvals pages so local docs preview no longer breaks rendering or leaves stale pages unpublished. (#46695) Thanks @velvet-shark.
|
||||
- Plugins/runtime barrels: route bundled extension runtime imports through public `openclaw/plugin-sdk/*` subpaths and block relative cross-package escapes so packaged extensions stop depending on monorepo-only relative paths. (#51939) Thanks @vincentkoc.
|
||||
- Gateway/config validation: stop treating the implicit default memory slot as a required explicit plugin config, so startup no longer fails with `plugins.slots.memory: plugin not found: memory-core` when `memory-core` was only inferred. (#47494) Thanks @ngutman.
|
||||
- Tlon: honor explicit empty allowlists and defer cite expansion. (#46788) Thanks @zpbrent and @vincentkoc.
|
||||
- Tlon/DM auth: defer cited-message expansion until after DM authorization and owner command handling, so unauthorized DMs and owner approval/admin commands no longer trigger cross-channel cite fetches before the deny or command path.
|
||||
- Gateway/agent events: stop broadcasting false end-of-run `seq gap` errors to clients, and isolate node-driven ingress turns with per-turn run IDs so stale tail events cannot leak into later session runs. (#43751) Thanks @caesargattuso.
|
||||
- Docs/security audit: spell out that `gateway.controlUi.allowedOrigins: ["*"]` is an explicit allow-all browser-origin policy and should be avoided outside tightly controlled local testing.
|
||||
- Gateway/auth: clear self-declared scopes for device-less trusted-proxy Control UI sessions so proxy-authenticated connects cannot claim admin or secrets scopes without a bound device identity.
|
||||
- Nodes/pending actions: re-check queued foreground actions against the current node command policy before returning them to the node. (#46815) Thanks @zpbrent and @vincentkoc.
|
||||
- Node/startup: remove leftover debug `console.log("node host PATH: ...")` that printed the resolved PATH on every `openclaw node run` invocation. (#46515) Fixes #46411. Thanks @ademczuk.
|
||||
- CLI/completion: reduce recursive completion-script string churn and fix nested PowerShell command-path matching so generated nested completions resolve on PowerShell too. (#45537) Thanks @yiShanXin and @vincentkoc.
|
||||
- Slack/startup: harden `@slack/bolt` import interop across current bundled runtime shapes so Slack monitors no longer crash with `App is not a constructor` after plugin-sdk bundling changes. (#45953) Thanks @merc1305.
|
||||
- Windows/gateway status: accept `schtasks` `Last Result` output as an alias for `Last Run Result`, so running scheduled-task installs no longer show `Runtime: unknown`. (#47844) Thanks @MoerAI.
|
||||
- ACP/acpx: resolve the bundled plugin root from the actual plugin directory so plugin-local installs stay under `dist/extensions/acpx` instead of escaping to `dist/extensions` and failing runtime setup. (#47601) Thanks @ngutman.
|
||||
- Gateway/WS handshake: raise the default pre-auth handshake timeout to 10 seconds and add `OPENCLAW_HANDSHAKE_TIMEOUT_MS` as a runtime override so busy local gateways stop dropping healthy CLI connections at 3 seconds. (#49262) Thanks @fuller-stack-dev.
|
||||
- Gateway/websocket pairing bypass for disabled auth: skip device-pairing enforcement for Control UI operator sessions when `gateway.auth.mode=none`, so reverse-proxied dashboards no longer get stuck on `pairing required` despite auth being explicitly disabled. (#47148) Thanks @ademczuk.
|
||||
- Control UI/model switching: preserve the selected provider prefix when switching models from the chat dropdown, so multi-provider setups no longer send `anthropic/gpt-5.2`-style mismatches when the user picked `openai/gpt-5.2`. (#47581) Thanks @chrishham.
|
||||
- Control UI/storage: scope persisted settings keys by gateway base path, with migration from the legacy shared key, so multiple gateways under one domain stop overwriting each other's dashboard preferences. (#47932) Thanks @bobBot-claw.
|
||||
- Agents/usage tracking: stop forcing `supportsUsageInStreaming: false` on non-native OpenAI-completions providers so compatible backends report token usage and cost again instead of showing all zeros. (#46500) Fixes #46142. Thanks @ademczuk.
|
||||
- ACP/acpx: keep plugin-local backend installs under `extensions/acpx` in live repo checkouts so rebuilds no longer delete the runtime binary, and avoid package-lock churn during runtime repair.
|
||||
- Plugins/subagents: preserve gateway-owned plugin subagent access across runtime, tool, and embedded-runner load paths so gateway plugin tools and context engines can still spawn and manage subagents after the loader cache split. (#46648) Thanks @jalehman.
|
||||
- Control UI/overview: keep the language dropdown aligned with the persisted locale during dashboard startup so refreshing the page does not fall back to English before locale hydration completes. (#48019) Thanks @git-jxj.
|
||||
- Agents/compaction: rerun transcript repair after `session.compact()` so orphaned `tool_result` blocks cannot survive compaction and break later Anthropic requests. (#16095) thanks @claw-sylphx.
|
||||
- Agents/compaction: trigger overflow recovery from the tool-result guard once post-compaction context still exceeds the safe threshold, so long tool loops compact before the next model call hard-fails. (#29371) thanks @keshav55.
|
||||
- macOS/exec approvals: harden exec-host request HMAC verification to use a timing-safe compare and keep malformed or truncated signatures fail-closed in focused IPC auth coverage.
|
||||
- Gateway/exec approvals: surface requested env override keys in gateway-host approval prompts so operators can review surviving env context without inheriting noisy base host env.
|
||||
- Telegram/network: preserve sticky IPv4 fallback state across polling restarts so hosts with unstable IPv6 to `api.telegram.org` stop re-triggering repeated Telegram timeouts after each restart. (#48282) Thanks @yassinebkr.
|
||||
- Plugins/subagents: forward per-run provider and model overrides through gateway plugin subagent dispatch so plugin-launched agent delegations honor explicit model selection again. (#48277) Thanks @jalehman.
|
||||
- Agents/compaction: write minimal boundary summaries for empty preparations while keeping split-turn prefixes on the normal path, so no-summarizable-message sessions stop retriggering the safeguard loop. (#42215) thanks @lml2468.
|
||||
- Models/chat commands: keep `/model ...@YYYYMMDD` version suffixes intact by default, but still honor matching stored numeric auth-profile overrides for the same provider. (#48896) Thanks @Alix-007.
|
||||
- Gateway/channels: serialize per-account channel startup so overlapping starts do not boot the same provider twice, preventing MS Teams `EADDRINUSE` crash loops during startup and restart. (#49583) Thanks @sudie-codes.
|
||||
- Tests/OpenAI Codex auth: align login expectations with the default `gpt-5.4` model so CI coverage stays consistent with the current OpenAI Codex default. (#44367) Thanks @jrrcdev.
|
||||
- Discord: enforce strict DM component allowlist auth (#49997) Thanks @joshavant.
|
||||
- Stabilize plugin loader and Docker extension smoke (#50058) Thanks @joshavant.
|
||||
- Telegram: stabilize pairing/session/forum routing and reply formatting tests (#50155) Thanks @joshavant.
|
||||
- Hardening: refresh stale device pairing requests and pending metadata (#50695) Thanks @smaeljaish771 and @joshavant.
|
||||
- Gateway: harden OpenResponses file-context escaping (#50782) Thanks @YLChen-007 and @joshavant.
|
||||
- LINE: harden Express webhook parsing to verified raw body (#51202) Thanks @gladiator9797 and @joshavant.
|
||||
- Exec: harden host env override handling across gateway and node (#51207) Thanks @gladiator9797 and @joshavant.
|
||||
- Voice Call: enforce spoken-output contract and fix stream TTS silence regression (#51500) Thanks @joshavant.
|
||||
- xAI/models: rename the bundled Grok 4.20 catalog entries to the GA IDs and normalize saved deprecated beta IDs at runtime so existing configs and sessions keep resolving. (#50772) thanks @Jaaneek
|
||||
- Plugins/Matrix TTS: send auto-TTS replies as native Matrix voice bubbles instead of generic audio attachments. (#37080) thanks @Matthew19990919.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Agents/bootstrap warnings: move bootstrap truncation warnings out of the system prompt and into the per-turn prompt body so prompt-cache reuse stays stable when truncation warnings appear or disappear. (#48753) Thanks @scoootscooob and @obviyus.
|
||||
- Telegram/DM topic session keys: route named-account DM topics through the same per-account base session key across inbound messages, native commands, and session-state lookups so `/status` and thread recovery stop creating phantom `agent:main:main:thread:...` sessions. (#48204) Thanks @vincentkoc.
|
||||
- macOS/node service startup: use `openclaw node start/stop --json` from the Mac app instead of the removed `openclaw service node ...` command shape, so current CLI installs expose the full node exec surface again. (#46843) Fixes #43171. Thanks @Br1an67.
|
||||
- macOS/launch at login: stop emitting `KeepAlive` for the desktop app launch agent so OpenClaw no longer relaunches immediately after a manual quit while launch at login remains enabled. (#40213) Thanks @stablegenius49.
|
||||
- ACP/gateway startup: use direct Telegram and Discord startup/status helpers instead of routing probes through the plugin runtime, and prepend the selected daemon Node bin dir to service PATH so plugin-local installs can still find `npm` and `pnpm`.
|
||||
- ACP/configured bindings: reinitialize configured ACP sessions that are stuck in `error` state instead of reusing the failed runtime.
|
||||
- Mattermost/DM send: retry transient direct-channel creation failures for DM deliveries, with configurable backoff and per-request timeout. (#42398) Thanks @JonathanJing.
|
||||
- Telegram/network: unify API and media fetches under the same sticky IPv4 and pinned-IP fallback chain, and re-validate pinned override addresses against SSRF policy. (#49148) Thanks @obviyus.
|
||||
- Agents/prompt composition: append bootstrap truncation warnings to the current-turn prompt and add regression coverage for stable system-prompt cache invariants. (#49237) Thanks @scoootscooob.
|
||||
- Gateway/auth: add regression coverage that keeps device-less trusted-proxy Control UI sessions off privileged pairing approval RPCs. Thanks @vincentkoc.
|
||||
- Plugins/runtime-api: pin extension runtime-api export surfaces with explicit guardrail coverage so future surface creep becomes a deliberate diff. Thanks @vincentkoc.
|
||||
- Synology Chat/multi-account: scope direct-message sessions by account and sender so identical webhook `user_id` values on different Synology accounts no longer share transcript or delivery state.
|
||||
- Telegram/security: add regression coverage proving pinned fallback host overrides stay bound to Telegram and delegate non-matching hostnames back to the original lookup path. Thanks @vincentkoc.
|
||||
- Secrets/exec refs: require explicit `--allow-exec` for `secrets apply` write plans that contain exec SecretRefs/providers, and align audit/configure/apply dry-run behavior to skip exec checks unless opted in to prevent unexpected command side effects. (#49417) Thanks @restriction and @joshavant.
|
||||
- Tools/image generation: add bundled fal image generation support so `image_generate` can target `fal/*` models with `FAL_KEY`, including single-image edit flows via FLUX image-to-image. Thanks @vincentkoc.
|
||||
- Gateway/hooks: preserve immutable hook ingress provenance across async isolated-agent dispatch so normalized hook session routes keep external wrapping, Gmail-specific policy, and Gmail model selection intact.
|
||||
- Messages/polls: treat zero-valued poll params on `message.send` as unset defaults while keeping non-zero poll params on the poll validation path. (#52150) Fixes #52118. Thanks @Bartok9.
|
||||
- xAI/web search: add missing Grok credential metadata so the bundled provider registration type-checks again. (#49472) thanks @scoootscooob.
|
||||
- Signal/runtime API: re-export `SignalAccountConfig` so Signal account resolution type-checks again. (#49470) Thanks @scoootscooob.
|
||||
- Google Chat/runtime API: thin the private runtime barrel onto the curated public SDK surface while keeping public Google Chat exports intact. (#49504) Thanks @scoootscooob.
|
||||
- Agents/session cache: opportunistically sweep expired embedded-runner session cache entries during later cache activity, so one-shot session files do not accumulate forever. (#52427) Thanks @karanuppal.
|
||||
- WhatsApp: stabilize inbound monitor and setup tests (#50007) Thanks @joshavant.
|
||||
- Matrix: make onboarding status runtime-safe (#49995) Thanks @joshavant.
|
||||
- Channels: stabilize lane harness and monitor tests (#50167) Thanks @joshavant.
|
||||
- WhatsApp/active-listener: pin the active listener registry to a `globalThis` singleton so split WhatsApp bundle chunks share one listener map and outbound sends stop missing the registered session. (#47433) Thanks @clawdia67.
|
||||
- Plugins/WhatsApp: share split-load singleton state for plugin command registration and active WhatsApp listeners so duplicate module graphs no longer lose native plugin commands or outbound listener state. (#50418) Thanks @huntharo.
|
||||
- Onboarding/custom providers: keep Azure AI Foundry `*.services.ai.azure.com` custom endpoints on the selected compatibility path instead of forcing Responses, so chat-completions Foundry models still work after setup. Fixes #50528. (#50535) Thanks @obviyus.
|
||||
- Plugins/update: let `openclaw plugins update <npm-spec>` target tracked npm installs by dist-tag or exact version, and preserve the recorded npm spec for later id-based updates. (#49998) Thanks @huntharo.
|
||||
- Tests/CLI: reduce command-secret gateway test import pressure while keeping the real protocol payload validator in place, so the isolated lane no longer carries the heavier runtime-web and message-channel graphs. (#50663) Thanks @huntharo.
|
||||
- Gateway/plugins: share plugin interactive callback routing and plugin bind approval state across duplicate module graphs so Telegram Codex picker buttons and plugin bind approvals no longer fall through to normal inbound message routing. (#50722) Thanks @huntharo.
|
||||
- Agents/compaction: add an opt-in post-compaction session JSONL truncation step that drops summarized transcript entries while preserving the retained branch tail and live session metadata. (#41021) thanks @thirumaleshp.
|
||||
- Telegram/routing: fail loud when `message send` targets an unknown non-default Telegram `accountId`, instead of silently falling back to the channel-level bot token and sending through the wrong bot. (#50853) Thanks @hclsys.
|
||||
- Web search: align onboarding, configure, and finalize with plugin-owned provider contracts, including disabled-provider recovery, config-aware credential hooks, and runtime-visible summaries. (#50935) Thanks @gumadeiras.
|
||||
- Agents/replay: sanitize malformed assistant tool-call replay blocks before provider replay so follow-up Anthropic requests do not inherit the downstream `replace` crash. (#50005) Thanks @jalehman.
|
||||
- Plugins/context engines: retry strict legacy `assemble()` calls without the new `prompt` field when older engines reject it, preserving prompt-aware retrieval compatibility for pre-prompt plugins. (#50848) thanks @danhdoan.
|
||||
- make `openclaw update status` explicitly say `up to date` when the local version already matches npm latest, while keeping the availability logic unchanged. (#51409) Thanks @dongzhenye.
|
||||
- Agents/embedded transport errors: distinguish common network failures like connection refused, DNS lookup failure, and interrupted sockets from true timeouts in embedded-run user messaging and lifecycle diagnostics. (#51419) Thanks @scoootscooob.
|
||||
- Discord/startup logging: report client initialization while the gateway is still connecting instead of claiming Discord is logged in before readiness is reached. (#51425) Thanks @scoootscoob.
|
||||
- Gateway/probe: honor caller `--timeout` for active local loopback probes in `gateway status`, keep inactive remote-mode loopback probes fast, and clamp probe timers to JS-safe bounds so slow local/container gateways stop reporting false timeouts. (#47533) Thanks @MonkeyLeeT.
|
||||
- Config/startup: keep bundled web-search allowlist compatibility on a lightweight manifest path so config validation no longer pulls bundled web-search registry imports into startup, while still avoiding accidental auto-allow of config-loaded override plugins. (#51574) Thanks @RichardCao.
|
||||
- Gateway/chat.send: persist uploaded image references across reloads and compaction without delaying first-turn dispatch or double-submitting the same image to vision models. (#51324) Thanks @fuller-stack-dev.
|
||||
- Plugins/runtime state: share plugin-facing infra singleton state across duplicate module graphs and keep session-binding adapter ownership stable until the active owner unregisters. (#50725) thanks @huntharo.
|
||||
- Agents/compaction safeguard: preserve split-turn context and preserved recent turns when capped retry fallback reuses the last successful summary. (#27727) thanks @Pandadadadazxf.
|
||||
- Discord/pickers: keep `/codex_resume --browse-projects` picker callbacks alive in Discord by sharing component callback state across duplicate module graphs, preserving callback fallbacks, and acknowledging matched plugin interactions before dispatch. (#51260) Thanks @huntharo.
|
||||
- Agents/memory flush: keep transcript-hash dedup active across memory-flush fallback retries so a write-then-throw flush attempt cannot append duplicate `MEMORY.md` entries before the fallback cycle completes. (#34222) Thanks @lml2468.
|
||||
- make `openclaw update status` explicitly say `up to date` when the local version already matches npm latest, while keeping the availability logic unchanged. (#51409) Thanks @dongzhenye.
|
||||
- Android/canvas: recycle captured and scaled snapshot bitmaps so repeated canvas snapshots do not leak native image memory. (#41889) Thanks @Kaneki-x.
|
||||
- Android/theme: switch status bar icon contrast with the active system theme so Android light mode no longer leaves unreadable light icons over the app header. (#51098) Thanks @goweii.
|
||||
- Discord/ACP: forward worker abort signals into ACP turns so timed-out Discord jobs cancel the running turn instead of silently leaving the bound ACP session working in the background.
|
||||
- Gateway/openresponses: preserve assistant commentary and session continuity across hosted-tool `/v1/responses` turns, and emit streamed tool-call payloads before finalization so client tool loops stay resumable. (#52171) Thanks @CharZhou.
|
||||
|
||||
### Breaking
|
||||
|
||||
- Skills/image generation: remove the bundled `nano-banana-pro` skill wrapper. Use `agents.defaults.imageGenerationModel.primary: "google/gemini-3-pro-image-preview"` for the native Nano Banana-style path instead.
|
||||
|
||||
- Browser/Chrome MCP: remove the legacy Chrome extension relay path, bundled extension assets, `driver: "extension"`, and `browser.relayBindHost`. Run `openclaw doctor --fix` to migrate host-local browser config to `existing-session` / `user`; Docker, headless, sandbox, and remote browser flows still use raw CDP. (#47893) Thanks @vincentkoc.
|
||||
- Plugins/runtime: remove the public `openclaw/extension-api` surface with no compatibility shim. Bundled plugins must use injected runtime for host-side operations (for example `api.runtime.agent.runEmbeddedPiAgent`) and any remaining direct imports must come from narrow `openclaw/plugin-sdk/*` subpaths instead of the monolithic SDK root.
|
||||
- Tools/image generation: standardize the stock image create/edit path on the core `image_generate` tool. The old `nano-banana-pro` docs/examples are gone; if you previously copied that sample-skill config, switch to `agents.defaults.imageGenerationModel` for built-in image generation or install a separate third-party skill explicitly.
|
||||
- Skills/image generation: remove the bundled `nano-banana-pro` skill wrapper. Use `agents.defaults.imageGenerationModel.primary: "google/gemini-3-pro-image-preview"` for the native Nano Banana-style path instead.
|
||||
- Plugins/message discovery: require `ChannelMessageActionAdapter.describeMessageTool(...)` for shared `message` tool discovery. The legacy `listActions`, `getCapabilities`, and `getToolSchema` adapter methods are removed. Plugin authors should migrate message discovery to `describeMessageTool(...)` and keep channel-specific action runtime code inside the owning plugin package. Thanks @gumadeiras.
|
||||
- Exec/env sandbox: block build-tool JVM injection (`MAVEN_OPTS`, `SBT_OPTS`, `GRADLE_OPTS`, `ANT_OPTS`), glibc tunable exploitation (`GLIBC_TUNABLES`), and .NET dependency resolution hijack (`DOTNET_ADDITIONAL_DEPS`) from the host exec environment, and restrict Gradle init script redirect (`GRADLE_USER_HOME`) as an override-only block so user-configured Gradle homes still propagate. (#49702)
|
||||
- Plugins/Matrix: add a new Matrix plugin backed by the official `matrix-js-sdk`. If you are upgrading from the previous public Matrix plugin, follow the migration guide: https://docs.openclaw.ai/install/migrating-matrix Thanks @gumadeiras.
|
||||
- Discord/commands: switch native command deployment to Carbon reconcile by default so Discord restarts stop churning slash commands through OpenClaw’s local deploy path. (#46597) Thanks @huntharo and @thewilloftheshadow.
|
||||
- Plugins/Matrix: durably dedupe inbound room events across gateway restarts so previously handled Matrix messages are not replayed as new, while preserving clean-restart backlog delivery for unseen events. (#50922) thanks @gumadeiras
|
||||
- Agents/media replies: migrate the remaining browser, canvas, and nodes snapshot outputs onto `details.media` so generated media keeps attaching to assistant replies after the collect-then-attach refactor. (#51731) Thanks @christianklotz.
|
||||
- Android/contacts search: escape literal `%` and `_` in contact-name queries so searches like `100%` or `_id` no longer match unrelated contacts through SQL `LIKE` wildcards. (#41891) Thanks @Kaneki-x.
|
||||
- ACP/Codex session replay: preserve hidden assistant thinking when loading or rebinding existing ACP sessions so stored thought chunks do not replay into visible assistant text. Thanks @vincentkoc.
|
||||
- Gateway/commands: keep internal `chat.send` slash-command UX while requiring `operator.admin` before internal callers can persist `/exec` defaults or mutate `phone-control` node policy through `/phone arm|disarm`.
|
||||
- Plugins/Matrix: move bundled plugin `KeyedAsyncQueue` imports onto the stable `plugin-sdk/core` surface so Matrix Docker/runtime builds do not depend on the brittle keyed-async-queue subpath. Thanks @ecohash-co and @vincentkoc.
|
||||
- Plugins/context engines: enforce owner-aware context-engine registration on both loader and public SDK paths so plugins cannot spoof privileged ownership, claim the core `legacy` engine id, or overwrite an existing engine id through direct SDK imports. (#47595) Thanks @vincentkoc.
|
||||
- Plugins/bundler TDZ: fix `RESERVED_COMMANDS` temporal dead zone error that prevented device-pair, phone-control, and talk-voice plugins from registering when the bundler placed the commands module after call sites in the same output chunk. Thanks @BunsDev.
|
||||
- Plugins/imports: fix stale googlechat runtime-api import paths and signal SDK circular re-exports broken by recent plugin-sdk refactors. Thanks @BunsDev.
|
||||
- Plugins/install precedence: keep bundled plugins ahead of auto-discovered globals by default, but let an explicitly installed plugin record win its own duplicate-id tie so installed channel plugins load from `~/.openclaw/extensions` after `openclaw plugins install`. (#46722) Thanks @Takhoffman.
|
||||
- Plugins/scoped ids: preserve scoped plugin ids during install and config keying, and keep bundled plugins ahead of discovered duplicate ids by default so `@scope/name` plugins no longer collide with unscoped installs. (#47413) Thanks @vincentkoc.
|
||||
- Docs/Mintlify: fix MDX marker syntax on Perplexity, Model Providers, Moonshot, and exec approvals pages so local docs preview no longer breaks rendering or leaves stale pages unpublished. (#46695) Thanks @velvet-shark.
|
||||
- Plugins/runtime barrels: route bundled extension runtime imports through public `openclaw/plugin-sdk/*` subpaths and block relative cross-package escapes so packaged extensions stop depending on monorepo-only relative paths. (#51939) Thanks @vincentkoc.
|
||||
- Docs/security audit: spell out that `gateway.controlUi.allowedOrigins: ["*"]` is an explicit allow-all browser-origin policy and should be avoided outside tightly controlled local testing.
|
||||
- Plugins/subagents: preserve gateway-owned plugin subagent access across runtime, tool, and embedded-runner load paths so gateway plugin tools and context engines can still spawn and manage subagents after the loader cache split. (#46648) Thanks @jalehman.
|
||||
- Plugins/subagents: forward per-run provider and model overrides through gateway plugin subagent dispatch so plugin-launched agent delegations honor explicit model selection again. (#48277) Thanks @jalehman.
|
||||
- Tests/OpenAI Codex auth: align login expectations with the default `gpt-5.4` model so CI coverage stays consistent with the current OpenAI Codex default. (#44367) Thanks @jrrcdev.
|
||||
- Plugins/Matrix TTS: send auto-TTS replies as native Matrix voice bubbles instead of generic audio attachments. (#37080) thanks @Matthew19990919.
|
||||
- Plugins/discovery: distinguish missing package entry files from package-path escape violations so startup skips absent plugin entry paths without raising false security diagnostics. (#52491) Thanks @hclsys.
|
||||
- Plugins/Matrix: accept shared send-tool media aliases (`mediaUrl`, `filePath`, `path`) and preserve `asVoice` / `audioAsVoice` through Matrix action dispatch so media-only sends and voice-message intents reach the plugin send layer correctly. Thanks @psacc and @vincentkoc.
|
||||
- Plugins/runtime-api: pin extension runtime-api export surfaces with explicit guardrail coverage so future surface creep becomes a deliberate diff. Thanks @vincentkoc.
|
||||
- Plugins/WhatsApp: share split-load singleton state for plugin command registration and active WhatsApp listeners so duplicate module graphs no longer lose native plugin commands or outbound listener state. (#50418) Thanks @huntharo.
|
||||
- Plugins/update: let `openclaw plugins update <npm-spec>` target tracked npm installs by dist-tag or exact version, and preserve the recorded npm spec for later id-based updates. (#49998) Thanks @huntharo.
|
||||
- Tests/CLI: reduce command-secret gateway test import pressure while keeping the real protocol payload validator in place, so the isolated lane no longer carries the heavier runtime-web and message-channel graphs. (#50663) Thanks @huntharo.
|
||||
- Gateway/plugins: share plugin interactive callback routing and plugin bind approval state across duplicate module graphs so Telegram Codex picker buttons and plugin bind approvals no longer fall through to normal inbound message routing. (#50722) Thanks @huntharo.
|
||||
- Plugins/context engines: retry strict legacy `assemble()` calls without the new `prompt` field when older engines reject it, preserving prompt-aware retrieval compatibility for pre-prompt plugins. (#50848) thanks @danhdoan.
|
||||
- Plugins/runtime state: share plugin-facing infra singleton state across duplicate module graphs and keep session-binding adapter ownership stable until the active owner unregisters. (#50725) thanks @huntharo.
|
||||
- Discord/pickers: keep `/codex_resume --browse-projects` picker callbacks alive in Discord by sharing component callback state across duplicate module graphs, preserving callback fallbacks, and acknowledging matched plugin interactions before dispatch. (#51260) Thanks @huntharo.
|
||||
- Memory/core tools: register `memory_search` and `memory_get` independently so one unavailable memory tool no longer suppresses the other in new sessions. (#50198) Thanks @artwalker.
|
||||
- Telegram/Mattermost message tool: keep plugin button schemas optional in isolated and cron sessions so plain sends do not fail validation when no current channel is active. (#52589) Thanks @tylerliu612.
|
||||
|
||||
## 2026.3.13
|
||||
|
||||
@@ -554,6 +618,12 @@ Docs: https://docs.openclaw.ai
|
||||
- Gateway/node pending drain followup: keep `hasMore` true when the deferred baseline status item still needs delivery, and avoid allocating empty pending-work state for drain-only nodes with no queued work. (#41429) Thanks @mbelinky.
|
||||
- Protocol/Swift model sync: regenerate pending node work Swift bindings after the landed `node.pending.*` schema additions so generated protocol artifacts are consistent again. (#41477) Thanks @mbelinky.
|
||||
- Cron/subagent followup: do not misclassify empty or `NO_REPLY` cron responses as interim acknowledgements that need a rerun, so deliberately silent cron jobs are no longer retried. (#41383) thanks @jackal092927.
|
||||
- CLI/memory teardown: close cached memory search/index managers in the one-shot CLI shutdown path so watcher-backed memory caches no longer keep completed CLI runs alive after output finishes. (#40389) thanks @Julbarth.
|
||||
- Tools/web search: treat Brave `llm-context` grounding snippets as plain strings so `web_search` no longer returns empty snippet arrays in LLM Context mode. (#41387) thanks @zheliu2.
|
||||
- ACP/run-mode delivery: restore inline delivery for one-shot ACP run spawns from non-subagent (main) requester sessions so completions reach the originating Discord/Telegram/etc. channel again. Subagent orchestrators continue to use stream-to-parent when an active heartbeat relay route is available. (#52426) Thanks @distractedCoding.
|
||||
- Telegram/exec approvals: reject `/approve` commands aimed at other bots, keep deterministic approval prompts visible when tool-result delivery fails, and stop resolved exact IDs from matching other pending approvals by prefix. (#37233) Thanks @huntharo.
|
||||
- Control UI/Sessions: restore single-column session table collapse on narrow viewport or container widths by moving the responsive table override next to the base grid rule and enabling inline-size container queries. (#12175) Thanks @benjipeng.
|
||||
- Telegram/final preview delivery: split active preview lifecycle from cleanup retention so missing archived preview edits avoid duplicate fallback sends without clearing the live preview or blocking later in-place finalization. (#41662) thanks @hougangdev.
|
||||
- Cron/state errors: record `lastErrorReason` in cron job state and keep the gateway schema aligned with the full failover-reason set, including regression coverage for protocol conformance. (#14382) thanks @futuremind2026.
|
||||
- Browser/Browserbase 429 handling: surface stable no-retry rate-limit guidance without buffering discarded HTTP 429 response bodies from remote browser services. (#40491) thanks @mvanhorn.
|
||||
- CI/CodeQL Swift toolchain: select Xcode 26.1 before installing Swift build tools so the CodeQL Swift job uses Swift tools 6.2 on `macos-latest`. (#41787) thanks @BunsDev.
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
# Slim (bookworm-slim): docker build --build-arg OPENCLAW_VARIANT=slim .
|
||||
ARG OPENCLAW_EXTENSIONS=""
|
||||
ARG OPENCLAW_VARIANT=default
|
||||
ARG OPENCLAW_DOCKER_APT_UPGRADE=1
|
||||
ARG OPENCLAW_NODE_BOOKWORM_IMAGE="node:24-bookworm@sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b"
|
||||
ARG OPENCLAW_NODE_BOOKWORM_DIGEST="sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b"
|
||||
ARG OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE="node:24-bookworm-slim@sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb"
|
||||
@@ -113,6 +114,7 @@ LABEL org.opencontainers.image.base.name="docker.io/library/node:24-bookworm-sli
|
||||
# ── Stage 3: Runtime ────────────────────────────────────────────
|
||||
FROM base-${OPENCLAW_VARIANT}
|
||||
ARG OPENCLAW_VARIANT
|
||||
ARG OPENCLAW_DOCKER_APT_UPGRADE
|
||||
|
||||
# OCI base-image metadata for downstream image consumers.
|
||||
# If you change these annotations, also update:
|
||||
@@ -129,10 +131,14 @@ WORKDIR /app
|
||||
|
||||
# Install system utilities present in bookworm but missing in bookworm-slim.
|
||||
# On the full bookworm image these are already installed (apt-get is a no-op).
|
||||
# Smoke workflows can opt out of distro upgrades to cut repeated CI time while
|
||||
# keeping the default runtime image behavior unchanged.
|
||||
RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
|
||||
apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \
|
||||
if [ "${OPENCLAW_DOCKER_APT_UPGRADE}" != "0" ]; then \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends; \
|
||||
fi && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
procps hostname curl git lsof openssl
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@ android {
|
||||
applicationId = "ai.openclaw.app"
|
||||
minSdk = 31
|
||||
targetSdk = 36
|
||||
versionCode = 2026032000
|
||||
versionName = "2026.3.20"
|
||||
versionCode = 2026032200
|
||||
versionName = "2026.3.22"
|
||||
ndk {
|
||||
// Support all major ABIs — native libs are tiny (~47 KB per ABI)
|
||||
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
|
||||
|
||||
@@ -237,6 +237,10 @@ class MainViewModel(app: Application) : AndroidViewModel(app) {
|
||||
ensureRuntime().handleCanvasA2UIActionFromWebView(payloadJson)
|
||||
}
|
||||
|
||||
fun isTrustedCanvasActionUrl(rawUrl: String?): Boolean {
|
||||
return ensureRuntime().isTrustedCanvasActionUrl(rawUrl)
|
||||
}
|
||||
|
||||
fun requestCanvasRehydrate(source: String = "screen_tab") {
|
||||
ensureRuntime().requestCanvasRehydrate(source = source, force = true)
|
||||
}
|
||||
|
||||
@@ -904,6 +904,10 @@ class NodeRuntime(
|
||||
}
|
||||
}
|
||||
|
||||
fun isTrustedCanvasActionUrl(rawUrl: String?): Boolean {
|
||||
return a2uiHandler.isTrustedCanvasActionUrl(rawUrl)
|
||||
}
|
||||
|
||||
fun loadChat(sessionKey: String) {
|
||||
val key = sessionKey.trim().ifEmpty { resolveMainSessionKey() }
|
||||
chat.load(key)
|
||||
|
||||
@@ -13,6 +13,13 @@ class A2UIHandler(
|
||||
private val getNodeCanvasHostUrl: () -> String?,
|
||||
private val getOperatorCanvasHostUrl: () -> String?,
|
||||
) {
|
||||
fun isTrustedCanvasActionUrl(rawUrl: String?): Boolean {
|
||||
return CanvasActionTrust.isTrustedCanvasActionUrl(
|
||||
rawUrl = rawUrl,
|
||||
trustedA2uiUrls = listOfNotNull(resolveA2uiHostUrl()),
|
||||
)
|
||||
}
|
||||
|
||||
fun resolveA2uiHostUrl(): String? {
|
||||
val nodeRaw = getNodeCanvasHostUrl()?.trim().orEmpty()
|
||||
val operatorRaw = getOperatorCanvasHostUrl()?.trim().orEmpty()
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package ai.openclaw.app.node
|
||||
|
||||
import java.net.URI
|
||||
|
||||
object CanvasActionTrust {
|
||||
const val scaffoldAssetUrl: String = "file:///android_asset/CanvasScaffold/scaffold.html"
|
||||
|
||||
fun isTrustedCanvasActionUrl(rawUrl: String?, trustedA2uiUrls: List<String>): Boolean {
|
||||
val candidate = rawUrl?.trim().orEmpty()
|
||||
if (candidate.isEmpty()) return false
|
||||
if (candidate == scaffoldAssetUrl) return true
|
||||
|
||||
val candidateUri = parseUri(candidate) ?: return false
|
||||
if (candidateUri.scheme.equals("file", ignoreCase = true)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return trustedA2uiUrls.any { trusted ->
|
||||
isTrustedA2uiPage(candidateUri, trusted)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isTrustedA2uiPage(candidateUri: URI, trustedUrl: String): Boolean {
|
||||
val trustedUri = parseUri(trustedUrl) ?: return false
|
||||
if (!candidateUri.scheme.equals(trustedUri.scheme, ignoreCase = true)) return false
|
||||
if (candidateUri.host?.equals(trustedUri.host, ignoreCase = true) != true) return false
|
||||
if (effectivePort(candidateUri) != effectivePort(trustedUri)) return false
|
||||
|
||||
val trustedPath = trustedUri.rawPath?.takeIf { it.isNotBlank() } ?: return false
|
||||
val candidatePath = candidateUri.rawPath?.takeIf { it.isNotBlank() } ?: return false
|
||||
val trustedPrefix = if (trustedPath.endsWith("/")) trustedPath else "$trustedPath/"
|
||||
return candidatePath == trustedPath || candidatePath.startsWith(trustedPrefix)
|
||||
}
|
||||
|
||||
private fun effectivePort(uri: URI): Int {
|
||||
if (uri.port >= 0) return uri.port
|
||||
return when (uri.scheme?.lowercase()) {
|
||||
"https" -> 443
|
||||
"http" -> 80
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseUri(raw: String): URI? =
|
||||
try {
|
||||
URI(raw)
|
||||
} catch (_: Throwable) {
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,6 @@ import java.time.format.DateTimeFormatter
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.resumeWithException
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
|
||||
class LocationCaptureManager(private val context: Context) {
|
||||
@@ -100,18 +98,15 @@ class LocationCaptureManager(private val context: Context) {
|
||||
val resolved =
|
||||
providers.firstOrNull { manager.isProviderEnabled(it) }
|
||||
?: throw IllegalStateException("LOCATION_UNAVAILABLE: no providers available")
|
||||
return withTimeout(timeoutMs.coerceAtLeast(1)) {
|
||||
suspendCancellableCoroutine { cont ->
|
||||
val location = withTimeout(timeoutMs.coerceAtLeast(1)) {
|
||||
suspendCancellableCoroutine<Location?> { cont ->
|
||||
val signal = CancellationSignal()
|
||||
cont.invokeOnCancellation { signal.cancel() }
|
||||
manager.getCurrentLocation(resolved, signal, context.mainExecutor) { location ->
|
||||
if (location != null) {
|
||||
cont.resume(location)
|
||||
} else {
|
||||
cont.resumeWithException(IllegalStateException("LOCATION_UNAVAILABLE: no fix"))
|
||||
}
|
||||
cont.resume(location) { _, _, _ -> }
|
||||
}
|
||||
}
|
||||
}
|
||||
return location ?: throw IllegalStateException("LOCATION_UNAVAILABLE: no fix")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.webkit.WebSettingsCompat
|
||||
import androidx.webkit.WebViewFeature
|
||||
import ai.openclaw.app.MainViewModel
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@Composable
|
||||
@@ -29,6 +30,7 @@ fun CanvasScreen(viewModel: MainViewModel, visible: Boolean, modifier: Modifier
|
||||
val context = LocalContext.current
|
||||
val isDebuggable = (context.applicationInfo.flags and android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE) != 0
|
||||
val webViewRef = remember { mutableStateOf<WebView?>(null) }
|
||||
val currentPageUrlRef = remember { AtomicReference<String?>(null) }
|
||||
|
||||
DisposableEffect(viewModel) {
|
||||
onDispose {
|
||||
@@ -68,6 +70,14 @@ fun CanvasScreen(viewModel: MainViewModel, visible: Boolean, modifier: Modifier
|
||||
isHorizontalScrollBarEnabled = true
|
||||
webViewClient =
|
||||
object : WebViewClient() {
|
||||
override fun onPageStarted(
|
||||
view: WebView,
|
||||
url: String?,
|
||||
favicon: android.graphics.Bitmap?,
|
||||
) {
|
||||
currentPageUrlRef.set(url)
|
||||
}
|
||||
|
||||
override fun onReceivedError(
|
||||
view: WebView,
|
||||
request: WebResourceRequest,
|
||||
@@ -90,6 +100,7 @@ fun CanvasScreen(viewModel: MainViewModel, visible: Boolean, modifier: Modifier
|
||||
}
|
||||
|
||||
override fun onPageFinished(view: WebView, url: String?) {
|
||||
currentPageUrlRef.set(url)
|
||||
if (isDebuggable) {
|
||||
Log.d("OpenClawWebView", "onPageFinished: $url")
|
||||
}
|
||||
@@ -122,7 +133,12 @@ fun CanvasScreen(viewModel: MainViewModel, visible: Boolean, modifier: Modifier
|
||||
}
|
||||
}
|
||||
|
||||
val bridge = CanvasA2UIActionBridge { payload -> viewModel.handleCanvasA2UIActionFromWebView(payload) }
|
||||
val bridge =
|
||||
CanvasA2UIActionBridge(
|
||||
isTrustedPage = { viewModel.isTrustedCanvasActionUrl(currentPageUrlRef.get()) },
|
||||
) { payload ->
|
||||
viewModel.handleCanvasA2UIActionFromWebView(payload)
|
||||
}
|
||||
addJavascriptInterface(bridge, CanvasA2UIActionBridge.interfaceName)
|
||||
viewModel.canvas.attach(this)
|
||||
webViewRef.value = this
|
||||
@@ -147,11 +163,15 @@ private fun disableForceDarkIfSupported(settings: WebSettings) {
|
||||
WebSettingsCompat.setForceDark(settings, WebSettingsCompat.FORCE_DARK_OFF)
|
||||
}
|
||||
|
||||
private class CanvasA2UIActionBridge(private val onMessage: (String) -> Unit) {
|
||||
private class CanvasA2UIActionBridge(
|
||||
private val isTrustedPage: () -> Boolean,
|
||||
private val onMessage: (String) -> Unit,
|
||||
) {
|
||||
@JavascriptInterface
|
||||
fun postMessage(payload: String?) {
|
||||
val msg = payload?.trim().orEmpty()
|
||||
if (msg.isEmpty()) return
|
||||
if (!isTrustedPage()) return
|
||||
onMessage(msg)
|
||||
}
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ class TalkModeManager(
|
||||
private val playbackGeneration = AtomicLong(0L)
|
||||
|
||||
private var ttsJob: Job? = null
|
||||
private val playerLock = Any()
|
||||
private var player: MediaPlayer? = null
|
||||
@Volatile private var finalizeInFlight = false
|
||||
private var listenWatchdogJob: Job? = null
|
||||
@@ -763,7 +764,9 @@ class TalkModeManager(
|
||||
try {
|
||||
withContext(Dispatchers.IO) { tempFile.writeBytes(audioBytes) }
|
||||
val player = MediaPlayer()
|
||||
this.player = player
|
||||
synchronized(playerLock) {
|
||||
this.player = player
|
||||
}
|
||||
val finished = CompletableDeferred<Unit>()
|
||||
player.setAudioAttributes(
|
||||
AudioAttributes.Builder()
|
||||
@@ -784,7 +787,7 @@ class TalkModeManager(
|
||||
ensurePlaybackActive(playbackToken)
|
||||
} finally {
|
||||
try {
|
||||
cleanupPlayer()
|
||||
cleanupPlayer(player)
|
||||
} catch (_: Throwable) {}
|
||||
tempFile.delete()
|
||||
}
|
||||
@@ -821,7 +824,11 @@ class TalkModeManager(
|
||||
return
|
||||
}
|
||||
if (resetInterrupt) {
|
||||
val currentMs = player?.currentPosition?.toDouble() ?: 0.0
|
||||
val currentMs = synchronized(playerLock) {
|
||||
try {
|
||||
player?.currentPosition?.toDouble() ?: 0.0
|
||||
} catch (_: IllegalStateException) { 0.0 }
|
||||
}
|
||||
lastInterruptedAtSeconds = currentMs / 1000.0
|
||||
}
|
||||
cleanupPlayer()
|
||||
@@ -864,10 +871,16 @@ class TalkModeManager(
|
||||
audioFocusRequest = null
|
||||
}
|
||||
|
||||
private fun cleanupPlayer() {
|
||||
player?.stop()
|
||||
player?.release()
|
||||
player = null
|
||||
private fun cleanupPlayer(expectedPlayer: MediaPlayer? = null) {
|
||||
synchronized(playerLock) {
|
||||
val p = player ?: return
|
||||
if (expectedPlayer != null && p !== expectedPlayer) return
|
||||
player = null
|
||||
try {
|
||||
p.stop()
|
||||
} catch (_: IllegalStateException) {}
|
||||
p.release()
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldInterrupt(transcript: String): Boolean {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package ai.openclaw.app.node
|
||||
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class CanvasActionTrustTest {
|
||||
@Test
|
||||
fun acceptsBundledScaffoldAsset() {
|
||||
assertTrue(CanvasActionTrust.isTrustedCanvasActionUrl(CanvasActionTrust.scaffoldAssetUrl, emptyList()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun acceptsTrustedA2uiPageOnAdvertisedCanvasHost() {
|
||||
assertTrue(
|
||||
CanvasActionTrust.isTrustedCanvasActionUrl(
|
||||
rawUrl = "https://canvas.example.com:9443/__openclaw__/cap/token/__openclaw__/a2ui/?platform=android",
|
||||
trustedA2uiUrls = listOf("https://canvas.example.com:9443/__openclaw__/cap/token/__openclaw__/a2ui/?platform=android"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rejectsDifferentOriginEvenIfPathMatches() {
|
||||
assertFalse(
|
||||
CanvasActionTrust.isTrustedCanvasActionUrl(
|
||||
rawUrl = "https://evil.example.com:9443/__openclaw__/cap/token/__openclaw__/a2ui/?platform=android",
|
||||
trustedA2uiUrls = listOf("https://canvas.example.com:9443/__openclaw__/cap/token/__openclaw__/a2ui/?platform=android"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rejectsUntrustedCanvasPagePathOnTrustedOrigin() {
|
||||
assertFalse(
|
||||
CanvasActionTrust.isTrustedCanvasActionUrl(
|
||||
rawUrl = "https://canvas.example.com:9443/untrusted/index.html",
|
||||
trustedA2uiUrls = listOf("https://canvas.example.com:9443/__openclaw__/cap/token/__openclaw__/a2ui/?platform=android"),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
// Shared iOS version defaults.
|
||||
// Generated overrides live in build/Version.xcconfig (git-ignored).
|
||||
|
||||
OPENCLAW_GATEWAY_VERSION = 2026.3.14
|
||||
OPENCLAW_MARKETING_VERSION = 2026.3.14
|
||||
OPENCLAW_BUILD_VERSION = 202603140
|
||||
OPENCLAW_GATEWAY_VERSION = 2026.3.22
|
||||
OPENCLAW_MARKETING_VERSION = 2026.3.22
|
||||
OPENCLAW_BUILD_VERSION = 202603220
|
||||
|
||||
#include? "../build/Version.xcconfig"
|
||||
|
||||
@@ -65,9 +65,9 @@ Release behavior:
|
||||
- Beta release also switches the app to `OpenClawPushTransport=relay`, `OpenClawPushDistribution=official`, and `OpenClawPushAPNsEnvironment=production`.
|
||||
- The beta flow does not modify `apps/ios/.local-signing.xcconfig` or `apps/ios/LocalSigning.xcconfig`.
|
||||
- Root `package.json.version` is the only version source for iOS.
|
||||
- A root version like `2026.3.13-beta.1` becomes:
|
||||
- `CFBundleShortVersionString = 2026.3.13`
|
||||
- `CFBundleVersion = next TestFlight build number for 2026.3.13`
|
||||
- A root version like `2026.3.22-beta.1` becomes:
|
||||
- `CFBundleShortVersionString = 2026.3.22`
|
||||
- `CFBundleVersion = next TestFlight build number for 2026.3.22`
|
||||
|
||||
Required env for beta builds:
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ def normalize_release_version(raw_value)
|
||||
version = raw_value.to_s.strip.sub(/\Av/, "")
|
||||
UI.user_error!("Missing root package.json version.") unless env_present?(version)
|
||||
unless version.match?(/\A\d+\.\d+\.\d+(?:[.-]?beta[.-]\d+)?\z/i)
|
||||
UI.user_error!("Invalid package.json version '#{raw_value}'. Expected 2026.3.13 or 2026.3.13-beta.1.")
|
||||
UI.user_error!("Invalid package.json version '#{raw_value}'. Expected 2026.3.22 or 2026.3.22-beta.1.")
|
||||
end
|
||||
|
||||
version
|
||||
|
||||
@@ -783,7 +783,7 @@ extension AppState {
|
||||
remoteToken: String,
|
||||
remoteTokenDirty: Bool) -> [String: Any]
|
||||
{
|
||||
Self.updatedRemoteGatewayConfig(
|
||||
self.updatedRemoteGatewayConfig(
|
||||
current: current,
|
||||
transport: transport,
|
||||
remoteUrl: remoteUrl,
|
||||
@@ -804,7 +804,7 @@ extension AppState {
|
||||
remoteToken: String,
|
||||
remoteTokenDirty: Bool) -> [String: Any]
|
||||
{
|
||||
Self.syncedGatewayRoot(
|
||||
self.syncedGatewayRoot(
|
||||
currentRoot: currentRoot,
|
||||
connectionMode: connectionMode,
|
||||
remoteTransport: remoteTransport,
|
||||
|
||||
@@ -8,8 +8,8 @@ final class CanvasA2UIActionMessageHandler: NSObject, WKScriptMessageHandler {
|
||||
static let messageName = "openclawCanvasA2UIAction"
|
||||
static let allMessageNames = [messageName]
|
||||
|
||||
// Compatibility helper for debug/test shims. Runtime dispatch remains
|
||||
// limited to in-app canvas schemes in `didReceive`.
|
||||
/// Compatibility helper for debug/test shims. Runtime dispatch remains
|
||||
/// limited to in-app canvas schemes in `didReceive`.
|
||||
static func isLocalNetworkCanvasURL(_ url: URL) -> Bool {
|
||||
guard let scheme = url.scheme?.lowercased(), scheme == "http" || scheme == "https" else {
|
||||
return false
|
||||
|
||||
@@ -57,8 +57,7 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
|
||||
let allowedSchemesJSON = (
|
||||
try? String(
|
||||
data: JSONSerialization.data(withJSONObject: CanvasScheme.allSchemes),
|
||||
encoding: .utf8)
|
||||
) ?? "[]"
|
||||
encoding: .utf8)) ?? "[]"
|
||||
let bridgeScript = """
|
||||
(() => {
|
||||
try {
|
||||
|
||||
@@ -17,10 +17,10 @@ extension CronJobEditor {
|
||||
self.enabled = job.enabled
|
||||
self.deleteAfterRun = job.deleteAfterRun ?? false
|
||||
switch job.parsedSessionTarget {
|
||||
case .predefined(let target):
|
||||
case let .predefined(target):
|
||||
self.sessionTarget = target
|
||||
self.preservedSessionTargetRaw = nil
|
||||
case .session(let id):
|
||||
case let .session(id):
|
||||
self.sessionTarget = .isolated
|
||||
self.preservedSessionTargetRaw = "session:\(id)"
|
||||
}
|
||||
@@ -265,7 +265,10 @@ extension CronJobEditor {
|
||||
}
|
||||
|
||||
var effectiveSessionTargetRaw: String {
|
||||
if self.sessionTarget == .isolated, let preserved = self.preservedSessionTargetRaw?.trimmingCharacters(in: .whitespacesAndNewlines), !preserved.isEmpty {
|
||||
if self.sessionTarget == .isolated,
|
||||
let preserved = self.preservedSessionTargetRaw?.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
!preserved.isEmpty
|
||||
{
|
||||
return preserved
|
||||
}
|
||||
return self.sessionTarget.rawValue
|
||||
|
||||
@@ -16,10 +16,10 @@ enum CronCustomSessionTarget: Codable, Equatable {
|
||||
|
||||
var rawValue: String {
|
||||
switch self {
|
||||
case .predefined(let target):
|
||||
return target.rawValue
|
||||
case .session(let id):
|
||||
return "session:\(id)"
|
||||
case let .predefined(target):
|
||||
target.rawValue
|
||||
case let .session(id):
|
||||
"session:\(id)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,10 +328,10 @@ struct CronJob: Identifiable, Codable, Equatable {
|
||||
/// predefined enum.
|
||||
var sessionTarget: CronSessionTarget {
|
||||
switch self.parsedSessionTarget {
|
||||
case .predefined(let target):
|
||||
return target
|
||||
case let .predefined(target):
|
||||
target
|
||||
case .session:
|
||||
return .isolated
|
||||
.isolated
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,20 +342,20 @@ struct CronJob: Identifiable, Codable, Equatable {
|
||||
var transcriptSessionKey: String? {
|
||||
switch self.parsedSessionTarget {
|
||||
case .predefined(.main):
|
||||
return nil
|
||||
nil
|
||||
case .predefined(.isolated), .predefined(.current):
|
||||
return "cron:\(self.id)"
|
||||
case .session(let id):
|
||||
return id
|
||||
"cron:\(self.id)"
|
||||
case let .session(id):
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
var supportsAnnounceDelivery: Bool {
|
||||
switch self.parsedSessionTarget {
|
||||
case .predefined(.main):
|
||||
return false
|
||||
false
|
||||
case .predefined(.isolated), .predefined(.current), .session:
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import Foundation
|
||||
|
||||
enum ExecApprovalCommandDisplaySanitizer {
|
||||
private static let invisibleCodePoints: Set<UInt32> = [
|
||||
0x115F,
|
||||
0x1160,
|
||||
0x3164,
|
||||
0xFFA0,
|
||||
]
|
||||
|
||||
static func sanitize(_ text: String) -> String {
|
||||
var sanitized = ""
|
||||
sanitized.reserveCapacity(text.count)
|
||||
for scalar in text.unicodeScalars {
|
||||
if self.shouldEscape(scalar) {
|
||||
sanitized.append(self.escape(scalar))
|
||||
} else {
|
||||
sanitized.append(String(scalar))
|
||||
}
|
||||
}
|
||||
return sanitized
|
||||
}
|
||||
|
||||
private static func shouldEscape(_ scalar: UnicodeScalar) -> Bool {
|
||||
scalar.properties.generalCategory == .format || self.invisibleCodePoints.contains(scalar.value)
|
||||
}
|
||||
|
||||
private static func escape(_ scalar: UnicodeScalar) -> String {
|
||||
"\\u{\(String(scalar.value, radix: 16, uppercase: true))}"
|
||||
}
|
||||
}
|
||||
@@ -89,11 +89,11 @@ final class ExecApprovalsGatewayPrompter {
|
||||
private static func shouldAsk(security: ExecSecurity, ask: ExecAsk) -> Bool {
|
||||
switch ask {
|
||||
case .always:
|
||||
return true
|
||||
true
|
||||
case .onMiss:
|
||||
return security == .allowlist
|
||||
security == .allowlist
|
||||
case .off:
|
||||
return false
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,21 +113,21 @@ final class ExecApprovalsGatewayPrompter {
|
||||
let mode = AppStateStore.shared.connectionMode
|
||||
let activeSession = WebChatManager.shared.activeSessionKey?.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let requestSession = request.request.sessionKey?.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
|
||||
|
||||
// Read-only resolve to avoid disk writes on the MainActor
|
||||
let approvals = ExecApprovalsStore.resolveReadOnly(agentId: request.request.agentId)
|
||||
let security = approvals.agent.security
|
||||
let ask = approvals.agent.ask
|
||||
|
||||
|
||||
let shouldAsk = Self.shouldAsk(security: security, ask: ask)
|
||||
|
||||
|
||||
let canPresent = shouldAsk && Self.shouldPresent(
|
||||
mode: mode,
|
||||
activeSession: activeSession,
|
||||
requestSession: requestSession,
|
||||
lastInputSeconds: Self.lastInputSeconds(),
|
||||
thresholdSeconds: 120)
|
||||
|
||||
|
||||
return PresentationDecision(
|
||||
shouldAsk: shouldAsk,
|
||||
canPresent: canPresent,
|
||||
|
||||
@@ -271,7 +271,7 @@ enum ExecApprovalsPromptPresenter {
|
||||
commandText.drawsBackground = true
|
||||
commandText.backgroundColor = NSColor.textBackgroundColor
|
||||
commandText.font = NSFont.monospacedSystemFont(ofSize: NSFont.systemFontSize, weight: .regular)
|
||||
commandText.string = request.command
|
||||
commandText.string = ExecApprovalCommandDisplaySanitizer.sanitize(request.command)
|
||||
commandText.textContainerInset = NSSize(width: 6, height: 6)
|
||||
commandText.textContainer?.lineFragmentPadding = 0
|
||||
commandText.textContainer?.widthTracksTextView = true
|
||||
|
||||
@@ -147,7 +147,9 @@ actor MacNodeBrowserProxy {
|
||||
}
|
||||
|
||||
if method != "GET", let body = params.body {
|
||||
request.httpBody = try JSONSerialization.data(withJSONObject: body.foundationValue, options: [.fragmentsAllowed])
|
||||
request.httpBody = try JSONSerialization.data(
|
||||
withJSONObject: body.foundationValue,
|
||||
options: [.fragmentsAllowed])
|
||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
}
|
||||
|
||||
|
||||
@@ -337,7 +337,6 @@ extension OnboardingView {
|
||||
self.remoteProbePreflightMessage == nil && self.remoteProbeState != .checking
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func remoteConnectionSection() -> some View {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
HStack(alignment: .top, spacing: 12) {
|
||||
@@ -503,17 +502,17 @@ extension OnboardingView {
|
||||
{
|
||||
switch issue {
|
||||
case .tokenRequired:
|
||||
return ("key.fill", .orange)
|
||||
("key.fill", .orange)
|
||||
case .tokenMismatch:
|
||||
return ("exclamationmark.triangle.fill", .orange)
|
||||
("exclamationmark.triangle.fill", .orange)
|
||||
case .gatewayTokenNotConfigured:
|
||||
return ("wrench.and.screwdriver.fill", .orange)
|
||||
("wrench.and.screwdriver.fill", .orange)
|
||||
case .setupCodeExpired:
|
||||
return ("qrcode.viewfinder", .orange)
|
||||
("qrcode.viewfinder", .orange)
|
||||
case .passwordRequired:
|
||||
return ("lock.slash.fill", .orange)
|
||||
("lock.slash.fill", .orange)
|
||||
case .pairingRequired:
|
||||
return ("link.badge.plus", .orange)
|
||||
("link.badge.plus", .orange)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ enum RemoteGatewayProbe {
|
||||
}
|
||||
|
||||
do {
|
||||
_ = try await GatewayConnection.shared.healthSnapshot(timeoutMs: 10_000)
|
||||
_ = try await GatewayConnection.shared.healthSnapshot(timeoutMs: 10000)
|
||||
let authSource = await GatewayConnection.shared.authSource()
|
||||
return .ready(RemoteGatewayProbeSuccess(authSource: authSource))
|
||||
} catch {
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2026.3.14</string>
|
||||
<string>2026.3.22</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>202603140</string>
|
||||
<string>202603220</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>OpenClaw</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
||||
@@ -23,8 +23,8 @@ enum TalkModeGatewayConfigParser {
|
||||
defaultSilenceTimeoutMs: Int,
|
||||
envVoice: String?,
|
||||
sagVoice: String?,
|
||||
envApiKey: String?
|
||||
) -> TalkModeGatewayConfigState {
|
||||
envApiKey: String?) -> TalkModeGatewayConfigState
|
||||
{
|
||||
let talk = snapshot.config?["talk"]?.dictionaryValue
|
||||
let selection = TalkConfigParsing.selectProviderConfig(talk, defaultProvider: defaultProvider)
|
||||
let activeProvider = selection?.provider ?? defaultProvider
|
||||
@@ -81,8 +81,8 @@ enum TalkModeGatewayConfigParser {
|
||||
defaultSilenceTimeoutMs: Int,
|
||||
envVoice: String?,
|
||||
sagVoice: String?,
|
||||
envApiKey: String?
|
||||
) -> TalkModeGatewayConfigState {
|
||||
envApiKey: String?) -> TalkModeGatewayConfigState
|
||||
{
|
||||
let resolvedVoice =
|
||||
(envVoice?.isEmpty == false ? envVoice : nil) ??
|
||||
(sagVoice?.isEmpty == false ? sagVoice : nil)
|
||||
|
||||
@@ -2780,54 +2780,6 @@ public struct SkillsBinsResult: Codable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct SkillsInstallParams: Codable, Sendable {
|
||||
public let name: String
|
||||
public let installid: String
|
||||
public let timeoutms: Int?
|
||||
|
||||
public init(
|
||||
name: String,
|
||||
installid: String,
|
||||
timeoutms: Int?)
|
||||
{
|
||||
self.name = name
|
||||
self.installid = installid
|
||||
self.timeoutms = timeoutms
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case name
|
||||
case installid = "installId"
|
||||
case timeoutms = "timeoutMs"
|
||||
}
|
||||
}
|
||||
|
||||
public struct SkillsUpdateParams: Codable, Sendable {
|
||||
public let skillkey: String
|
||||
public let enabled: Bool?
|
||||
public let apikey: String?
|
||||
public let env: [String: AnyCodable]?
|
||||
|
||||
public init(
|
||||
skillkey: String,
|
||||
enabled: Bool?,
|
||||
apikey: String?,
|
||||
env: [String: AnyCodable]?)
|
||||
{
|
||||
self.skillkey = skillkey
|
||||
self.enabled = enabled
|
||||
self.apikey = apikey
|
||||
self.env = env
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case skillkey = "skillKey"
|
||||
case enabled
|
||||
case apikey = "apiKey"
|
||||
case env
|
||||
}
|
||||
}
|
||||
|
||||
public struct CronJob: Codable, Sendable {
|
||||
public let id: String
|
||||
public let agentid: String?
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
@testable import OpenClaw
|
||||
|
||||
struct ExecApprovalCommandDisplaySanitizerTests {
|
||||
@Test func `escapes invisible command spoofing characters`() {
|
||||
let input = "date\u{200B}\u{3164}\u{FFA0}\u{115F}\u{1160}가"
|
||||
#expect(
|
||||
ExecApprovalCommandDisplaySanitizer.sanitize(input) ==
|
||||
"date\\u{200B}\\u{3164}\\u{FFA0}\\u{115F}\\u{1160}가")
|
||||
}
|
||||
}
|
||||
@@ -2780,54 +2780,6 @@ public struct SkillsBinsResult: Codable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct SkillsInstallParams: Codable, Sendable {
|
||||
public let name: String
|
||||
public let installid: String
|
||||
public let timeoutms: Int?
|
||||
|
||||
public init(
|
||||
name: String,
|
||||
installid: String,
|
||||
timeoutms: Int?)
|
||||
{
|
||||
self.name = name
|
||||
self.installid = installid
|
||||
self.timeoutms = timeoutms
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case name
|
||||
case installid = "installId"
|
||||
case timeoutms = "timeoutMs"
|
||||
}
|
||||
}
|
||||
|
||||
public struct SkillsUpdateParams: Codable, Sendable {
|
||||
public let skillkey: String
|
||||
public let enabled: Bool?
|
||||
public let apikey: String?
|
||||
public let env: [String: AnyCodable]?
|
||||
|
||||
public init(
|
||||
skillkey: String,
|
||||
enabled: Bool?,
|
||||
apikey: String?,
|
||||
env: [String: AnyCodable]?)
|
||||
{
|
||||
self.skillkey = skillkey
|
||||
self.enabled = enabled
|
||||
self.apikey = apikey
|
||||
self.env = env
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case skillkey = "skillKey"
|
||||
case enabled
|
||||
case apikey = "apiKey"
|
||||
case env
|
||||
}
|
||||
}
|
||||
|
||||
public struct CronJob: Codable, Sendable {
|
||||
public let id: String
|
||||
public let agentid: String?
|
||||
|
||||
@@ -6869,6 +6869,16 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "agents.list.*.tools.exec.strictInlineEval",
|
||||
"kind": "core",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "agents.list.*.tools.exec.timeoutSec",
|
||||
"kind": "core",
|
||||
@@ -31087,6 +31097,26 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.synology-chat.dangerouslyAllowInheritedWebhookPath",
|
||||
"kind": "channel",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.synology-chat.dangerouslyAllowNameMatching",
|
||||
"kind": "channel",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.telegram",
|
||||
"kind": "channel",
|
||||
@@ -42146,6 +42176,46 @@
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "hooks.internal.installs.*.clawhubChannel",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "hooks.internal.installs.*.clawhubFamily",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "hooks.internal.installs.*.clawhubPackage",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "hooks.internal.installs.*.clawhubUrl",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "hooks.internal.installs.*.hooks",
|
||||
"kind": "core",
|
||||
@@ -45683,7 +45753,7 @@
|
||||
"storage"
|
||||
],
|
||||
"label": "Node Browser Proxy Allowed Profiles",
|
||||
"help": "Optional allowlist of browser profile names exposed through node proxy routing. Leave empty to expose all configured profiles, or use a tight list to enforce least-privilege profile access.",
|
||||
"help": "Optional allowlist of browser profile names exposed through node proxy routing. Leave empty to preserve the default full profile surface, including profile create/delete routes. When set, OpenClaw enforces least-privilege profile access and blocks persistent profile create/delete through the proxy.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
@@ -45994,7 +46064,7 @@
|
||||
"advanced"
|
||||
],
|
||||
"label": "Expected acpx Version",
|
||||
"help": "Exact version to enforce (for example 0.1.16) or \"any\" to skip strict version matching.",
|
||||
"help": "Exact version to enforce or \"any\" to skip strict version matching.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -47259,6 +47329,127 @@
|
||||
"help": "Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/deepgram-provider",
|
||||
"help": "OpenClaw Deepgram media-understanding provider (plugin: deepgram)",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.config",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/deepgram-provider Config",
|
||||
"help": "Plugin-defined config payload for deepgram.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.enabled",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Enable @openclaw/deepgram-provider",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.hooks",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Hook Policy",
|
||||
"help": "Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.hooks.allowPromptInjection",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Allow Prompt Injection Hooks",
|
||||
"help": "Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.subagent",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Subagent Policy",
|
||||
"help": "Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.subagent.allowedModels",
|
||||
"kind": "plugin",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Plugin Subagent Allowed Models",
|
||||
"help": "Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.subagent.allowedModels.*",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.subagent.allowModelOverride",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Allow Plugin Subagent Model Override",
|
||||
"help": "Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.device-pair",
|
||||
"kind": "plugin",
|
||||
@@ -48094,6 +48285,170 @@
|
||||
"help": "Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/duckduckgo-plugin",
|
||||
"help": "OpenClaw DuckDuckGo plugin (plugin: duckduckgo)",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.config",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/duckduckgo-plugin Config",
|
||||
"help": "Plugin-defined config payload for duckduckgo.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.config.webSearch",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.config.webSearch.region",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "DuckDuckGo Region",
|
||||
"help": "Optional DuckDuckGo region code such as us-en, uk-en, or de-de.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.config.webSearch.safeSearch",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"enumValues": [
|
||||
"strict",
|
||||
"moderate",
|
||||
"off"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "DuckDuckGo SafeSearch",
|
||||
"help": "SafeSearch level for DuckDuckGo results.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.enabled",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Enable @openclaw/duckduckgo-plugin",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.hooks",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Hook Policy",
|
||||
"help": "Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.hooks.allowPromptInjection",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Allow Prompt Injection Hooks",
|
||||
"help": "Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.subagent",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Subagent Policy",
|
||||
"help": "Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.subagent.allowedModels",
|
||||
"kind": "plugin",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Plugin Subagent Allowed Models",
|
||||
"help": "Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.subagent.allowedModels.*",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.subagent.allowModelOverride",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Allow Plugin Subagent Model Override",
|
||||
"help": "Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.elevenlabs",
|
||||
"kind": "plugin",
|
||||
@@ -48215,6 +48570,155 @@
|
||||
"help": "Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/exa-plugin",
|
||||
"help": "OpenClaw Exa plugin (plugin: exa)",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.config",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/exa-plugin Config",
|
||||
"help": "Plugin-defined config payload for exa.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.config.webSearch",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.config.webSearch.apiKey",
|
||||
"kind": "plugin",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"auth",
|
||||
"security"
|
||||
],
|
||||
"label": "Exa API Key",
|
||||
"help": "Exa Search API key (fallback: EXA_API_KEY env var).",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.enabled",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Enable @openclaw/exa-plugin",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.hooks",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Hook Policy",
|
||||
"help": "Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.hooks.allowPromptInjection",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Allow Prompt Injection Hooks",
|
||||
"help": "Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.subagent",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Subagent Policy",
|
||||
"help": "Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.subagent.allowedModels",
|
||||
"kind": "plugin",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Plugin Subagent Allowed Models",
|
||||
"help": "Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.subagent.allowedModels.*",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.subagent.allowModelOverride",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Allow Plugin Subagent Model Override",
|
||||
"help": "Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.fal",
|
||||
"kind": "plugin",
|
||||
@@ -49025,6 +49529,127 @@
|
||||
"help": "Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/groq-provider",
|
||||
"help": "OpenClaw Groq media-understanding provider (plugin: groq)",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.config",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/groq-provider Config",
|
||||
"help": "Plugin-defined config payload for groq.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.enabled",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Enable @openclaw/groq-provider",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.hooks",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Hook Policy",
|
||||
"help": "Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.hooks.allowPromptInjection",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Allow Prompt Injection Hooks",
|
||||
"help": "Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.subagent",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Subagent Policy",
|
||||
"help": "Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.subagent.allowedModels",
|
||||
"kind": "plugin",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Plugin Subagent Allowed Models",
|
||||
"help": "Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.subagent.allowedModels.*",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.subagent.allowModelOverride",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Allow Plugin Subagent Model Override",
|
||||
"help": "Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.huggingface",
|
||||
"kind": "plugin",
|
||||
@@ -57674,6 +58299,46 @@
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.installs.*.clawhubChannel",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.installs.*.clawhubFamily",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.installs.*.clawhubPackage",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.installs.*.clawhubUrl",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.installs.*.installedAt",
|
||||
"kind": "core",
|
||||
@@ -60430,6 +61095,20 @@
|
||||
"help": "Execution security posture selector controlling sandbox/approval expectations for command execution. Keep strict security mode for untrusted prompts and relax only for trusted operator workflows.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "tools.exec.strictInlineEval",
|
||||
"kind": "core",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"tools"
|
||||
],
|
||||
"label": "Require Inline-Eval Approval",
|
||||
"help": "Require explicit approval for interpreter inline-eval forms such as `python -c`, `node -e`, `ruby -e`, or `osascript -e`. Prevents silent allowlist reuse and downgrades allow-always to ask-each-time for those forms.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "tools.exec.timeoutSec",
|
||||
"kind": "core",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{"generatedBy":"scripts/generate-config-doc-baseline.ts","recordType":"meta","totalPaths":5566}
|
||||
{"generatedBy":"scripts/generate-config-doc-baseline.ts","recordType":"meta","totalPaths":5619}
|
||||
{"recordType":"path","path":"acp","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"ACP","help":"ACP runtime controls for enabling dispatch, selecting backends, constraining allowed agent targets, and tuning streamed turn projection behavior.","hasChildren":true}
|
||||
{"recordType":"path","path":"acp.allowedAgents","kind":"core","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"ACP Allowed Agents","help":"Allowlist of ACP target agent ids permitted for ACP runtime sessions. Empty means no additional allowlist restriction.","hasChildren":true}
|
||||
{"recordType":"path","path":"acp.allowedAgents.*","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
@@ -614,6 +614,7 @@
|
||||
{"recordType":"path","path":"agents.list.*.tools.exec.safeBinTrustedDirs","kind":"core","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"agents.list.*.tools.exec.safeBinTrustedDirs.*","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"agents.list.*.tools.exec.security","kind":"core","type":"string","required":false,"enumValues":["deny","allowlist","full"],"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"agents.list.*.tools.exec.strictInlineEval","kind":"core","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"agents.list.*.tools.exec.timeoutSec","kind":"core","type":"integer","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"agents.list.*.tools.fs","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"agents.list.*.tools.fs.workspaceOnly","kind":"core","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
@@ -2803,6 +2804,8 @@
|
||||
{"recordType":"path","path":"channels.slack.webhookPath","kind":"channel","type":"string","required":true,"defaultValue":"/slack/events","deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.synology-chat","kind":"channel","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["channels","network"],"label":"Synology Chat","help":"Connect your Synology NAS Chat to OpenClaw with full agent capabilities.","hasChildren":true}
|
||||
{"recordType":"path","path":"channels.synology-chat.*","kind":"channel","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.synology-chat.dangerouslyAllowInheritedWebhookPath","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.synology-chat.dangerouslyAllowNameMatching","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.telegram","kind":"channel","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["channels","network"],"label":"Telegram","help":"simplest way to get started — register a bot with @BotFather and get going.","hasChildren":true}
|
||||
{"recordType":"path","path":"channels.telegram.accounts","kind":"channel","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"channels.telegram.accounts.*","kind":"channel","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
@@ -3756,6 +3759,10 @@
|
||||
{"recordType":"path","path":"hooks.internal.handlers.*.module","kind":"core","type":"string","required":true,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Internal Hook Module","help":"Safe relative module path for the internal hook handler implementation loaded at runtime. Keep module files in reviewed directories and avoid dynamic path composition.","hasChildren":false}
|
||||
{"recordType":"path","path":"hooks.internal.installs","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Internal Hook Install Records","help":"Install metadata for internal hook modules, including source and resolved artifacts for repeatable deployments. Use this as operational provenance and avoid manual drift edits.","hasChildren":true}
|
||||
{"recordType":"path","path":"hooks.internal.installs.*","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"hooks.internal.installs.*.clawhubChannel","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"hooks.internal.installs.*.clawhubFamily","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"hooks.internal.installs.*.clawhubPackage","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"hooks.internal.installs.*.clawhubUrl","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"hooks.internal.installs.*.hooks","kind":"core","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"hooks.internal.installs.*.hooks.*","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"hooks.internal.installs.*.installedAt","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
@@ -4053,7 +4060,7 @@
|
||||
{"recordType":"path","path":"models.providers.*.models.*.reasoning","kind":"core","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"nodeHost","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Node Host","help":"Node host controls for features exposed from this gateway node to other nodes or clients. Keep defaults unless you intentionally proxy local capabilities across your node network.","hasChildren":true}
|
||||
{"recordType":"path","path":"nodeHost.browserProxy","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["network"],"label":"Node Browser Proxy","help":"Groups browser-proxy settings for exposing local browser control through node routing. Enable only when remote node workflows need your local browser profiles.","hasChildren":true}
|
||||
{"recordType":"path","path":"nodeHost.browserProxy.allowProfiles","kind":"core","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access","network","storage"],"label":"Node Browser Proxy Allowed Profiles","help":"Optional allowlist of browser profile names exposed through node proxy routing. Leave empty to expose all configured profiles, or use a tight list to enforce least-privilege profile access.","hasChildren":true}
|
||||
{"recordType":"path","path":"nodeHost.browserProxy.allowProfiles","kind":"core","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access","network","storage"],"label":"Node Browser Proxy Allowed Profiles","help":"Optional allowlist of browser profile names exposed through node proxy routing. Leave empty to preserve the default full profile surface, including profile create/delete routes. When set, OpenClaw enforces least-privilege profile access and blocks persistent profile create/delete through the proxy.","hasChildren":true}
|
||||
{"recordType":"path","path":"nodeHost.browserProxy.allowProfiles.*","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"nodeHost.browserProxy.enabled","kind":"core","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["network"],"label":"Node Browser Proxy Enabled","help":"Expose the local browser control server through node proxy routing so remote clients can use this host's browser capabilities. Keep disabled unless remote automation explicitly depends on it.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugins","help":"Plugin system controls for enabling extensions, constraining load scope, configuring entries, and tracking installs. Keep plugin policy explicit and least-privilege in production environments.","hasChildren":true}
|
||||
@@ -4077,7 +4084,7 @@
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"ACPX Runtime Config","help":"Plugin-defined config payload for acpx.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.command","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"acpx Command","help":"Optional path/command override for acpx (for example /home/user/repos/acpx/dist/cli.js). Leave unset to use plugin-local bundled acpx.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.cwd","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Default Working Directory","help":"Default cwd for ACP session operations when not set per session.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.expectedVersion","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Expected acpx Version","help":"Exact version to enforce (for example 0.1.16) or \"any\" to skip strict version matching.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.expectedVersion","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Expected acpx Version","help":"Exact version to enforce or \"any\" to skip strict version matching.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.mcpServers","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"MCP Servers","help":"Named MCP server definitions to inject into ACPX-backed session bootstrap. Each entry needs a command and can include args and env.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.mcpServers.*","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.mcpServers.*.args","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
@@ -4172,6 +4179,15 @@
|
||||
{"recordType":"path","path":"plugins.entries.copilot-proxy.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.copilot-proxy.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.copilot-proxy.subagent.allowModelOverride","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Plugin Subagent Model Override","help":"Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/deepgram-provider","help":"OpenClaw Deepgram media-understanding provider (plugin: deepgram)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/deepgram-provider Config","help":"Plugin-defined config payload for deepgram.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/deepgram-provider","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.hooks","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Hook Policy","help":"Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.hooks.allowPromptInjection","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Prompt Injection Hooks","help":"Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.subagent","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Subagent Policy","help":"Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.subagent.allowModelOverride","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Plugin Subagent Model Override","help":"Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.device-pair","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Device Pairing","help":"Generate setup codes and approve device pairing requests. (plugin: device-pair)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.device-pair.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Device Pairing Config","help":"Plugin-defined config payload for device-pair.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.device-pair.config.publicUrl","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Gateway URL","help":"Public WebSocket URL used for /pair setup codes (ws/wss or http/https).","hasChildren":false}
|
||||
@@ -4231,6 +4247,18 @@
|
||||
{"recordType":"path","path":"plugins.entries.discord.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.discord.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.discord.subagent.allowModelOverride","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Plugin Subagent Model Override","help":"Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/duckduckgo-plugin","help":"OpenClaw DuckDuckGo plugin (plugin: duckduckgo)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/duckduckgo-plugin Config","help":"Plugin-defined config payload for duckduckgo.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.config.webSearch","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.config.webSearch.region","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"DuckDuckGo Region","help":"Optional DuckDuckGo region code such as us-en, uk-en, or de-de.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.config.webSearch.safeSearch","kind":"plugin","type":"string","required":false,"enumValues":["strict","moderate","off"],"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"DuckDuckGo SafeSearch","help":"SafeSearch level for DuckDuckGo results.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/duckduckgo-plugin","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.hooks","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Hook Policy","help":"Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.hooks.allowPromptInjection","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Prompt Injection Hooks","help":"Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.subagent","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Subagent Policy","help":"Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.subagent.allowModelOverride","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Plugin Subagent Model Override","help":"Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.elevenlabs","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/elevenlabs-speech","help":"OpenClaw ElevenLabs speech plugin (plugin: elevenlabs)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.elevenlabs.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/elevenlabs-speech Config","help":"Plugin-defined config payload for elevenlabs.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.elevenlabs.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/elevenlabs-speech","hasChildren":false}
|
||||
@@ -4240,6 +4268,17 @@
|
||||
{"recordType":"path","path":"plugins.entries.elevenlabs.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.elevenlabs.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.elevenlabs.subagent.allowModelOverride","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Plugin Subagent Model Override","help":"Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.exa","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/exa-plugin","help":"OpenClaw Exa plugin (plugin: exa)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.exa.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/exa-plugin Config","help":"Plugin-defined config payload for exa.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.exa.config.webSearch","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.exa.config.webSearch.apiKey","kind":"plugin","type":["object","string"],"required":false,"deprecated":false,"sensitive":true,"tags":["auth","security"],"label":"Exa API Key","help":"Exa Search API key (fallback: EXA_API_KEY env var).","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.exa.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/exa-plugin","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.exa.hooks","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Hook Policy","help":"Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.exa.hooks.allowPromptInjection","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Prompt Injection Hooks","help":"Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.exa.subagent","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Subagent Policy","help":"Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.exa.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.exa.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.exa.subagent.allowModelOverride","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Plugin Subagent Model Override","help":"Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.fal","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/fal-provider","help":"OpenClaw fal provider plugin (plugin: fal)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.fal.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/fal-provider Config","help":"Plugin-defined config payload for fal.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.fal.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/fal-provider","hasChildren":false}
|
||||
@@ -4300,6 +4339,15 @@
|
||||
{"recordType":"path","path":"plugins.entries.googlechat.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.googlechat.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.googlechat.subagent.allowModelOverride","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Plugin Subagent Model Override","help":"Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.groq","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/groq-provider","help":"OpenClaw Groq media-understanding provider (plugin: groq)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.groq.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/groq-provider Config","help":"Plugin-defined config payload for groq.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.groq.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/groq-provider","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.groq.hooks","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Hook Policy","help":"Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.groq.hooks.allowPromptInjection","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Prompt Injection Hooks","help":"Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.groq.subagent","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Subagent Policy","help":"Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.groq.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.groq.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.groq.subagent.allowModelOverride","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Plugin Subagent Model Override","help":"Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.huggingface","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/huggingface-provider","help":"OpenClaw Hugging Face provider plugin (plugin: huggingface)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.huggingface.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/huggingface-provider Config","help":"Plugin-defined config payload for huggingface.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.huggingface.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/huggingface-provider","hasChildren":false}
|
||||
@@ -4959,6 +5007,10 @@
|
||||
{"recordType":"path","path":"plugins.entries.zalouser.subagent.allowModelOverride","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Plugin Subagent Model Override","help":"Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.installs","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Install Records","help":"CLI-managed install metadata (used by `openclaw plugins update` to locate install sources).","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.installs.*","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.installs.*.clawhubChannel","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.installs.*.clawhubFamily","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.installs.*.clawhubPackage","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.installs.*.clawhubUrl","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.installs.*.installedAt","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Install Time","help":"ISO timestamp of last install/update.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.installs.*.installPath","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["storage"],"label":"Plugin Install Path","help":"Resolved install directory (usually ~/.openclaw/extensions/<id>).","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.installs.*.integrity","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Resolved Integrity","help":"Resolved npm dist integrity hash for the fetched artifact (if reported by npm).","hasChildren":false}
|
||||
@@ -5183,6 +5235,7 @@
|
||||
{"recordType":"path","path":"tools.exec.safeBinTrustedDirs","kind":"core","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["storage","tools"],"label":"Exec Safe Bin Trusted Dirs","help":"Additional explicit directories trusted for safe-bin path checks (PATH entries are never auto-trusted).","hasChildren":true}
|
||||
{"recordType":"path","path":"tools.exec.safeBinTrustedDirs.*","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"tools.exec.security","kind":"core","type":"string","required":false,"enumValues":["deny","allowlist","full"],"deprecated":false,"sensitive":false,"tags":["tools"],"label":"Exec Security","help":"Execution security posture selector controlling sandbox/approval expectations for command execution. Keep strict security mode for untrusted prompts and relax only for trusted operator workflows.","hasChildren":false}
|
||||
{"recordType":"path","path":"tools.exec.strictInlineEval","kind":"core","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["tools"],"label":"Require Inline-Eval Approval","help":"Require explicit approval for interpreter inline-eval forms such as `python -c`, `node -e`, `ruby -e`, or `osascript -e`. Prevents silent allowlist reuse and downgrades allow-always to ask-each-time for those forms.","hasChildren":false}
|
||||
{"recordType":"path","path":"tools.exec.timeoutSec","kind":"core","type":"integer","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"tools.fs","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"tools.fs.workspaceOnly","kind":"core","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["tools"],"label":"Workspace-only FS tools","help":"Restrict filesystem tools (read/write/edit/apply_patch) to the workspace directory (default: false).","hasChildren":false}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +1,36 @@
|
||||
{"category":"legacy","entrypoint":"index","importSpecifier":"openclaw/plugin-sdk","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/index.ts"}
|
||||
{"declaration":"export function buildFalImageGenerationProvider(): ImageGenerationProvider;","entrypoint":"index","exportName":"buildFalImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":188,"sourcePath":"src/image-generation/providers/fal.ts"}
|
||||
{"declaration":"export function buildGoogleImageGenerationProvider(): ImageGenerationProvider;","entrypoint":"index","exportName":"buildGoogleImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":96,"sourcePath":"src/image-generation/providers/google.ts"}
|
||||
{"declaration":"export function buildOpenAIImageGenerationProvider(): ImageGenerationProvider;","entrypoint":"index","exportName":"buildOpenAIImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":22,"sourcePath":"src/image-generation/providers/openai.ts"}
|
||||
{"declaration":"export function buildFalImageGenerationProvider(): ImageGenerationProvider;","entrypoint":"index","exportName":"buildFalImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":190,"sourcePath":"extensions/fal/image-generation-provider.ts"}
|
||||
{"declaration":"export function buildGoogleImageGenerationProvider(): ImageGenerationProvider;","entrypoint":"index","exportName":"buildGoogleImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":95,"sourcePath":"extensions/google/image-generation-provider.ts"}
|
||||
{"declaration":"export function buildOpenAIImageGenerationProvider(): ImageGenerationProvider;","entrypoint":"index","exportName":"buildOpenAIImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":22,"sourcePath":"extensions/openai/image-generation-provider.ts"}
|
||||
{"declaration":"export function delegateCompactionToRuntime(params: { sessionId: string; sessionKey?: string | undefined; sessionFile: string; tokenBudget?: number | undefined; force?: boolean | undefined; currentTokenCount?: number | undefined; compactionTarget?: \"budget\" | ... 1 more ... | undefined; customInstructions?: string | undefined; runtimeContext?: ContextEngineRuntimeContext | undefined; }): Promise<...>;","entrypoint":"index","exportName":"delegateCompactionToRuntime","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":16,"sourcePath":"src/context-engine/delegate.ts"}
|
||||
{"declaration":"export function emptyPluginConfigSchema(): OpenClawPluginConfigSchema;","entrypoint":"index","exportName":"emptyPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":13,"sourcePath":"src/plugins/config-schema.ts"}
|
||||
{"declaration":"export function onDiagnosticEvent(listener: (evt: DiagnosticEventPayload) => void): () => void;","entrypoint":"index","exportName":"onDiagnosticEvent","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":229,"sourcePath":"src/infra/diagnostic-events.ts"}
|
||||
{"declaration":"export function registerContextEngine(id: string, factory: ContextEngineFactory): ContextEngineRegistrationResult;","entrypoint":"index","exportName":"registerContextEngine","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":377,"sourcePath":"src/context-engine/registry.ts"}
|
||||
{"declaration":"export type AnyAgentTool = AnyAgentTool;","entrypoint":"index","exportName":"AnyAgentTool","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/agents/tools/common.ts"}
|
||||
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"index","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":139,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"index","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":17,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAgentToolFactory = ChannelAgentToolFactory;","entrypoint":"index","exportName":"ChannelAgentToolFactory","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":21,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelCapabilities = ChannelCapabilities;","entrypoint":"index","exportName":"ChannelCapabilities","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":223,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelConfigSchema = ChannelConfigSchema;","entrypoint":"index","exportName":"ChannelConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":47,"sourcePath":"src/channels/plugins/types.plugin.ts"}
|
||||
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"index","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"index","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":18,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAgentToolFactory = ChannelAgentToolFactory;","entrypoint":"index","exportName":"ChannelAgentToolFactory","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":23,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelCapabilities = ChannelCapabilities;","entrypoint":"index","exportName":"ChannelCapabilities","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":230,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelConfigSchema = ChannelConfigSchema;","entrypoint":"index","exportName":"ChannelConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":48,"sourcePath":"src/channels/plugins/types.plugin.ts"}
|
||||
{"declaration":"export type ChannelConfiguredBindingConversationRef = ChannelConfiguredBindingConversationRef;","entrypoint":"index","exportName":"ChannelConfiguredBindingConversationRef","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":553,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelConfiguredBindingMatch = ChannelConfiguredBindingMatch;","entrypoint":"index","exportName":"ChannelConfiguredBindingMatch","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":558,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelConfiguredBindingProvider = ChannelConfiguredBindingProvider;","entrypoint":"index","exportName":"ChannelConfiguredBindingProvider","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":562,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelGatewayContext = ChannelGatewayContext<ResolvedAccount>;","entrypoint":"index","exportName":"ChannelGatewayContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":238,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelId = ChannelId;","entrypoint":"index","exportName":"ChannelId","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"index","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":506,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"index","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":473,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"index","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":516,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"index","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":482,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionName = \"send\" | \"broadcast\" | \"poll\" | \"poll-vote\" | \"react\" | \"reactions\" | \"read\" | \"edit\" | \"unsend\" | \"reply\" | \"sendWithEffect\" | \"renameGroup\" | \"setGroupIcon\" | \"addParticipant\" | \"removeParticipant\" | \"leaveGroup\" | \"sendAttachment\" | \"delete\" | \"pin\" | \"unpin\" | \"list-pins\" | \"permissions\" | \"thread-create\" | \"thread-list\" | \"thread-reply\" | \"search\" | \"sticker\" | \"sticker-search\" | \"member-info\" | \"role-info\" | \"emoji-list\" | \"emoji-upload\" | \"sticker-upload\" | \"role-add\" | \"role-remove\" | \"channel-info\" | \"channel-list\" | \"channel-create\" | \"channel-edit\" | \"channel-delete\" | \"channel-move\" | \"category-create\" | \"category-edit\" | \"category-delete\" | \"topic-create\" | \"topic-edit\" | \"voice-status\" | \"event-list\" | \"event-create\" | \"timeout\" | \"kick\" | \"ban\" | \"set-profile\" | \"set-presence\" | \"download-file\";","entrypoint":"index","exportName":"ChannelMessageActionName","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/channels/plugins/types.ts"}
|
||||
{"declaration":"export type ChannelPlugin = ChannelPlugin<ResolvedAccount, Probe, Audit>;","entrypoint":"index","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/channels/plugins/types.plugin.ts"}
|
||||
{"declaration":"export type ChannelPlugin = ChannelPlugin<ResolvedAccount, Probe, Audit>;","entrypoint":"index","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":55,"sourcePath":"src/channels/plugins/types.plugin.ts"}
|
||||
{"declaration":"export type ChannelSetupAdapter = ChannelSetupAdapter;","entrypoint":"index","exportName":"ChannelSetupAdapter","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":56,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"index","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":60,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"index","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":63,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelSetupWizard = ChannelSetupWizard;","entrypoint":"index","exportName":"ChannelSetupWizard","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":247,"sourcePath":"src/channels/plugins/setup-wizard.ts"}
|
||||
{"declaration":"export type ChannelSetupWizardAllowFromEntry = ChannelSetupWizardAllowFromEntry;","entrypoint":"index","exportName":"ChannelSetupWizardAllowFromEntry","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":154,"sourcePath":"src/channels/plugins/setup-wizard.ts"}
|
||||
{"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"index","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":97,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"index","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":100,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"index","exportName":"ClawdbotConfig","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"}
|
||||
{"declaration":"export type CompiledConfiguredBinding = CompiledConfiguredBinding;","entrypoint":"index","exportName":"CompiledConfiguredBinding","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":38,"sourcePath":"src/channels/plugins/binding-types.ts"}
|
||||
{"declaration":"export type ConfiguredBindingConversation = ConversationRef;","entrypoint":"index","exportName":"ConfiguredBindingConversation","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/channels/plugins/binding-types.ts"}
|
||||
{"declaration":"export type ConfiguredBindingResolution = ConfiguredBindingResolution;","entrypoint":"index","exportName":"ConfiguredBindingResolution","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":49,"sourcePath":"src/channels/plugins/binding-types.ts"}
|
||||
{"declaration":"export type ContextEngineFactory = ContextEngineFactory;","entrypoint":"index","exportName":"ContextEngineFactory","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/context-engine/registry.ts"}
|
||||
{"declaration":"export type ContextEngineFactory = ContextEngineFactory;","entrypoint":"index","exportName":"ContextEngineFactory","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":10,"sourcePath":"src/context-engine/registry.ts"}
|
||||
{"declaration":"export type ContextEngineInfo = ContextEngineInfo;","entrypoint":"index","exportName":"ContextEngineInfo","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":46,"sourcePath":"src/context-engine/types.ts"}
|
||||
{"declaration":"export type ContextEngineMaintenanceResult = TranscriptRewriteResult;","entrypoint":"index","exportName":"ContextEngineMaintenanceResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":84,"sourcePath":"src/context-engine/types.ts"}
|
||||
{"declaration":"export type ContextEngineRuntimeContext = ContextEngineRuntimeContext;","entrypoint":"index","exportName":"ContextEngineRuntimeContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":86,"sourcePath":"src/context-engine/types.ts"}
|
||||
@@ -42,21 +42,21 @@
|
||||
{"declaration":"export type ImageGenerationResolution = ImageGenerationResolution;","entrypoint":"index","exportName":"ImageGenerationResolution","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/image-generation/types.ts"}
|
||||
{"declaration":"export type ImageGenerationResult = ImageGenerationResult;","entrypoint":"index","exportName":"ImageGenerationResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":36,"sourcePath":"src/image-generation/types.ts"}
|
||||
{"declaration":"export type ImageGenerationSourceImage = ImageGenerationSourceImage;","entrypoint":"index","exportName":"ImageGenerationSourceImage","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":14,"sourcePath":"src/image-generation/types.ts"}
|
||||
{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"index","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":935,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"index","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":951,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"index","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"}
|
||||
{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"index","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1292,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"index","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":80,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"index","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":58,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"index","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/plugins/runtime/types.ts"}
|
||||
{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"index","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"index","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":130,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"index","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":284,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"index","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1314,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"index","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":88,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"index","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":59,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"index","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/plugins/runtime/types.ts"}
|
||||
{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"index","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":155,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"index","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":140,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"index","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":295,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ReplyPayload = ReplyPayload;","entrypoint":"index","exportName":"ReplyPayload","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":76,"sourcePath":"src/auto-reply/types.ts"}
|
||||
{"declaration":"export type RuntimeEnv = RuntimeEnv;","entrypoint":"index","exportName":"RuntimeEnv","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/runtime.ts"}
|
||||
{"declaration":"export type RuntimeLogger = RuntimeLogger;","entrypoint":"index","exportName":"RuntimeLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":3,"sourcePath":"src/plugins/runtime/types-core.ts"}
|
||||
{"declaration":"export type RuntimeLogger = RuntimeLogger;","entrypoint":"index","exportName":"RuntimeLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/plugins/runtime/types-core.ts"}
|
||||
{"declaration":"export type SecretInput = SecretInput;","entrypoint":"index","exportName":"SecretInput","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":16,"sourcePath":"src/config/types.secrets.ts"}
|
||||
{"declaration":"export type SecretRef = SecretRef;","entrypoint":"index","exportName":"SecretRef","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":10,"sourcePath":"src/config/types.secrets.ts"}
|
||||
{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"index","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":917,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"index","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":933,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type StatefulBindingTargetDescriptor = StatefulBindingTargetDescriptor;","entrypoint":"index","exportName":"StatefulBindingTargetDescriptor","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":17,"sourcePath":"src/channels/plugins/binding-types.ts"}
|
||||
{"declaration":"export type StatefulBindingTargetDriver = StatefulBindingTargetDriver;","entrypoint":"index","exportName":"StatefulBindingTargetDriver","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":15,"sourcePath":"src/channels/plugins/stateful-target-drivers.ts"}
|
||||
{"declaration":"export type StatefulBindingTargetReadyResult = StatefulBindingTargetReadyResult;","entrypoint":"index","exportName":"StatefulBindingTargetReadyResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":7,"sourcePath":"src/channels/plugins/stateful-target-drivers.ts"}
|
||||
@@ -98,8 +98,8 @@
|
||||
{"declaration":"export type BasicAllowlistResolutionEntry = BasicAllowlistResolutionEntry;","entrypoint":"allow-from","exportName":"BasicAllowlistResolutionEntry","importSpecifier":"openclaw/plugin-sdk/allow-from","kind":"type","recordType":"export","sourceLine":129,"sourcePath":"src/plugin-sdk/allow-from.ts"}
|
||||
{"declaration":"export type CompiledAllowlist = CompiledAllowlist;","entrypoint":"allow-from","exportName":"CompiledAllowlist","importSpecifier":"openclaw/plugin-sdk/allow-from","kind":"type","recordType":"export","sourceLine":19,"sourcePath":"src/channels/allowlist-match.ts"}
|
||||
{"category":"channel","entrypoint":"channel-actions","importSpecifier":"openclaw/plugin-sdk/channel-actions","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/channel-actions.ts"}
|
||||
{"declaration":"export function createMessageToolButtonsSchema(): TSchema;","entrypoint":"channel-actions","exportName":"createMessageToolButtonsSchema","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":10,"sourcePath":"src/plugin-sdk/channel-actions.ts"}
|
||||
{"declaration":"export function createMessageToolCardSchema(): TSchema;","entrypoint":"channel-actions","exportName":"createMessageToolCardSchema","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":25,"sourcePath":"src/plugin-sdk/channel-actions.ts"}
|
||||
{"declaration":"export function createMessageToolButtonsSchema(): TSchema;","entrypoint":"channel-actions","exportName":"createMessageToolButtonsSchema","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":11,"sourcePath":"src/plugin-sdk/channel-actions.ts"}
|
||||
{"declaration":"export function createMessageToolCardSchema(): TSchema;","entrypoint":"channel-actions","exportName":"createMessageToolCardSchema","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":27,"sourcePath":"src/plugin-sdk/channel-actions.ts"}
|
||||
{"declaration":"export function createUnionActionGate<TAccount, TKey extends string>(accounts: readonly TAccount[], createGate: (account: TAccount) => OptionalDefaultGate<TKey>): OptionalDefaultGate<TKey>;","entrypoint":"channel-actions","exportName":"createUnionActionGate","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":13,"sourcePath":"src/channels/plugins/actions/shared.ts"}
|
||||
{"declaration":"export function listTokenSourcedAccounts<TAccount extends TokenSourcedAccount>(accounts: readonly TAccount[]): TAccount[];","entrypoint":"channel-actions","exportName":"listTokenSourcedAccounts","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":7,"sourcePath":"src/channels/plugins/actions/shared.ts"}
|
||||
{"declaration":"export function resolveReactionMessageId(params: { args: Record<string, unknown>; toolContext?: ReactionToolContext | undefined; }): string | number | undefined;","entrypoint":"channel-actions","exportName":"resolveReactionMessageId","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":7,"sourcePath":"src/channels/plugins/actions/reaction-message-id.ts"}
|
||||
@@ -113,32 +113,32 @@
|
||||
{"declaration":"export const MarkdownConfigSchema: z.ZodOptional<z.ZodObject<{ tables: z.ZodOptional<z.ZodEnum<{ off: \"off\"; bullets: \"bullets\"; code: \"code\"; }>>; }, z.core.$strict>>;","entrypoint":"channel-config-schema","exportName":"MarkdownConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":371,"sourcePath":"src/config/zod-schema.core.ts"}
|
||||
{"declaration":"export const ToolPolicySchema: z.ZodOptional<z.ZodObject<{ allow: z.ZodOptional<z.ZodArray<z.ZodString>>; alsoAllow: z.ZodOptional<z.ZodArray<z.ZodString>>; deny: z.ZodOptional<z.ZodArray<z.ZodString>>; }, z.core.$strict>>;","entrypoint":"channel-config-schema","exportName":"ToolPolicySchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":253,"sourcePath":"src/config/zod-schema.agent-runtime.ts"}
|
||||
{"category":"channel","entrypoint":"channel-contract","importSpecifier":"openclaw/plugin-sdk/channel-contract","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/channel-contract.ts"}
|
||||
{"declaration":"export type BaseProbeResult = BaseProbeResult<TError>;","entrypoint":"channel-contract","exportName":"BaseProbeResult","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":547,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type BaseTokenResolution = BaseTokenResolution;","entrypoint":"channel-contract","exportName":"BaseTokenResolution","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":553,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"channel-contract","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":139,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"channel-contract","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":17,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelGroupContext = ChannelGroupContext;","entrypoint":"channel-contract","exportName":"ChannelGroupContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":210,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"channel-contract","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":506,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-contract","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":473,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionDiscoveryContext = ChannelMessageActionDiscoveryContext;","entrypoint":"channel-contract","exportName":"ChannelMessageActionDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":29,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type BaseProbeResult = BaseProbeResult<TError>;","entrypoint":"channel-contract","exportName":"BaseProbeResult","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":558,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type BaseTokenResolution = BaseTokenResolution;","entrypoint":"channel-contract","exportName":"BaseTokenResolution","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":564,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"channel-contract","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"channel-contract","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":18,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelGroupContext = ChannelGroupContext;","entrypoint":"channel-contract","exportName":"ChannelGroupContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":216,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"channel-contract","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":516,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-contract","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":482,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionDiscoveryContext = ChannelMessageActionDiscoveryContext;","entrypoint":"channel-contract","exportName":"ChannelMessageActionDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":31,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionName = \"send\" | \"broadcast\" | \"poll\" | \"poll-vote\" | \"react\" | \"reactions\" | \"read\" | \"edit\" | \"unsend\" | \"reply\" | \"sendWithEffect\" | \"renameGroup\" | \"setGroupIcon\" | \"addParticipant\" | \"removeParticipant\" | \"leaveGroup\" | \"sendAttachment\" | \"delete\" | \"pin\" | \"unpin\" | \"list-pins\" | \"permissions\" | \"thread-create\" | \"thread-list\" | \"thread-reply\" | \"search\" | \"sticker\" | \"sticker-search\" | \"member-info\" | \"role-info\" | \"emoji-list\" | \"emoji-upload\" | \"sticker-upload\" | \"role-add\" | \"role-remove\" | \"channel-info\" | \"channel-list\" | \"channel-create\" | \"channel-edit\" | \"channel-delete\" | \"channel-move\" | \"category-create\" | \"category-edit\" | \"category-delete\" | \"topic-create\" | \"topic-edit\" | \"voice-status\" | \"event-list\" | \"event-create\" | \"timeout\" | \"kick\" | \"ban\" | \"set-profile\" | \"set-presence\" | \"download-file\";","entrypoint":"channel-contract","exportName":"ChannelMessageActionName","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/channels/plugins/types.ts"}
|
||||
{"declaration":"export type ChannelMessageToolDiscovery = ChannelMessageToolDiscovery;","entrypoint":"channel-contract","exportName":"ChannelMessageToolDiscovery","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageToolSchemaContribution = ChannelMessageToolSchemaContribution;","entrypoint":"channel-contract","exportName":"ChannelMessageToolSchemaContribution","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":49,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"channel-contract","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":97,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelThreadingContext = ChannelThreadingContext;","entrypoint":"channel-contract","exportName":"ChannelThreadingContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":358,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelThreadingToolContext = ChannelThreadingToolContext;","entrypoint":"channel-contract","exportName":"ChannelThreadingToolContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":372,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageToolDiscovery = ChannelMessageToolDiscovery;","entrypoint":"channel-contract","exportName":"ChannelMessageToolDiscovery","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":56,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageToolSchemaContribution = ChannelMessageToolSchemaContribution;","entrypoint":"channel-contract","exportName":"ChannelMessageToolSchemaContribution","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":51,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"channel-contract","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":100,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelThreadingContext = ChannelThreadingContext;","entrypoint":"channel-contract","exportName":"ChannelThreadingContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":365,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelThreadingToolContext = ChannelThreadingToolContext;","entrypoint":"channel-contract","exportName":"ChannelThreadingToolContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":379,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"category":"channel","entrypoint":"channel-pairing","importSpecifier":"openclaw/plugin-sdk/channel-pairing","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
|
||||
{"declaration":"export function createChannelPairingChallengeIssuer(params: { channel: ChannelId; upsertPairingRequest: (params: { id: string; meta?: PairingMeta | undefined; }) => Promise<{ code: string; created: boolean; }>; }): (challenge: Omit<...>) => Promise<...>;","entrypoint":"channel-pairing","exportName":"createChannelPairingChallengeIssuer","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":19,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
|
||||
{"declaration":"export function createChannelPairingController(params: { core: PluginRuntime; channel: ChannelId; accountId: string; }): ChannelPairingController;","entrypoint":"channel-pairing","exportName":"createChannelPairingController","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":36,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
|
||||
{"declaration":"export function createChannelPairingChallengeIssuer(params: { channel: ChannelId; upsertPairingRequest: (params: { id: string; meta?: PairingMeta | undefined; }) => Promise<{ code: string; created: boolean; }>; }): (challenge: Omit<...>) => Promise<...>;","entrypoint":"channel-pairing","exportName":"createChannelPairingChallengeIssuer","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":21,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
|
||||
{"declaration":"export function createChannelPairingController(params: { core: PluginRuntime; channel: ChannelId; accountId: string; }): ChannelPairingController;","entrypoint":"channel-pairing","exportName":"createChannelPairingController","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":39,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
|
||||
{"declaration":"export function createLoggedPairingApprovalNotifier(format: string | ((params: { cfg: OpenClawConfig; id: string; accountId?: string | undefined; runtime?: RuntimeEnv | undefined; }) => string), log?: (message: string) => void): (params: { ...; }) => Promise<...>;","entrypoint":"channel-pairing","exportName":"createLoggedPairingApprovalNotifier","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":12,"sourcePath":"src/channels/plugins/pairing-adapters.ts"}
|
||||
{"declaration":"export function createPairingPrefixStripper(prefixRe: RegExp, map?: (entry: string) => string): (entry: string) => string;","entrypoint":"channel-pairing","exportName":"createPairingPrefixStripper","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":5,"sourcePath":"src/channels/plugins/pairing-adapters.ts"}
|
||||
{"declaration":"export function createTextPairingAdapter(params: { idLabel: string; message: string; normalizeAllowEntry?: ((entry: string) => string) | undefined; notify: (params: { cfg: OpenClawConfig; id: string; accountId?: string | undefined; runtime?: RuntimeEnv | undefined; } & { ...; }) => void | Promise<...>; }): ChannelPairingAdapter;","entrypoint":"channel-pairing","exportName":"createTextPairingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":21,"sourcePath":"src/channels/plugins/pairing-adapters.ts"}
|
||||
{"declaration":"export type ChannelPairingController = ChannelPairingController;","entrypoint":"channel-pairing","exportName":"ChannelPairingController","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
|
||||
{"declaration":"export type ChannelPairingController = ChannelPairingController;","entrypoint":"channel-pairing","exportName":"ChannelPairingController","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"type","recordType":"export","sourceLine":14,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
|
||||
{"category":"channel","entrypoint":"channel-reply-pipeline","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/channel-reply-pipeline.ts"}
|
||||
{"declaration":"export function createChannelReplyPipeline(params: { cfg: OpenClawConfig; agentId: string; channel?: string | undefined; accountId?: string | undefined; typing?: CreateTypingCallbacksParams | undefined; typingCallbacks?: TypingCallbacks | undefined; }): ChannelReplyPipeline;","entrypoint":"channel-reply-pipeline","exportName":"createChannelReplyPipeline","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"function","recordType":"export","sourceLine":20,"sourcePath":"src/plugin-sdk/channel-reply-pipeline.ts"}
|
||||
{"declaration":"export type ChannelReplyPipeline = ChannelReplyPipeline;","entrypoint":"channel-reply-pipeline","exportName":"ChannelReplyPipeline","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":16,"sourcePath":"src/plugin-sdk/channel-reply-pipeline.ts"}
|
||||
{"declaration":"export type CreateTypingCallbacksParams = CreateTypingCallbacksParams;","entrypoint":"channel-reply-pipeline","exportName":"CreateTypingCallbacksParams","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":11,"sourcePath":"src/channels/typing.ts"}
|
||||
{"declaration":"export type ReplyPrefixContext = import(\"/Users/vincentkoc/GIT/_Perso/openclaw/.worktrees/pr-51877/src/auto-reply/reply/response-prefix-template\").ResponsePrefixContext;","entrypoint":"channel-reply-pipeline","exportName":"ReplyPrefixContext","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/plugin-sdk/channel-reply-pipeline.ts"}
|
||||
{"declaration":"export type ReplyPrefixContext = import(\"src/auto-reply/reply/response-prefix-template\").ResponsePrefixContext;","entrypoint":"channel-reply-pipeline","exportName":"ReplyPrefixContext","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/plugin-sdk/channel-reply-pipeline.ts"}
|
||||
{"declaration":"export type ReplyPrefixContextBundle = ReplyPrefixContextBundle;","entrypoint":"channel-reply-pipeline","exportName":"ReplyPrefixContextBundle","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/channels/reply-prefix.ts"}
|
||||
{"declaration":"export type ReplyPrefixOptions = ReplyPrefixOptions;","entrypoint":"channel-reply-pipeline","exportName":"ReplyPrefixOptions","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":20,"sourcePath":"src/channels/reply-prefix.ts"}
|
||||
{"declaration":"export type TypingCallbacks = TypingCallbacks;","entrypoint":"channel-reply-pipeline","exportName":"TypingCallbacks","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/channels/typing.ts"}
|
||||
@@ -147,8 +147,8 @@
|
||||
{"declaration":"export function createReplyPrefixContext(params: { cfg: OpenClawConfig; agentId: string; channel?: string | undefined; accountId?: string | undefined; }): ReplyPrefixContextBundle;","entrypoint":"channel-runtime","exportName":"createReplyPrefixContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":28,"sourcePath":"src/channels/reply-prefix.ts"}
|
||||
{"declaration":"export function createReplyPrefixOptions(params: { cfg: OpenClawConfig; agentId: string; channel?: string | undefined; accountId?: string | undefined; }): ReplyPrefixOptions;","entrypoint":"channel-runtime","exportName":"createReplyPrefixOptions","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":64,"sourcePath":"src/channels/reply-prefix.ts"}
|
||||
{"declaration":"export function createTypingCallbacks(params: CreateTypingCallbacksParams): TypingCallbacks;","entrypoint":"channel-runtime","exportName":"createTypingCallbacks","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":23,"sourcePath":"src/channels/typing.ts"}
|
||||
{"declaration":"export function isWhatsAppGroupJid(value: string): boolean;","entrypoint":"channel-runtime","exportName":"isWhatsAppGroupJid","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":17,"sourcePath":"src/whatsapp/normalize.ts"}
|
||||
{"declaration":"export function isWhatsAppUserTarget(value: string): boolean;","entrypoint":"channel-runtime","exportName":"isWhatsAppUserTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":33,"sourcePath":"src/whatsapp/normalize.ts"}
|
||||
{"declaration":"export function isWhatsAppGroupJid(value: string): boolean;","entrypoint":"channel-runtime","exportName":"isWhatsAppGroupJid","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":17,"sourcePath":"extensions/whatsapp/src/normalize-target.ts"}
|
||||
{"declaration":"export function isWhatsAppUserTarget(value: string): boolean;","entrypoint":"channel-runtime","exportName":"isWhatsAppUserTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":30,"sourcePath":"extensions/whatsapp/src/normalize-target.ts"}
|
||||
{"declaration":"export function keepHttpServerTaskAlive(params: { server: CloseAwareServer; abortSignal?: AbortSignal | undefined; onAbort?: (() => void | Promise<void>) | undefined; }): Promise<void>;","entrypoint":"channel-runtime","exportName":"keepHttpServerTaskAlive","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":79,"sourcePath":"src/plugin-sdk/channel-lifecycle.ts"}
|
||||
{"declaration":"export function looksLikeSignalTargetId(raw: string, normalized?: string | undefined): boolean;","entrypoint":"channel-runtime","exportName":"looksLikeSignalTargetId","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":38,"sourcePath":"src/channels/plugins/normalize/signal.ts"}
|
||||
{"declaration":"export function looksLikeWhatsAppTargetId(raw: string): boolean;","entrypoint":"channel-runtime","exportName":"looksLikeWhatsAppTargetId","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":20,"sourcePath":"src/channels/plugins/normalize/whatsapp.ts"}
|
||||
@@ -158,23 +158,23 @@
|
||||
{"declaration":"export function normalizeSignalMessagingTarget(raw: string): string | undefined;","entrypoint":"channel-runtime","exportName":"normalizeSignalMessagingTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":1,"sourcePath":"src/channels/plugins/normalize/signal.ts"}
|
||||
{"declaration":"export function normalizeWhatsAppAllowFromEntries(allowFrom: (string | number)[]): string[];","entrypoint":"channel-runtime","exportName":"normalizeWhatsAppAllowFromEntries","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":12,"sourcePath":"src/channels/plugins/normalize/whatsapp.ts"}
|
||||
{"declaration":"export function normalizeWhatsAppMessagingTarget(raw: string): string | undefined;","entrypoint":"channel-runtime","exportName":"normalizeWhatsAppMessagingTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":4,"sourcePath":"src/channels/plugins/normalize/whatsapp.ts"}
|
||||
{"declaration":"export function normalizeWhatsAppTarget(value: string): string | null;","entrypoint":"channel-runtime","exportName":"normalizeWhatsAppTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":55,"sourcePath":"src/whatsapp/normalize.ts"}
|
||||
{"declaration":"export function normalizeWhatsAppTarget(value: string): string | null;","entrypoint":"channel-runtime","exportName":"normalizeWhatsAppTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":47,"sourcePath":"extensions/whatsapp/src/normalize-target.ts"}
|
||||
{"declaration":"export function reduceInteractiveReply<TState>(interactive: InteractiveReply | undefined, initialState: TState, reduce: (state: TState, block: InteractiveReplyBlock, index: number) => TState): TState;","entrypoint":"channel-runtime","exportName":"reduceInteractiveReply","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":3,"sourcePath":"src/channels/plugins/outbound/interactive.ts"}
|
||||
{"declaration":"export function resolvePollMaxSelections(optionCount: number, allowMultiselect: boolean | undefined): number;","entrypoint":"channel-runtime","exportName":"resolvePollMaxSelections","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":29,"sourcePath":"src/polls.ts"}
|
||||
{"declaration":"export function resolveWhatsAppHeartbeatRecipients(cfg: OpenClawConfig, opts?: HeartbeatRecipientsOpts): HeartbeatRecipientsResult;","entrypoint":"channel-runtime","exportName":"resolveWhatsAppHeartbeatRecipients","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":48,"sourcePath":"src/channels/plugins/whatsapp-heartbeat.ts"}
|
||||
{"declaration":"export function waitUntilAbort(signal?: AbortSignal | undefined, onAbort?: (() => void | Promise<void>) | undefined): Promise<void>;","entrypoint":"channel-runtime","exportName":"waitUntilAbort","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":38,"sourcePath":"src/plugin-sdk/channel-lifecycle.ts"}
|
||||
{"declaration":"export const CHANNEL_MESSAGE_ACTION_NAMES: readonly [\"send\", \"broadcast\", \"poll\", \"poll-vote\", \"react\", \"reactions\", \"read\", \"edit\", \"unsend\", \"reply\", \"sendWithEffect\", \"renameGroup\", \"setGroupIcon\", \"addParticipant\", \"removeParticipant\", \"leaveGroup\", \"sendAttachment\", \"delete\", \"pin\", \"unpin\", \"list-pins\", \"permissions\", \"thread-create\", \"thread-list\", \"thread-reply\", \"search\", \"sticker\", \"sticker-search\", \"member-info\", \"role-info\", \"emoji-list\", \"emoji-upload\", \"sticker-upload\", \"role-add\", \"role-remove\", \"channel-info\", \"channel-list\", \"channel-create\", \"channel-edit\", \"channel-delete\", \"channel-move\", \"category-create\", \"category-edit\", \"category-delete\", \"topic-create\", \"topic-edit\", \"voice-status\", \"event-list\", \"event-create\", \"timeout\", \"kick\", \"ban\", \"set-profile\", \"set-presence\", \"set-profile\", \"download-file\"];","entrypoint":"channel-runtime","exportName":"CHANNEL_MESSAGE_ACTION_NAMES","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"const","recordType":"export","sourceLine":1,"sourcePath":"src/channels/plugins/message-action-names.ts"}
|
||||
{"declaration":"export const CHANNEL_MESSAGE_CAPABILITIES: readonly [\"interactive\", \"buttons\", \"cards\", \"components\", \"blocks\"];","entrypoint":"channel-runtime","exportName":"CHANNEL_MESSAGE_CAPABILITIES","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"const","recordType":"export","sourceLine":1,"sourcePath":"src/channels/plugins/message-capabilities.ts"}
|
||||
{"declaration":"export type BaseProbeResult = BaseProbeResult<TError>;","entrypoint":"channel-runtime","exportName":"BaseProbeResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":547,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type BaseTokenResolution = BaseTokenResolution;","entrypoint":"channel-runtime","exportName":"BaseTokenResolution","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":553,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"channel-runtime","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":139,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAccountState = ChannelAccountState;","entrypoint":"channel-runtime","exportName":"ChannelAccountState","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":105,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAgentPromptAdapter = ChannelAgentPromptAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAgentPromptAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":455,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"channel-runtime","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":17,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAgentToolFactory = ChannelAgentToolFactory;","entrypoint":"channel-runtime","exportName":"ChannelAgentToolFactory","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":21,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type BaseProbeResult = BaseProbeResult<TError>;","entrypoint":"channel-runtime","exportName":"BaseProbeResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":558,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type BaseTokenResolution = BaseTokenResolution;","entrypoint":"channel-runtime","exportName":"BaseTokenResolution","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":564,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"channel-runtime","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAccountState = ChannelAccountState;","entrypoint":"channel-runtime","exportName":"ChannelAccountState","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":108,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAgentPromptAdapter = ChannelAgentPromptAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAgentPromptAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":463,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"channel-runtime","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":18,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAgentToolFactory = ChannelAgentToolFactory;","entrypoint":"channel-runtime","exportName":"ChannelAgentToolFactory","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":23,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAllowlistAdapter = ChannelAllowlistAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAllowlistAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":497,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelAuthAdapter = ChannelAuthAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAuthAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":362,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelCapabilities = ChannelCapabilities;","entrypoint":"channel-runtime","exportName":"ChannelCapabilities","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":223,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelCapabilities = ChannelCapabilities;","entrypoint":"channel-runtime","exportName":"ChannelCapabilities","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":230,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelCapabilitiesDiagnostics = ChannelCapabilitiesDiagnostics;","entrypoint":"channel-runtime","exportName":"ChannelCapabilitiesDiagnostics","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":47,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelCapabilitiesDisplayLine = ChannelCapabilitiesDisplayLine;","entrypoint":"channel-runtime","exportName":"ChannelCapabilitiesDisplayLine","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":42,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelCapabilitiesDisplayTone = ChannelCapabilitiesDisplayTone;","entrypoint":"channel-runtime","exportName":"ChannelCapabilitiesDisplayTone","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":40,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
@@ -184,8 +184,8 @@
|
||||
{"declaration":"export type ChannelConfiguredBindingMatch = ChannelConfiguredBindingMatch;","entrypoint":"channel-runtime","exportName":"ChannelConfiguredBindingMatch","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":558,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelConfiguredBindingProvider = ChannelConfiguredBindingProvider;","entrypoint":"channel-runtime","exportName":"ChannelConfiguredBindingProvider","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":562,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelDirectoryAdapter = ChannelDirectoryAdapter;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":406,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelDirectoryEntry = ChannelDirectoryEntry;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryEntry","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":461,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelDirectoryEntryKind = ChannelDirectoryEntryKind;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryEntryKind","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":459,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelDirectoryEntry = ChannelDirectoryEntry;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryEntry","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":469,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelDirectoryEntryKind = ChannelDirectoryEntryKind;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryEntryKind","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":467,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelElevatedAdapter = ChannelElevatedAdapter;","entrypoint":"channel-runtime","exportName":"ChannelElevatedAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":437,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelExecApprovalAdapter = ChannelExecApprovalAdapter;","entrypoint":"channel-runtime","exportName":"ChannelExecApprovalAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":463,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelExecApprovalForwardTarget = ChannelExecApprovalForwardTarget;","entrypoint":"channel-runtime","exportName":"ChannelExecApprovalForwardTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
@@ -193,49 +193,49 @@
|
||||
{"declaration":"export type ChannelGatewayAdapter = ChannelGatewayAdapter<ResolvedAccount>;","entrypoint":"channel-runtime","exportName":"ChannelGatewayAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":346,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelGatewayContext = ChannelGatewayContext<ResolvedAccount>;","entrypoint":"channel-runtime","exportName":"ChannelGatewayContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":238,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelGroupAdapter = ChannelGroupAdapter;","entrypoint":"channel-runtime","exportName":"ChannelGroupAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":122,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelGroupContext = ChannelGroupContext;","entrypoint":"channel-runtime","exportName":"ChannelGroupContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":210,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelGroupContext = ChannelGroupContext;","entrypoint":"channel-runtime","exportName":"ChannelGroupContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":216,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelHeartbeatAdapter = ChannelHeartbeatAdapter;","entrypoint":"channel-runtime","exportName":"ChannelHeartbeatAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":372,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelHeartbeatDeps = ChannelHeartbeatDeps;","entrypoint":"channel-runtime","exportName":"ChannelHeartbeatDeps","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":113,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelHeartbeatDeps = ChannelHeartbeatDeps;","entrypoint":"channel-runtime","exportName":"ChannelHeartbeatDeps","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":116,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelId = ChannelId;","entrypoint":"channel-runtime","exportName":"ChannelId","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelLifecycleAdapter = ChannelLifecycleAdapter;","entrypoint":"channel-runtime","exportName":"ChannelLifecycleAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":449,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelLoginWithQrStartResult = ChannelLoginWithQrStartResult;","entrypoint":"channel-runtime","exportName":"ChannelLoginWithQrStartResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":317,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelLoginWithQrWaitResult = ChannelLoginWithQrWaitResult;","entrypoint":"channel-runtime","exportName":"ChannelLoginWithQrWaitResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":322,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelLogoutContext = ChannelLogoutContext<ResolvedAccount>;","entrypoint":"channel-runtime","exportName":"ChannelLogoutContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":327,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelLogoutResult = ChannelLogoutResult;","entrypoint":"channel-runtime","exportName":"ChannelLogoutResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":311,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelLogSink = ChannelLogSink;","entrypoint":"channel-runtime","exportName":"ChannelLogSink","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":203,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMentionAdapter = ChannelMentionAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMentionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":253,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":506,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":473,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionDiscoveryContext = ChannelMessageActionDiscoveryContext;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":29,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelLogSink = ChannelLogSink;","entrypoint":"channel-runtime","exportName":"ChannelLogSink","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":209,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMentionAdapter = ChannelMentionAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMentionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":260,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":516,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":482,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionDiscoveryContext = ChannelMessageActionDiscoveryContext;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":31,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageActionName = \"send\" | \"broadcast\" | \"poll\" | \"poll-vote\" | \"react\" | \"reactions\" | \"read\" | \"edit\" | \"unsend\" | \"reply\" | \"sendWithEffect\" | \"renameGroup\" | \"setGroupIcon\" | \"addParticipant\" | \"removeParticipant\" | \"leaveGroup\" | \"sendAttachment\" | \"delete\" | \"pin\" | \"unpin\" | \"list-pins\" | \"permissions\" | \"thread-create\" | \"thread-list\" | \"thread-reply\" | \"search\" | \"sticker\" | \"sticker-search\" | \"member-info\" | \"role-info\" | \"emoji-list\" | \"emoji-upload\" | \"sticker-upload\" | \"role-add\" | \"role-remove\" | \"channel-info\" | \"channel-list\" | \"channel-create\" | \"channel-edit\" | \"channel-delete\" | \"channel-move\" | \"category-create\" | \"category-edit\" | \"category-delete\" | \"topic-create\" | \"topic-edit\" | \"voice-status\" | \"event-list\" | \"event-create\" | \"timeout\" | \"kick\" | \"ban\" | \"set-profile\" | \"set-presence\" | \"download-file\";","entrypoint":"channel-runtime","exportName":"ChannelMessageActionName","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/channels/plugins/types.ts"}
|
||||
{"declaration":"export type ChannelMessageCapability = \"interactive\" | \"buttons\" | \"cards\" | \"components\" | \"blocks\";","entrypoint":"channel-runtime","exportName":"ChannelMessageCapability","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/channels/plugins/message-capabilities.ts"}
|
||||
{"declaration":"export type ChannelMessageToolDiscovery = ChannelMessageToolDiscovery;","entrypoint":"channel-runtime","exportName":"ChannelMessageToolDiscovery","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageToolSchemaContribution = ChannelMessageToolSchemaContribution;","entrypoint":"channel-runtime","exportName":"ChannelMessageToolSchemaContribution","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":49,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessagingAdapter = ChannelMessagingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMessagingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":387,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMeta = ChannelMeta;","entrypoint":"channel-runtime","exportName":"ChannelMeta","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":118,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageToolDiscovery = ChannelMessageToolDiscovery;","entrypoint":"channel-runtime","exportName":"ChannelMessageToolDiscovery","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":56,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessageToolSchemaContribution = ChannelMessageToolSchemaContribution;","entrypoint":"channel-runtime","exportName":"ChannelMessageToolSchemaContribution","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":51,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessagingAdapter = ChannelMessagingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMessagingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":395,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMeta = ChannelMeta;","entrypoint":"channel-runtime","exportName":"ChannelMeta","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":122,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelOutboundAdapter = ChannelOutboundAdapter;","entrypoint":"channel-runtime","exportName":"ChannelOutboundAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":154,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelOutboundContext = ChannelOutboundContext;","entrypoint":"channel-runtime","exportName":"ChannelOutboundContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":128,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelOutboundTargetMode = ChannelOutboundTargetMode;","entrypoint":"channel-runtime","exportName":"ChannelOutboundTargetMode","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":15,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelPairingAdapter = ChannelPairingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelPairingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":335,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelPlugin = ChannelPlugin<ResolvedAccount, Probe, Audit>;","entrypoint":"channel-runtime","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/channels/plugins/types.plugin.ts"}
|
||||
{"declaration":"export type ChannelPollContext = ChannelPollContext;","entrypoint":"channel-runtime","exportName":"ChannelPollContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":536,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelPollResult = ChannelPollResult;","entrypoint":"channel-runtime","exportName":"ChannelPollResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":528,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelPlugin = ChannelPlugin<ResolvedAccount, Probe, Audit>;","entrypoint":"channel-runtime","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":55,"sourcePath":"src/channels/plugins/types.plugin.ts"}
|
||||
{"declaration":"export type ChannelPollContext = ChannelPollContext;","entrypoint":"channel-runtime","exportName":"ChannelPollContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":547,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelPollResult = ChannelPollResult;","entrypoint":"channel-runtime","exportName":"ChannelPollResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":538,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelResolveKind = ChannelResolveKind;","entrypoint":"channel-runtime","exportName":"ChannelResolveKind","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":417,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelResolverAdapter = ChannelResolverAdapter;","entrypoint":"channel-runtime","exportName":"ChannelResolverAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":427,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelResolveResult = ChannelResolveResult;","entrypoint":"channel-runtime","exportName":"ChannelResolveResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":419,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelSecurityAdapter = ChannelSecurityAdapter<ResolvedAccount>;","entrypoint":"channel-runtime","exportName":"ChannelSecurityAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":575,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelSecurityContext = ChannelSecurityContext<ResolvedAccount>;","entrypoint":"channel-runtime","exportName":"ChannelSecurityContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":247,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelSecurityDmPolicy = ChannelSecurityDmPolicy;","entrypoint":"channel-runtime","exportName":"ChannelSecurityDmPolicy","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":238,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelSecurityContext = ChannelSecurityContext<ResolvedAccount>;","entrypoint":"channel-runtime","exportName":"ChannelSecurityContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":254,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelSecurityDmPolicy = ChannelSecurityDmPolicy;","entrypoint":"channel-runtime","exportName":"ChannelSecurityDmPolicy","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":245,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelSetupAdapter = ChannelSetupAdapter;","entrypoint":"channel-runtime","exportName":"ChannelSetupAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":56,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"channel-runtime","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":60,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"channel-runtime","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":63,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelStatusAdapter = ChannelStatusAdapter<ResolvedAccount, Probe, Audit>;","entrypoint":"channel-runtime","exportName":"ChannelStatusAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":184,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"channel-runtime","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":97,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelStreamingAdapter = ChannelStreamingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelStreamingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":272,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelStructuredComponents = ChannelStructuredComponents;","entrypoint":"channel-runtime","exportName":"ChannelStructuredComponents","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":281,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelThreadingAdapter = ChannelThreadingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelThreadingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":315,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelThreadingContext = ChannelThreadingContext;","entrypoint":"channel-runtime","exportName":"ChannelThreadingContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":358,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelThreadingToolContext = ChannelThreadingToolContext;","entrypoint":"channel-runtime","exportName":"ChannelThreadingToolContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":372,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelToolSend = ChannelToolSend;","entrypoint":"channel-runtime","exportName":"ChannelToolSend","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":500,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"channel-runtime","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":100,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelStreamingAdapter = ChannelStreamingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelStreamingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":279,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelStructuredComponents = ChannelStructuredComponents;","entrypoint":"channel-runtime","exportName":"ChannelStructuredComponents","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":288,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelThreadingAdapter = ChannelThreadingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelThreadingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":322,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelThreadingContext = ChannelThreadingContext;","entrypoint":"channel-runtime","exportName":"ChannelThreadingContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":365,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelThreadingToolContext = ChannelThreadingToolContext;","entrypoint":"channel-runtime","exportName":"ChannelThreadingToolContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":379,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelToolSend = ChannelToolSend;","entrypoint":"channel-runtime","exportName":"ChannelToolSend","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":509,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChatType = ChatType;","entrypoint":"channel-runtime","exportName":"ChatType","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/channels/chat-type.ts"}
|
||||
{"declaration":"export type CreateTypingCallbacksParams = CreateTypingCallbacksParams;","entrypoint":"channel-runtime","exportName":"CreateTypingCallbacksParams","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":11,"sourcePath":"src/channels/typing.ts"}
|
||||
{"declaration":"export type NormalizedPollInput = NormalizedPollInput;","entrypoint":"channel-runtime","exportName":"NormalizedPollInput","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":17,"sourcePath":"src/polls.ts"}
|
||||
@@ -245,26 +245,27 @@
|
||||
{"declaration":"export type TypingCallbacks = TypingCallbacks;","entrypoint":"channel-runtime","exportName":"TypingCallbacks","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/channels/typing.ts"}
|
||||
{"category":"channel","entrypoint":"channel-setup","importSpecifier":"openclaw/plugin-sdk/channel-setup","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/channel-setup.ts"}
|
||||
{"declaration":"export function createOptionalChannelSetupAdapter(params: OptionalChannelSetupParams): ChannelSetupAdapter;","entrypoint":"channel-setup","exportName":"createOptionalChannelSetupAdapter","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":22,"sourcePath":"src/plugin-sdk/optional-channel-setup.ts"}
|
||||
{"declaration":"export function createOptionalChannelSetupSurface(params: OptionalChannelSetupParams): OptionalChannelSetupSurface;","entrypoint":"channel-setup","exportName":"createOptionalChannelSetupSurface","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":37,"sourcePath":"src/plugin-sdk/channel-setup.ts"}
|
||||
{"declaration":"export function createOptionalChannelSetupSurface(params: OptionalChannelSetupParams): OptionalChannelSetupSurface;","entrypoint":"channel-setup","exportName":"createOptionalChannelSetupSurface","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":40,"sourcePath":"src/plugin-sdk/channel-setup.ts"}
|
||||
{"declaration":"export function createOptionalChannelSetupWizard(params: OptionalChannelSetupParams): ChannelSetupWizard;","entrypoint":"channel-setup","exportName":"createOptionalChannelSetupWizard","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":35,"sourcePath":"src/plugin-sdk/optional-channel-setup.ts"}
|
||||
{"declaration":"export function createTopLevelChannelDmPolicy(params: { label: string; channel: string; policyKey: string; allowFromKey: string; getCurrent: (cfg: OpenClawConfig) => DmPolicy; promptAllowFrom?: ((params: { cfg: OpenClawConfig; prompter: WizardPrompter; accountId?: string | undefined; }) => Promise<...>) | undefined; getAllowFrom?: ((cfg: OpenClawConfig) => (string | number)[] | undefined) | undefined; }): ChannelSetupDmPolicy;","entrypoint":"channel-setup","exportName":"createTopLevelChannelDmPolicy","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":363,"sourcePath":"src/channels/plugins/setup-wizard-helpers.ts"}
|
||||
{"declaration":"export function createTopLevelChannelDmPolicy(params: { label: string; channel: string; policyKey: string; allowFromKey: string; getCurrent: (cfg: OpenClawConfig) => DmPolicy; promptAllowFrom?: ((params: { cfg: OpenClawConfig; prompter: WizardPrompter; accountId?: string | undefined; }) => Promise<...>) | undefined; getAllowFrom?: ((cfg: OpenClawConfig) => (string | number)[] | undefined) | undefined; }): ChannelSetupDmPolicy;","entrypoint":"channel-setup","exportName":"createTopLevelChannelDmPolicy","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":411,"sourcePath":"src/channels/plugins/setup-wizard-helpers.ts"}
|
||||
{"declaration":"export function formatDocsLink(path: string, label?: string | undefined, opts?: { fallback?: string | undefined; force?: boolean | undefined; } | undefined): string;","entrypoint":"channel-setup","exportName":"formatDocsLink","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":5,"sourcePath":"src/terminal/links.ts"}
|
||||
{"declaration":"export function setSetupChannelEnabled(cfg: OpenClawConfig, channel: string, enabled: boolean): OpenClawConfig;","entrypoint":"channel-setup","exportName":"setSetupChannelEnabled","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":765,"sourcePath":"src/channels/plugins/setup-wizard-helpers.ts"}
|
||||
{"declaration":"export function splitSetupEntries(raw: string): string[];","entrypoint":"channel-setup","exportName":"splitSetupEntries","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":76,"sourcePath":"src/channels/plugins/setup-wizard-helpers.ts"}
|
||||
{"declaration":"export function setSetupChannelEnabled(cfg: OpenClawConfig, channel: string, enabled: boolean): OpenClawConfig;","entrypoint":"channel-setup","exportName":"setSetupChannelEnabled","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":813,"sourcePath":"src/channels/plugins/setup-wizard-helpers.ts"}
|
||||
{"declaration":"export function splitSetupEntries(raw: string): string[];","entrypoint":"channel-setup","exportName":"splitSetupEntries","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":80,"sourcePath":"src/channels/plugins/setup-wizard-helpers.ts"}
|
||||
{"declaration":"export const DEFAULT_ACCOUNT_ID: \"default\";","entrypoint":"channel-setup","exportName":"DEFAULT_ACCOUNT_ID","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"const","recordType":"export","sourceLine":3,"sourcePath":"src/routing/account-id.ts"}
|
||||
{"declaration":"export type ChannelSetupAdapter = ChannelSetupAdapter;","entrypoint":"channel-setup","exportName":"ChannelSetupAdapter","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":56,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type ChannelSetupDmPolicy = ChannelSetupDmPolicy;","entrypoint":"channel-setup","exportName":"ChannelSetupDmPolicy","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":93,"sourcePath":"src/channels/plugins/setup-wizard-types.ts"}
|
||||
{"declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"channel-setup","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":60,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"channel-setup","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":63,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelSetupWizard = ChannelSetupWizard;","entrypoint":"channel-setup","exportName":"ChannelSetupWizard","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":247,"sourcePath":"src/channels/plugins/setup-wizard.ts"}
|
||||
{"declaration":"export type OptionalChannelSetupSurface = OptionalChannelSetupSurface;","entrypoint":"channel-setup","exportName":"OptionalChannelSetupSurface","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":27,"sourcePath":"src/plugin-sdk/channel-setup.ts"}
|
||||
{"declaration":"export type OptionalChannelSetupSurface = OptionalChannelSetupSurface;","entrypoint":"channel-setup","exportName":"OptionalChannelSetupSurface","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":29,"sourcePath":"src/plugin-sdk/channel-setup.ts"}
|
||||
{"category":"channel","entrypoint":"command-auth","importSpecifier":"openclaw/plugin-sdk/command-auth","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/command-auth.ts"}
|
||||
{"declaration":"export function buildCommandsMessage(cfg?: OpenClawConfig | undefined, skillCommands?: SkillCommandSpec[] | undefined, options?: CommandsMessageOptions | undefined): string;","entrypoint":"command-auth","exportName":"buildCommandsMessage","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":847,"sourcePath":"src/auto-reply/status.ts"}
|
||||
{"declaration":"export function buildCommandsMessagePaginated(cfg?: OpenClawConfig | undefined, skillCommands?: SkillCommandSpec[] | undefined, options?: CommandsMessageOptions | undefined): CommandsMessageResult;","entrypoint":"command-auth","exportName":"buildCommandsMessagePaginated","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":856,"sourcePath":"src/auto-reply/status.ts"}
|
||||
{"declaration":"export function buildCommandsMessage(cfg?: OpenClawConfig | undefined, skillCommands?: SkillCommandSpec[] | undefined, options?: CommandsMessageOptions | undefined): string;","entrypoint":"command-auth","exportName":"buildCommandsMessage","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":961,"sourcePath":"src/auto-reply/status.ts"}
|
||||
{"declaration":"export function buildCommandsMessagePaginated(cfg?: OpenClawConfig | undefined, skillCommands?: SkillCommandSpec[] | undefined, options?: CommandsMessageOptions | undefined): CommandsMessageResult;","entrypoint":"command-auth","exportName":"buildCommandsMessagePaginated","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":970,"sourcePath":"src/auto-reply/status.ts"}
|
||||
{"declaration":"export function buildCommandsPaginationKeyboard(currentPage: number, totalPages: number, agentId?: string | undefined): { text: string; callback_data: string; }[][];","entrypoint":"command-auth","exportName":"buildCommandsPaginationKeyboard","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":89,"sourcePath":"src/auto-reply/reply/commands-info.ts"}
|
||||
{"declaration":"export function buildCommandText(commandName: string, args?: string | undefined): string;","entrypoint":"command-auth","exportName":"buildCommandText","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":199,"sourcePath":"src/auto-reply/commands-registry.ts"}
|
||||
{"declaration":"export function buildCommandTextFromArgs(command: ChatCommandDefinition, args?: CommandArgs | undefined): string;","entrypoint":"command-auth","exportName":"buildCommandTextFromArgs","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":291,"sourcePath":"src/auto-reply/commands-registry.ts"}
|
||||
{"declaration":"export function buildHelpMessage(cfg?: OpenClawConfig | undefined): string;","entrypoint":"command-auth","exportName":"buildHelpMessage","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":727,"sourcePath":"src/auto-reply/status.ts"}
|
||||
{"declaration":"export function buildHelpMessage(cfg?: OpenClawConfig | undefined): string;","entrypoint":"command-auth","exportName":"buildHelpMessage","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":841,"sourcePath":"src/auto-reply/status.ts"}
|
||||
{"declaration":"export function buildModelsProviderData(cfg: OpenClawConfig, agentId?: string | undefined): Promise<ModelsProviderData>;","entrypoint":"command-auth","exportName":"buildModelsProviderData","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":37,"sourcePath":"src/auto-reply/reply/commands-models.ts"}
|
||||
{"declaration":"export function createPreCryptoDirectDmAuthorizer(params: { resolveAccess: (senderId: string) => Promise<ResolvedInboundDirectDmAccess | Pick<ResolvedInboundDirectDmAccess, \"access\">>; issuePairingChallenge?: ((params: { ...; }) => Promise<...>) | undefined; onBlocked?: ((params: { ...; }) => void) | undefined; }): (input: { ...; }) => Promise<...>;","entrypoint":"command-auth","exportName":"createPreCryptoDirectDmAuthorizer","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":105,"sourcePath":"src/plugin-sdk/direct-dm.ts"}
|
||||
{"declaration":"export function findCommandByNativeName(name: string, provider?: string | undefined): ChatCommandDefinition | undefined;","entrypoint":"command-auth","exportName":"findCommandByNativeName","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":187,"sourcePath":"src/auto-reply/commands-registry.ts"}
|
||||
{"declaration":"export function formatModelsAvailableHeader(params: { provider: string; total: number; cfg: OpenClawConfig; agentDir?: string | undefined; sessionEntry?: SessionEntry | undefined; }): string;","entrypoint":"command-auth","exportName":"formatModelsAvailableHeader","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":204,"sourcePath":"src/auto-reply/reply/commands-models.ts"}
|
||||
{"declaration":"export function getCommandDetection(_cfg?: OpenClawConfig | undefined): CommandDetection;","entrypoint":"command-auth","exportName":"getCommandDetection","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":440,"sourcePath":"src/auto-reply/commands-registry.ts"}
|
||||
@@ -289,12 +290,13 @@
|
||||
{"declaration":"export function resolveCommandAuthorization(params: { ctx: MsgContext; cfg: OpenClawConfig; commandAuthorized: boolean; }): CommandAuthorization;","entrypoint":"command-auth","exportName":"resolveCommandAuthorization","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":303,"sourcePath":"src/auto-reply/command-auth.ts"}
|
||||
{"declaration":"export function resolveCommandAuthorizedFromAuthorizers(params: { useAccessGroups: boolean; authorizers: CommandAuthorizer[]; modeWhenAccessGroupsOff?: CommandGatingModeWhenAccessGroupsOff | undefined; }): boolean;","entrypoint":"command-auth","exportName":"resolveCommandAuthorizedFromAuthorizers","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":8,"sourcePath":"src/channels/command-gating.ts"}
|
||||
{"declaration":"export function resolveControlCommandGate(params: { useAccessGroups: boolean; authorizers: CommandAuthorizer[]; allowTextCommands: boolean; hasControlCommand: boolean; modeWhenAccessGroupsOff?: CommandGatingModeWhenAccessGroupsOff | undefined; }): { ...; };","entrypoint":"command-auth","exportName":"resolveControlCommandGate","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":31,"sourcePath":"src/channels/command-gating.ts"}
|
||||
{"declaration":"export function resolveDirectDmAuthorizationOutcome(params: { isGroup: boolean; dmPolicy: string; senderAllowedForCommands: boolean; }): \"disabled\" | \"unauthorized\" | \"allowed\";","entrypoint":"command-auth","exportName":"resolveDirectDmAuthorizationOutcome","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":114,"sourcePath":"src/plugin-sdk/command-auth.ts"}
|
||||
{"declaration":"export function resolveDirectDmAuthorizationOutcome(params: { isGroup: boolean; dmPolicy: string; senderAllowedForCommands: boolean; }): \"disabled\" | \"unauthorized\" | \"allowed\";","entrypoint":"command-auth","exportName":"resolveDirectDmAuthorizationOutcome","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":120,"sourcePath":"src/plugin-sdk/command-auth.ts"}
|
||||
{"declaration":"export function resolveDualTextControlCommandGate(params: { useAccessGroups: boolean; primaryConfigured: boolean; primaryAllowed: boolean; secondaryConfigured: boolean; secondaryAllowed: boolean; hasControlCommand: boolean; modeWhenAccessGroupsOff?: CommandGatingModeWhenAccessGroupsOff | undefined; }): { ...; };","entrypoint":"command-auth","exportName":"resolveDualTextControlCommandGate","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":47,"sourcePath":"src/channels/command-gating.ts"}
|
||||
{"declaration":"export function resolveInboundDirectDmAccessWithRuntime(params: { cfg: OpenClawConfig; channel: ChannelId; accountId: string; dmPolicy?: string | null | undefined; allowFrom?: (string | number)[] | null | undefined; senderId: string; ... 4 more ...; readStoreAllowFrom?: ((provider: ChannelId, accountId: string) => Promise<...>) | undefined; }): Promise<...>;","entrypoint":"command-auth","exportName":"resolveInboundDirectDmAccessWithRuntime","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":35,"sourcePath":"src/plugin-sdk/direct-dm.ts"}
|
||||
{"declaration":"export function resolveModelsCommandReply(params: { cfg: OpenClawConfig; commandBodyNormalized: string; surface?: string | undefined; currentModel?: string | undefined; agentId?: string | undefined; agentDir?: string | undefined; sessionEntry?: SessionEntry | undefined; }): Promise<...>;","entrypoint":"command-auth","exportName":"resolveModelsCommandReply","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":220,"sourcePath":"src/auto-reply/reply/commands-models.ts"}
|
||||
{"declaration":"export function resolveNativeCommandSessionTargets(params: ResolveNativeCommandSessionTargetsParams): { sessionKey: string; commandTargetSessionKey: string; };","entrypoint":"command-auth","exportName":"resolveNativeCommandSessionTargets","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":10,"sourcePath":"src/channels/native-command-session-targets.ts"}
|
||||
{"declaration":"export function resolveSenderCommandAuthorization(params: ResolveSenderCommandAuthorizationParams): Promise<{ shouldComputeAuth: boolean; effectiveAllowFrom: string[]; effectiveGroupAllowFrom: string[]; senderAllowedForCommands: boolean; commandAuthorized: boolean | undefined; }>;","entrypoint":"command-auth","exportName":"resolveSenderCommandAuthorization","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":143,"sourcePath":"src/plugin-sdk/command-auth.ts"}
|
||||
{"declaration":"export function resolveSenderCommandAuthorizationWithRuntime(params: ResolveSenderCommandAuthorizationWithRuntimeParams): Promise<{ shouldComputeAuth: boolean; effectiveAllowFrom: string[]; effectiveGroupAllowFrom: string[]; senderAllowedForCommands: boolean; commandAuthorized: boolean | undefined; }>;","entrypoint":"command-auth","exportName":"resolveSenderCommandAuthorizationWithRuntime","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":132,"sourcePath":"src/plugin-sdk/command-auth.ts"}
|
||||
{"declaration":"export function resolveSenderCommandAuthorization(params: ResolveSenderCommandAuthorizationParams): Promise<{ shouldComputeAuth: boolean; effectiveAllowFrom: string[]; effectiveGroupAllowFrom: string[]; senderAllowedForCommands: boolean; commandAuthorized: boolean | undefined; }>;","entrypoint":"command-auth","exportName":"resolveSenderCommandAuthorization","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":149,"sourcePath":"src/plugin-sdk/command-auth.ts"}
|
||||
{"declaration":"export function resolveSenderCommandAuthorizationWithRuntime(params: ResolveSenderCommandAuthorizationWithRuntimeParams): Promise<{ shouldComputeAuth: boolean; effectiveAllowFrom: string[]; effectiveGroupAllowFrom: string[]; senderAllowedForCommands: boolean; commandAuthorized: boolean | undefined; }>;","entrypoint":"command-auth","exportName":"resolveSenderCommandAuthorizationWithRuntime","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":138,"sourcePath":"src/plugin-sdk/command-auth.ts"}
|
||||
{"declaration":"export function resolveSkillCommandInvocation(params: { commandBodyNormalized: string; skillCommands: SkillCommandSpec[]; }): { command: SkillCommandSpec; args?: string | undefined; } | null;","entrypoint":"command-auth","exportName":"resolveSkillCommandInvocation","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":58,"sourcePath":"src/auto-reply/skill-commands-base.ts"}
|
||||
{"declaration":"export function resolveStoredModelOverride(params: { sessionEntry?: SessionEntry | undefined; sessionStore?: Record<string, SessionEntry> | undefined; sessionKey?: string | undefined; parentSessionKey?: string | undefined; }): StoredModelOverride | null;","entrypoint":"command-auth","exportName":"resolveStoredModelOverride","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":156,"sourcePath":"src/auto-reply/reply/model-selection.ts"}
|
||||
{"declaration":"export function resolveTextCommand(raw: string, cfg?: OpenClawConfig | undefined): { command: ChatCommandDefinition; args?: string | undefined; } | null;","entrypoint":"command-auth","exportName":"resolveTextCommand","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":494,"sourcePath":"src/auto-reply/commands-registry.ts"}
|
||||
@@ -308,45 +310,48 @@
|
||||
{"declaration":"export type CommandArgs = CommandArgs;","entrypoint":"command-auth","exportName":"CommandArgs","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":46,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
|
||||
{"declaration":"export type CommandArgValues = CommandArgValues;","entrypoint":"command-auth","exportName":"CommandArgValues","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":44,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
|
||||
{"declaration":"export type CommandAuthorization = CommandAuthorization;","entrypoint":"command-auth","exportName":"CommandAuthorization","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/auto-reply/command-auth.ts"}
|
||||
{"declaration":"export type CommandAuthorizationRuntime = CommandAuthorizationRuntime;","entrypoint":"command-auth","exportName":"CommandAuthorizationRuntime","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":98,"sourcePath":"src/plugin-sdk/command-auth.ts"}
|
||||
{"declaration":"export type CommandAuthorizationRuntime = CommandAuthorizationRuntime;","entrypoint":"command-auth","exportName":"CommandAuthorizationRuntime","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":104,"sourcePath":"src/plugin-sdk/command-auth.ts"}
|
||||
{"declaration":"export type CommandAuthorizer = CommandAuthorizer;","entrypoint":"command-auth","exportName":"CommandAuthorizer","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/channels/command-gating.ts"}
|
||||
{"declaration":"export type CommandDetection = CommandDetection;","entrypoint":"command-auth","exportName":"CommandDetection","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":78,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
|
||||
{"declaration":"export type CommandGatingModeWhenAccessGroupsOff = CommandGatingModeWhenAccessGroupsOff;","entrypoint":"command-auth","exportName":"CommandGatingModeWhenAccessGroupsOff","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/channels/command-gating.ts"}
|
||||
{"declaration":"export type CommandNormalizeOptions = CommandNormalizeOptions;","entrypoint":"command-auth","exportName":"CommandNormalizeOptions","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":74,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
|
||||
{"declaration":"export type CommandScope = CommandScope;","entrypoint":"command-auth","exportName":"CommandScope","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":3,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
|
||||
{"declaration":"export type DirectDmCommandAuthorizationRuntime = DirectDmCommandAuthorizationRuntime;","entrypoint":"command-auth","exportName":"DirectDmCommandAuthorizationRuntime","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/plugin-sdk/direct-dm.ts"}
|
||||
{"declaration":"export type ModelsProviderData = ModelsProviderData;","entrypoint":"command-auth","exportName":"ModelsProviderData","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":27,"sourcePath":"src/auto-reply/reply/commands-models.ts"}
|
||||
{"declaration":"export type NativeCommandSpec = NativeCommandSpec;","entrypoint":"command-auth","exportName":"NativeCommandSpec","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":67,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
|
||||
{"declaration":"export type ResolvedCommandArgChoice = ResolvedCommandArgChoice;","entrypoint":"command-auth","exportName":"ResolvedCommandArgChoice","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":314,"sourcePath":"src/auto-reply/commands-registry.ts"}
|
||||
{"declaration":"export type ResolvedInboundDirectDmAccess = ResolvedInboundDirectDmAccess;","entrypoint":"command-auth","exportName":"ResolvedInboundDirectDmAccess","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":22,"sourcePath":"src/plugin-sdk/direct-dm.ts"}
|
||||
{"declaration":"export type ResolveNativeCommandSessionTargetsParams = ResolveNativeCommandSessionTargetsParams;","entrypoint":"command-auth","exportName":"ResolveNativeCommandSessionTargetsParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/channels/native-command-session-targets.ts"}
|
||||
{"declaration":"export type ResolveSenderCommandAuthorizationParams = ResolveSenderCommandAuthorizationParams;","entrypoint":"command-auth","exportName":"ResolveSenderCommandAuthorizationParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":81,"sourcePath":"src/plugin-sdk/command-auth.ts"}
|
||||
{"declaration":"export type ResolveSenderCommandAuthorizationWithRuntimeParams = ResolveSenderCommandAuthorizationWithRuntimeParams;","entrypoint":"command-auth","exportName":"ResolveSenderCommandAuthorizationWithRuntimeParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":106,"sourcePath":"src/plugin-sdk/command-auth.ts"}
|
||||
{"declaration":"export type ResolveSenderCommandAuthorizationParams = ResolveSenderCommandAuthorizationParams;","entrypoint":"command-auth","exportName":"ResolveSenderCommandAuthorizationParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":87,"sourcePath":"src/plugin-sdk/command-auth.ts"}
|
||||
{"declaration":"export type ResolveSenderCommandAuthorizationWithRuntimeParams = ResolveSenderCommandAuthorizationWithRuntimeParams;","entrypoint":"command-auth","exportName":"ResolveSenderCommandAuthorizationWithRuntimeParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":112,"sourcePath":"src/plugin-sdk/command-auth.ts"}
|
||||
{"declaration":"export type ShouldHandleTextCommandsParams = ShouldHandleTextCommandsParams;","entrypoint":"command-auth","exportName":"ShouldHandleTextCommandsParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":83,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
|
||||
{"declaration":"export type StoredModelOverride = StoredModelOverride;","entrypoint":"command-auth","exportName":"StoredModelOverride","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":123,"sourcePath":"src/auto-reply/reply/model-selection.ts"}
|
||||
{"category":"core","entrypoint":"core","importSpecifier":"openclaw/plugin-sdk/core","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function applyAccountNameToChannelSection(params: { cfg: OpenClawConfig; channelKey: string; accountId: string; name?: string | undefined; alwaysUseAccounts?: boolean | undefined; }): OpenClawConfig;","entrypoint":"core","exportName":"applyAccountNameToChannelSection","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":33,"sourcePath":"src/channels/plugins/setup-helpers.ts"}
|
||||
{"declaration":"export function buildAgentSessionKey(params: { agentId: string; channel: string; accountId?: string | null | undefined; peer?: RoutePeer | null | undefined; dmScope?: \"main\" | \"per-peer\" | \"per-channel-peer\" | \"per-account-channel-peer\" | undefined; identityLinks?: Record<...> | undefined; }): string;","entrypoint":"core","exportName":"buildAgentSessionKey","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":91,"sourcePath":"src/routing/resolve-route.ts"}
|
||||
{"declaration":"export function buildChannelConfigSchema(schema: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>): ChannelConfigSchema;","entrypoint":"core","exportName":"buildChannelConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":35,"sourcePath":"src/channels/plugins/config-schema.ts"}
|
||||
{"declaration":"export function buildChannelOutboundSessionRoute(params: { cfg: OpenClawConfig; agentId: string; channel: string; accountId?: string | null | undefined; peer: { kind: \"direct\" | \"group\" | \"channel\"; id: string; }; chatType: \"direct\" | \"group\" | \"channel\"; from: string; to: string; threadId?: string | ... 1 more ... | undefined; }): ChannelOutboundSessionRoute;","entrypoint":"core","exportName":"buildChannelOutboundSessionRoute","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":155,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function channelTargetSchema(options?: { description?: string | undefined; } | undefined): TString;","entrypoint":"core","exportName":"channelTargetSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":33,"sourcePath":"src/agents/schema/typebox.ts"}
|
||||
{"declaration":"export function channelTargetsSchema(options?: { description?: string | undefined; } | undefined): TArray<TString>;","entrypoint":"core","exportName":"channelTargetsSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":39,"sourcePath":"src/agents/schema/typebox.ts"}
|
||||
{"declaration":"export function buildChannelOutboundSessionRoute(params: { cfg: OpenClawConfig; agentId: string; channel: string; accountId?: string | null | undefined; peer: { kind: \"direct\" | \"group\" | \"channel\"; id: string; }; chatType: \"direct\" | \"group\" | \"channel\"; from: string; to: string; threadId?: string | ... 1 more ... | undefined; }): ChannelOutboundSessionRoute;","entrypoint":"core","exportName":"buildChannelOutboundSessionRoute","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":162,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function channelTargetSchema(options?: { description?: string | undefined; } | undefined): TString;","entrypoint":"core","exportName":"channelTargetSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":38,"sourcePath":"src/agents/schema/typebox.ts"}
|
||||
{"declaration":"export function channelTargetsSchema(options?: { description?: string | undefined; } | undefined): TArray<TString>;","entrypoint":"core","exportName":"channelTargetsSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":44,"sourcePath":"src/agents/schema/typebox.ts"}
|
||||
{"declaration":"export function clearAccountEntryFields<TAccountEntry extends object>(params: { accounts?: Record<string, TAccountEntry> | undefined; accountId: string; fields: string[]; isValueSet?: ((value: unknown) => boolean) | undefined; markClearedOnFieldPresence?: boolean | undefined; }): { ...; };","entrypoint":"core","exportName":"clearAccountEntryFields","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":122,"sourcePath":"src/channels/plugins/config-helpers.ts"}
|
||||
{"declaration":"export function createChannelPluginBase<TResolvedAccount>(params: CreateChannelPluginBaseOptions<TResolvedAccount>): CreatedChannelPluginBase<TResolvedAccount>;","entrypoint":"core","exportName":"createChannelPluginBase","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":417,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function createChatChannelPlugin<TResolvedAccount extends { accountId?: string | null; }, Probe = unknown, Audit = unknown>(params: { base: ChatChannelPluginBase<TResolvedAccount, Probe, Audit>; security?: ChannelSecurityAdapter<TResolvedAccount> | ChatChannelSecurityOptions<...> | undefined; pairing?: ChannelPairingAdapter | ... 1 more ... | undefined; threading?: ChannelThreadingAdapter | ... 1 more ... | undefined; outbound?: ChannelOutboundAdapter | ... 1 more ... | undefined; }): ChannelPlugin<...>;","entrypoint":"core","exportName":"createChatChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":394,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function defineChannelPluginEntry<TPlugin extends ChannelPlugin>({ id, name, description, plugin, configSchema, setRuntime, registerFull, }: DefineChannelPluginEntryOptions<TPlugin>): DefinedPluginEntry;","entrypoint":"core","exportName":"defineChannelPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":231,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"core","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":79,"sourcePath":"src/plugin-sdk/plugin-entry.ts"}
|
||||
{"declaration":"export function defineSetupPluginEntry<TPlugin>(plugin: TPlugin): { plugin: TPlugin; };","entrypoint":"core","exportName":"defineSetupPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":257,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function createChannelPluginBase<TResolvedAccount>(params: CreateChannelPluginBaseOptions<TResolvedAccount>): CreatedChannelPluginBase<TResolvedAccount>;","entrypoint":"core","exportName":"createChannelPluginBase","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":436,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function createChatChannelPlugin<TResolvedAccount extends { accountId?: string | null; }, Probe = unknown, Audit = unknown>(params: { base: ChatChannelPluginBase<TResolvedAccount, Probe, Audit>; security?: ChannelSecurityAdapter<TResolvedAccount> | ChatChannelSecurityOptions<...> | undefined; pairing?: ChannelPairingAdapter | ... 1 more ... | undefined; threading?: ChannelThreadingAdapter | ... 1 more ... | undefined; outbound?: ChannelOutboundAdapter | ... 1 more ... | undefined; }): ChannelPlugin<...>;","entrypoint":"core","exportName":"createChatChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":413,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function defineChannelPluginEntry<TPlugin>({ id, name, description, plugin, configSchema, setRuntime, registerFull, }: DefineChannelPluginEntryOptions<TPlugin>): DefinedPluginEntry;","entrypoint":"core","exportName":"defineChannelPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":245,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"core","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":88,"sourcePath":"src/plugin-sdk/plugin-entry.ts"}
|
||||
{"declaration":"export function defineSetupPluginEntry<TPlugin>(plugin: TPlugin): { plugin: TPlugin; };","entrypoint":"core","exportName":"defineSetupPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":276,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function delegateCompactionToRuntime(params: { sessionId: string; sessionKey?: string | undefined; sessionFile: string; tokenBudget?: number | undefined; force?: boolean | undefined; currentTokenCount?: number | undefined; compactionTarget?: \"budget\" | ... 1 more ... | undefined; customInstructions?: string | undefined; runtimeContext?: ContextEngineRuntimeContext | undefined; }): Promise<...>;","entrypoint":"core","exportName":"delegateCompactionToRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":16,"sourcePath":"src/context-engine/delegate.ts"}
|
||||
{"declaration":"export function deleteAccountFromConfigSection(params: { cfg: OpenClawConfig; sectionKey: string; accountId: string; clearBaseFields?: string[] | undefined; }): OpenClawConfig;","entrypoint":"core","exportName":"deleteAccountFromConfigSection","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":60,"sourcePath":"src/channels/plugins/config-helpers.ts"}
|
||||
{"declaration":"export function emptyPluginConfigSchema(): OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"emptyPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":13,"sourcePath":"src/plugins/config-schema.ts"}
|
||||
{"declaration":"export function enqueueKeyedTask<T>(params: { tails: Map<string, Promise<void>>; key: string; task: () => Promise<T>; hooks?: KeyedAsyncQueueHooks | undefined; }): Promise<...>;","entrypoint":"core","exportName":"enqueueKeyedTask","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":7,"sourcePath":"src/plugin-sdk/keyed-async-queue.ts"}
|
||||
{"declaration":"export function formatPairingApproveHint(channelId: string): string;","entrypoint":"core","exportName":"formatPairingApproveHint","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":17,"sourcePath":"src/channels/plugins/helpers.ts"}
|
||||
{"declaration":"export function getChatChannelMeta(id: \"telegram\" | \"whatsapp\" | \"discord\" | \"irc\" | \"googlechat\" | \"slack\" | \"signal\" | \"imessage\" | \"line\"): ChannelMeta;","entrypoint":"core","exportName":"getChatChannelMeta","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":142,"sourcePath":"src/channels/registry.ts"}
|
||||
{"declaration":"export function getChatChannelMeta(id: \"telegram\" | \"whatsapp\" | \"discord\" | \"irc\" | \"googlechat\" | \"slack\" | \"signal\" | \"imessage\" | \"line\"): ChannelMeta;","entrypoint":"core","exportName":"getChatChannelMeta","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":158,"sourcePath":"src/channels/registry.ts"}
|
||||
{"declaration":"export function isSecretRef(value: unknown): value is SecretRef;","entrypoint":"core","exportName":"isSecretRef","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":34,"sourcePath":"src/config/types.secrets.ts"}
|
||||
{"declaration":"export function loadSecretFileSync(filePath: string, label: string, options?: SecretFileReadOptions): SecretFileReadResult;","entrypoint":"core","exportName":"loadSecretFileSync","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":29,"sourcePath":"src/infra/secret-file.ts"}
|
||||
{"declaration":"export function migrateBaseNameToDefaultAccount(params: { cfg: OpenClawConfig; channelKey: string; alwaysUseAccounts?: boolean | undefined; }): OpenClawConfig;","entrypoint":"core","exportName":"migrateBaseNameToDefaultAccount","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":92,"sourcePath":"src/channels/plugins/setup-helpers.ts"}
|
||||
{"declaration":"export function normalizeAccountId(value: string | null | undefined): string;","entrypoint":"core","exportName":"normalizeAccountId","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":34,"sourcePath":"src/routing/account-id.ts"}
|
||||
{"declaration":"export function normalizeAtHashSlug(raw?: string | null | undefined): string;","entrypoint":"core","exportName":"normalizeAtHashSlug","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":19,"sourcePath":"src/shared/string-normalization.ts"}
|
||||
{"declaration":"export function normalizeHyphenSlug(raw?: string | null | undefined): string;","entrypoint":"core","exportName":"normalizeHyphenSlug","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":9,"sourcePath":"src/shared/string-normalization.ts"}
|
||||
{"declaration":"export function optionalStringEnum<T extends readonly string[]>(values: T, options?: StringEnumOptions<T>): TOptional<TUnsafe<T[number]>>;","entrypoint":"core","exportName":"optionalStringEnum","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":26,"sourcePath":"src/agents/schema/typebox.ts"}
|
||||
{"declaration":"export function optionalStringEnum<T extends readonly string[]>(values: T, options?: StringEnumOptions<T>): TOptional<TUnsafe<T[number]>>;","entrypoint":"core","exportName":"optionalStringEnum","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":31,"sourcePath":"src/agents/schema/typebox.ts"}
|
||||
{"declaration":"export function parseOptionalDelimitedEntries(value?: string | undefined): string[] | undefined;","entrypoint":"core","exportName":"parseOptionalDelimitedEntries","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":23,"sourcePath":"src/channels/plugins/helpers.ts"}
|
||||
{"declaration":"export function readSecretFileSync(filePath: string, label: string, options?: SecretFileReadOptions): string;","entrypoint":"core","exportName":"readSecretFileSync","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":118,"sourcePath":"src/infra/secret-file.ts"}
|
||||
{"declaration":"export function resolveGatewayBindUrl(params: { bind?: string | undefined; customBindHost?: string | undefined; scheme: \"ws\" | \"wss\"; port: number; pickTailnetHost: () => string | null; pickLanHost: () => string | null; }): GatewayBindUrlResult;","entrypoint":"core","exportName":"resolveGatewayBindUrl","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":11,"sourcePath":"src/shared/gateway-bind-url.ts"}
|
||||
@@ -354,129 +359,140 @@
|
||||
{"declaration":"export function resolveThreadSessionKeys(params: { baseSessionKey: string; threadId?: string | null | undefined; parentSessionKey?: string | undefined; useSuffix?: boolean | undefined; normalizeThreadId?: ((threadId: string) => string) | undefined; }): { ...; };","entrypoint":"core","exportName":"resolveThreadSessionKeys","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":234,"sourcePath":"src/routing/session-key.ts"}
|
||||
{"declaration":"export function setAccountEnabledInConfigSection(params: { cfg: OpenClawConfig; sectionKey: string; accountId: string; enabled: boolean; allowTopLevel?: boolean | undefined; }): OpenClawConfig;","entrypoint":"core","exportName":"setAccountEnabledInConfigSection","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":16,"sourcePath":"src/channels/plugins/config-helpers.ts"}
|
||||
{"declaration":"export function stringEnum<T extends readonly string[]>(values: T, options?: StringEnumOptions<T>): TUnsafe<T[number]>;","entrypoint":"core","exportName":"stringEnum","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":15,"sourcePath":"src/agents/schema/typebox.ts"}
|
||||
{"declaration":"export function stripChannelTargetPrefix(raw: string, ...providers: string[]): string;","entrypoint":"core","exportName":"stripChannelTargetPrefix","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":140,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function stripTargetKindPrefix(raw: string): string;","entrypoint":"core","exportName":"stripTargetKindPrefix","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":151,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function stripChannelTargetPrefix(raw: string, ...providers: string[]): string;","entrypoint":"core","exportName":"stripChannelTargetPrefix","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":142,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function stripTargetKindPrefix(raw: string): string;","entrypoint":"core","exportName":"stripTargetKindPrefix","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":154,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function tryReadSecretFileSync(filePath: string | undefined, label: string, options?: SecretFileReadOptions): string | undefined;","entrypoint":"core","exportName":"tryReadSecretFileSync","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":130,"sourcePath":"src/infra/secret-file.ts"}
|
||||
{"declaration":"export const DEFAULT_ACCOUNT_ID: \"default\";","entrypoint":"core","exportName":"DEFAULT_ACCOUNT_ID","importSpecifier":"openclaw/plugin-sdk/core","kind":"const","recordType":"export","sourceLine":3,"sourcePath":"src/routing/account-id.ts"}
|
||||
{"declaration":"export const DEFAULT_SECRET_FILE_MAX_BYTES: number;","entrypoint":"core","exportName":"DEFAULT_SECRET_FILE_MAX_BYTES","importSpecifier":"openclaw/plugin-sdk/core","kind":"const","recordType":"export","sourceLine":5,"sourcePath":"src/infra/secret-file.ts"}
|
||||
{"declaration":"export type AnyAgentTool = AnyAgentTool;","entrypoint":"core","exportName":"AnyAgentTool","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/agents/tools/common.ts"}
|
||||
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"core","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":473,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessagingAdapter = ChannelMessagingAdapter;","entrypoint":"core","exportName":"ChannelMessagingAdapter","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":387,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelOutboundSessionRoute = ChannelOutboundSessionRoute;","entrypoint":"core","exportName":"ChannelOutboundSessionRoute","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":302,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelOutboundSessionRouteParams = { cfg: OpenClawConfig; agentId: string; accountId?: string | null; target: string; resolvedTarget?: { to: string; kind: import(\"/Users/vincentkoc/GIT/_Perso/openclaw/.worktrees/pr-51877/src/channels/plugins/types.core\").ChannelDirectoryEntryKind | \"channel\"; display?: string; source: \"normalized\" | \"directory\"; }; replyToId?: string | null; threadId?: string | number | null;};","entrypoint":"core","exportName":"ChannelOutboundSessionRouteParams","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":136,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export type ChannelPlugin = ChannelPlugin<ResolvedAccount, Probe, Audit>;","entrypoint":"core","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/channels/plugins/types.plugin.ts"}
|
||||
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"core","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":482,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelMessagingAdapter = ChannelMessagingAdapter;","entrypoint":"core","exportName":"ChannelMessagingAdapter","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":395,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelOutboundSessionRoute = ChannelOutboundSessionRoute;","entrypoint":"core","exportName":"ChannelOutboundSessionRoute","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":309,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelOutboundSessionRouteParams = { cfg: OpenClawConfig; agentId: string; accountId?: string | null; target: string; resolvedTarget?: { to: string; kind: import(\"src/channels/plugins/types.core\").ChannelDirectoryEntryKind | \"channel\"; display?: string; source: \"normalized\" | \"directory\"; }; replyToId?: string | null; threadId?: string | number | null;};","entrypoint":"core","exportName":"ChannelOutboundSessionRouteParams","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":137,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export type ChannelPlugin = ChannelPlugin<ResolvedAccount, Probe, Audit>;","entrypoint":"core","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":55,"sourcePath":"src/channels/plugins/types.plugin.ts"}
|
||||
{"declaration":"export type GatewayBindUrlResult = GatewayBindUrlResult;","entrypoint":"core","exportName":"GatewayBindUrlResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/shared/gateway-bind-url.ts"}
|
||||
{"declaration":"export type GatewayRequestHandlerOptions = GatewayRequestHandlerOptions;","entrypoint":"core","exportName":"GatewayRequestHandlerOptions","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":111,"sourcePath":"src/gateway/server-methods/types.ts"}
|
||||
{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"core","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":935,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type GatewayRequestHandlerOptions = GatewayRequestHandlerOptions;","entrypoint":"core","exportName":"GatewayRequestHandlerOptions","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":112,"sourcePath":"src/gateway/server-methods/types.ts"}
|
||||
{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"core","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":951,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"core","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"}
|
||||
{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1292,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"core","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1050,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":80,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"core","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1275,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"core","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1265,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"core","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1258,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginToolContext = OpenClawPluginToolContext;","entrypoint":"core","exportName":"OpenClawPluginToolContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":94,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginToolFactory = OpenClawPluginToolFactory;","entrypoint":"core","exportName":"OpenClawPluginToolFactory","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":111,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":950,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"core","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1079,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"core","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":58,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"core","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/plugins/runtime/types.ts"}
|
||||
{"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"core","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":560,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"core","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthDoctorHintContext = ProviderAuthDoctorHintContext;","entrypoint":"core","exportName":"ProviderAuthDoctorHintContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":435,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthMethod = ProviderAuthMethod;","entrypoint":"core","exportName":"ProviderAuthMethod","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":222,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthMethodNonInteractiveContext = ProviderAuthMethodNonInteractiveContext;","entrypoint":"core","exportName":"ProviderAuthMethodNonInteractiveContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":206,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"core","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":130,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuildMissingAuthMessageContext = ProviderBuildMissingAuthMessageContext;","entrypoint":"core","exportName":"ProviderBuildMissingAuthMessageContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":488,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuiltInModelSuppressionContext = ProviderBuiltInModelSuppressionContext;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":504,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuiltInModelSuppressionResult = ProviderBuiltInModelSuppressionResult;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":513,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCacheTtlEligibilityContext = ProviderCacheTtlEligibilityContext;","entrypoint":"core","exportName":"ProviderCacheTtlEligibilityContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":476,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCatalogContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":243,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCatalogResult = ProviderCatalogResult;","entrypoint":"core","exportName":"ProviderCatalogResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":266,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderDefaultThinkingPolicyContext = ProviderDefaultThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderDefaultThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":537,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderDiscoveryContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":576,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderFetchUsageSnapshotContext = ProviderFetchUsageSnapshotContext;","entrypoint":"core","exportName":"ProviderFetchUsageSnapshotContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":416,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderModernModelPolicyContext = ProviderModernModelPolicyContext;","entrypoint":"core","exportName":"ProviderModernModelPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":547,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderNormalizeResolvedModelContext = ProviderNormalizeResolvedModelContext;","entrypoint":"core","exportName":"ProviderNormalizeResolvedModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":327,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPreparedRuntimeAuth = ProviderPreparedRuntimeAuth;","entrypoint":"core","exportName":"ProviderPreparedRuntimeAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":363,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderPrepareDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":318,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareExtraParamsContext = ProviderPrepareExtraParamsContext;","entrypoint":"core","exportName":"ProviderPrepareExtraParamsContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":449,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareRuntimeAuthContext = ProviderPrepareRuntimeAuthContext;","entrypoint":"core","exportName":"ProviderPrepareRuntimeAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":342,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolvedUsageAuth = ProviderResolvedUsageAuth;","entrypoint":"core","exportName":"ProviderResolvedUsageAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":403,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolveDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderResolveDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":301,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolveUsageAuthContext = ProviderResolveUsageAuthContext;","entrypoint":"core","exportName":"ProviderResolveUsageAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":384,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"core","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":284,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":525,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1314,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"core","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1068,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":88,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"core","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1296,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"core","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1285,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"core","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1277,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginToolContext = OpenClawPluginToolContext;","entrypoint":"core","exportName":"OpenClawPluginToolContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":103,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginToolFactory = OpenClawPluginToolFactory;","entrypoint":"core","exportName":"OpenClawPluginToolFactory","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":120,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":966,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"core","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1097,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"core","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":59,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"core","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/plugins/runtime/types.ts"}
|
||||
{"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"core","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":571,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"core","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":155,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthDoctorHintContext = ProviderAuthDoctorHintContext;","entrypoint":"core","exportName":"ProviderAuthDoctorHintContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":446,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthMethod = ProviderAuthMethod;","entrypoint":"core","exportName":"ProviderAuthMethod","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":233,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthMethodNonInteractiveContext = ProviderAuthMethodNonInteractiveContext;","entrypoint":"core","exportName":"ProviderAuthMethodNonInteractiveContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":217,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"core","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":140,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuildMissingAuthMessageContext = ProviderBuildMissingAuthMessageContext;","entrypoint":"core","exportName":"ProviderBuildMissingAuthMessageContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":499,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuiltInModelSuppressionContext = ProviderBuiltInModelSuppressionContext;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":515,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuiltInModelSuppressionResult = ProviderBuiltInModelSuppressionResult;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":524,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCacheTtlEligibilityContext = ProviderCacheTtlEligibilityContext;","entrypoint":"core","exportName":"ProviderCacheTtlEligibilityContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":487,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCatalogContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":254,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCatalogResult = ProviderCatalogResult;","entrypoint":"core","exportName":"ProviderCatalogResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":277,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderDefaultThinkingPolicyContext = ProviderDefaultThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderDefaultThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":548,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderDiscoveryContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":587,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderFetchUsageSnapshotContext = ProviderFetchUsageSnapshotContext;","entrypoint":"core","exportName":"ProviderFetchUsageSnapshotContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":427,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderModernModelPolicyContext = ProviderModernModelPolicyContext;","entrypoint":"core","exportName":"ProviderModernModelPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":558,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderNormalizeResolvedModelContext = ProviderNormalizeResolvedModelContext;","entrypoint":"core","exportName":"ProviderNormalizeResolvedModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":338,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPreparedRuntimeAuth = ProviderPreparedRuntimeAuth;","entrypoint":"core","exportName":"ProviderPreparedRuntimeAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":374,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderPrepareDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":329,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareExtraParamsContext = ProviderPrepareExtraParamsContext;","entrypoint":"core","exportName":"ProviderPrepareExtraParamsContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":460,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareRuntimeAuthContext = ProviderPrepareRuntimeAuthContext;","entrypoint":"core","exportName":"ProviderPrepareRuntimeAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":353,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolvedUsageAuth = ProviderResolvedUsageAuth;","entrypoint":"core","exportName":"ProviderResolvedUsageAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":414,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolveDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderResolveDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":312,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolveUsageAuthContext = ProviderResolveUsageAuthContext;","entrypoint":"core","exportName":"ProviderResolveUsageAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":395,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"core","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":295,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":536,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderUsageSnapshot = ProviderUsageSnapshot;","entrypoint":"core","exportName":"ProviderUsageSnapshot","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":7,"sourcePath":"src/infra/provider-usage.types.ts"}
|
||||
{"declaration":"export type ProviderWrapStreamFnContext = ProviderWrapStreamFnContext;","entrypoint":"core","exportName":"ProviderWrapStreamFnContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":466,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderWrapStreamFnContext = ProviderWrapStreamFnContext;","entrypoint":"core","exportName":"ProviderWrapStreamFnContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":477,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type RoutePeer = RoutePeer;","entrypoint":"core","exportName":"RoutePeer","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":21,"sourcePath":"src/routing/resolve-route.ts"}
|
||||
{"declaration":"export type RoutePeerKind = ChatType;","entrypoint":"core","exportName":"RoutePeerKind","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":19,"sourcePath":"src/routing/resolve-route.ts"}
|
||||
{"declaration":"export type SecretFileReadOptions = SecretFileReadOptions;","entrypoint":"core","exportName":"SecretFileReadOptions","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":7,"sourcePath":"src/infra/secret-file.ts"}
|
||||
{"declaration":"export type SecretFileReadResult = SecretFileReadResult;","entrypoint":"core","exportName":"SecretFileReadResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/infra/secret-file.ts"}
|
||||
{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"core","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":917,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"core","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":933,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type TailscaleStatusCommandResult = TailscaleStatusCommandResult;","entrypoint":"core","exportName":"TailscaleStatusCommandResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/shared/tailscale-status.ts"}
|
||||
{"declaration":"export type TailscaleStatusCommandRunner = TailscaleStatusCommandRunner;","entrypoint":"core","exportName":"TailscaleStatusCommandRunner","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/shared/tailscale-status.ts"}
|
||||
{"declaration":"export type UsageProviderId = UsageProviderId;","entrypoint":"core","exportName":"UsageProviderId","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":20,"sourcePath":"src/infra/provider-usage.types.ts"}
|
||||
{"declaration":"export type UsageWindow = UsageWindow;","entrypoint":"core","exportName":"UsageWindow","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/infra/provider-usage.types.ts"}
|
||||
{"declaration":"export class KeyedAsyncQueue","entrypoint":"core","exportName":"KeyedAsyncQueue","importSpecifier":"openclaw/plugin-sdk/core","kind":"class","recordType":"export","sourceLine":34,"sourcePath":"src/plugin-sdk/keyed-async-queue.ts"}
|
||||
{"category":"core","entrypoint":"plugin-entry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/plugin-entry.ts"}
|
||||
{"declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"plugin-entry","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export","sourceLine":79,"sourcePath":"src/plugin-sdk/plugin-entry.ts"}
|
||||
{"declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"plugin-entry","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export","sourceLine":88,"sourcePath":"src/plugin-sdk/plugin-entry.ts"}
|
||||
{"declaration":"export function emptyPluginConfigSchema(): OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"emptyPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export","sourceLine":13,"sourcePath":"src/plugins/config-schema.ts"}
|
||||
{"declaration":"export type AnyAgentTool = AnyAgentTool;","entrypoint":"plugin-entry","exportName":"AnyAgentTool","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/agents/tools/common.ts"}
|
||||
{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"plugin-entry","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":935,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"plugin-entry","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":951,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"plugin-entry","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"}
|
||||
{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-entry","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1292,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1050,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":80,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1275,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"plugin-entry","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1265,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"plugin-entry","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1258,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"plugin-entry","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":950,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"plugin-entry","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1079,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"plugin-entry","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":58,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":560,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthDoctorHintContext = ProviderAuthDoctorHintContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthDoctorHintContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":435,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthMethod = ProviderAuthMethod;","entrypoint":"plugin-entry","exportName":"ProviderAuthMethod","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":222,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthMethodNonInteractiveContext = ProviderAuthMethodNonInteractiveContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthMethodNonInteractiveContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":206,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"plugin-entry","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":130,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuildMissingAuthMessageContext = ProviderBuildMissingAuthMessageContext;","entrypoint":"plugin-entry","exportName":"ProviderBuildMissingAuthMessageContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":488,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuiltInModelSuppressionContext = ProviderBuiltInModelSuppressionContext;","entrypoint":"plugin-entry","exportName":"ProviderBuiltInModelSuppressionContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":504,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuiltInModelSuppressionResult = ProviderBuiltInModelSuppressionResult;","entrypoint":"plugin-entry","exportName":"ProviderBuiltInModelSuppressionResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":513,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCacheTtlEligibilityContext = ProviderCacheTtlEligibilityContext;","entrypoint":"plugin-entry","exportName":"ProviderCacheTtlEligibilityContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":476,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCatalogContext = ProviderCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderCatalogContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":243,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCatalogResult = ProviderCatalogResult;","entrypoint":"plugin-entry","exportName":"ProviderCatalogResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":266,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderDefaultThinkingPolicyContext = ProviderDefaultThinkingPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderDefaultThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":537,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderDiscoveryContext = ProviderCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":576,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderFetchUsageSnapshotContext = ProviderFetchUsageSnapshotContext;","entrypoint":"plugin-entry","exportName":"ProviderFetchUsageSnapshotContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":416,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderModernModelPolicyContext = ProviderModernModelPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderModernModelPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":547,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderNormalizeResolvedModelContext = ProviderNormalizeResolvedModelContext;","entrypoint":"plugin-entry","exportName":"ProviderNormalizeResolvedModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":327,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPreparedRuntimeAuth = ProviderPreparedRuntimeAuth;","entrypoint":"plugin-entry","exportName":"ProviderPreparedRuntimeAuth","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":363,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":318,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareExtraParamsContext = ProviderPrepareExtraParamsContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareExtraParamsContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":449,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareRuntimeAuthContext = ProviderPrepareRuntimeAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareRuntimeAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":342,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolvedUsageAuth = ProviderResolvedUsageAuth;","entrypoint":"plugin-entry","exportName":"ProviderResolvedUsageAuth","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":403,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolveDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"plugin-entry","exportName":"ProviderResolveDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":301,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolveUsageAuthContext = ProviderResolveUsageAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderResolveUsageAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":384,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"plugin-entry","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":284,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":525,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderWrapStreamFnContext = ProviderWrapStreamFnContext;","entrypoint":"plugin-entry","exportName":"ProviderWrapStreamFnContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":466,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"plugin-entry","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":917,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-entry","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1314,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1068,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":88,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1296,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"plugin-entry","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1285,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"plugin-entry","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1277,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"plugin-entry","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":966,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"plugin-entry","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1097,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"plugin-entry","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":59,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":571,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":155,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthDoctorHintContext = ProviderAuthDoctorHintContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthDoctorHintContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":446,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthMethod = ProviderAuthMethod;","entrypoint":"plugin-entry","exportName":"ProviderAuthMethod","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":233,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthMethodNonInteractiveContext = ProviderAuthMethodNonInteractiveContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthMethodNonInteractiveContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":217,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"plugin-entry","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":140,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuildMissingAuthMessageContext = ProviderBuildMissingAuthMessageContext;","entrypoint":"plugin-entry","exportName":"ProviderBuildMissingAuthMessageContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":499,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuiltInModelSuppressionContext = ProviderBuiltInModelSuppressionContext;","entrypoint":"plugin-entry","exportName":"ProviderBuiltInModelSuppressionContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":515,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuiltInModelSuppressionResult = ProviderBuiltInModelSuppressionResult;","entrypoint":"plugin-entry","exportName":"ProviderBuiltInModelSuppressionResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":524,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCacheTtlEligibilityContext = ProviderCacheTtlEligibilityContext;","entrypoint":"plugin-entry","exportName":"ProviderCacheTtlEligibilityContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":487,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCatalogContext = ProviderCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderCatalogContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":254,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCatalogResult = ProviderCatalogResult;","entrypoint":"plugin-entry","exportName":"ProviderCatalogResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":277,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderDefaultThinkingPolicyContext = ProviderDefaultThinkingPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderDefaultThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":548,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderDiscoveryContext = ProviderCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":587,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderFetchUsageSnapshotContext = ProviderFetchUsageSnapshotContext;","entrypoint":"plugin-entry","exportName":"ProviderFetchUsageSnapshotContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":427,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderModernModelPolicyContext = ProviderModernModelPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderModernModelPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":558,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderNormalizeResolvedModelContext = ProviderNormalizeResolvedModelContext;","entrypoint":"plugin-entry","exportName":"ProviderNormalizeResolvedModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":338,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPreparedRuntimeAuth = ProviderPreparedRuntimeAuth;","entrypoint":"plugin-entry","exportName":"ProviderPreparedRuntimeAuth","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":374,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":329,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareExtraParamsContext = ProviderPrepareExtraParamsContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareExtraParamsContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":460,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareRuntimeAuthContext = ProviderPrepareRuntimeAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareRuntimeAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":353,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolvedUsageAuth = ProviderResolvedUsageAuth;","entrypoint":"plugin-entry","exportName":"ProviderResolvedUsageAuth","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":414,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolveDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"plugin-entry","exportName":"ProviderResolveDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":312,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolveUsageAuthContext = ProviderResolveUsageAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderResolveUsageAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":395,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"plugin-entry","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":295,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":536,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderWrapStreamFnContext = ProviderWrapStreamFnContext;","entrypoint":"plugin-entry","exportName":"ProviderWrapStreamFnContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":477,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"plugin-entry","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":933,"sourcePath":"src/plugins/types.ts"}
|
||||
{"category":"provider","entrypoint":"provider-onboard","importSpecifier":"openclaw/plugin-sdk/provider-onboard","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/provider-onboard.ts"}
|
||||
{"declaration":"export function applyAgentDefaultModelPrimary(cfg: OpenClawConfig, primary: string): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyAgentDefaultModelPrimary","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":76,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyCloudflareAiGatewayConfig(cfg: OpenClawConfig, params?: { accountId?: string | undefined; gatewayId?: string | undefined; } | undefined): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyCloudflareAiGatewayConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":85,"sourcePath":"extensions/cloudflare-ai-gateway/onboard.ts"}
|
||||
{"declaration":"export function applyCloudflareAiGatewayProviderConfig(cfg: OpenClawConfig, params?: { accountId?: string | undefined; gatewayId?: string | undefined; } | undefined): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyCloudflareAiGatewayProviderConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":41,"sourcePath":"extensions/cloudflare-ai-gateway/onboard.ts"}
|
||||
{"declaration":"export function applyOnboardAuthAgentModelsAndProviders(cfg: OpenClawConfig, params: { agentModels: Record<string, AgentModelEntryConfig>; providers: Record<string, ModelProviderConfig>; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyOnboardAuthAgentModelsAndProviders","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":53,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithDefaultModel(cfg: OpenClawConfig, params: { agentModels: Record<string, AgentModelEntryConfig>; providerId: string; api: \"github-copilot\" | \"openai-completions\" | ... 5 more ... | \"ollama\"; baseUrl: string; defaultModel: ModelDefinitionConfig; defaultModelId?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithDefaultModel","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":131,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithDefaultModelPreset(cfg: OpenClawConfig, params: { providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\"; ... 4 more ...; primaryModelRef?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithDefaultModelPreset","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":152,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithDefaultModels(cfg: OpenClawConfig, params: { agentModels: Record<string, AgentModelEntryConfig>; providerId: string; api: \"github-copilot\" | \"openai-completions\" | ... 5 more ... | \"ollama\"; baseUrl: string; defaultModels: ModelDefinitionConfig[]; defaultModelId?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithDefaultModels","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":96,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithDefaultModelsPreset(cfg: OpenClawConfig, params: { providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\"; ... 4 more ...; primaryModelRef?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithDefaultModelsPreset","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":177,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithModelCatalog(cfg: OpenClawConfig, params: { agentModels: Record<string, AgentModelEntryConfig>; providerId: string; api: \"github-copilot\" | \"openai-completions\" | ... 5 more ... | \"ollama\"; baseUrl: string; catalogModels: ModelDefinitionConfig[]; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithModelCatalog","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":202,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithModelCatalogPreset(cfg: OpenClawConfig, params: { providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\"; baseUrl: string; catalogModels: ModelDefinitionConfig[]; aliases?: readonly AgentModelAliasEntry[] | undefined; primaryModelRef?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithModelCatalogPreset","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":234,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithDefaultModelsPreset(cfg: OpenClawConfig, params: { providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\"; ... 4 more ...; primaryModelRef?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithDefaultModelsPreset","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":230,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithModelCatalog(cfg: OpenClawConfig, params: { agentModels: Record<string, AgentModelEntryConfig>; providerId: string; api: \"github-copilot\" | \"openai-completions\" | ... 5 more ... | \"ollama\"; baseUrl: string; catalogModels: ModelDefinitionConfig[]; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithModelCatalog","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":272,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithModelCatalogPreset(cfg: OpenClawConfig, params: { providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\"; baseUrl: string; catalogModels: ModelDefinitionConfig[]; aliases?: readonly AgentModelAliasEntry[] | undefined; primaryModelRef?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithModelCatalogPreset","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":304,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyVercelAiGatewayConfig(cfg: OpenClawConfig): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyVercelAiGatewayConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":27,"sourcePath":"extensions/vercel-ai-gateway/onboard.ts"}
|
||||
{"declaration":"export function applyVercelAiGatewayProviderConfig(cfg: OpenClawConfig): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyVercelAiGatewayProviderConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":8,"sourcePath":"extensions/vercel-ai-gateway/onboard.ts"}
|
||||
{"declaration":"export function createDefaultModelPresetAppliers<TArgs extends unknown[]>(params: { resolveParams: (cfg: OpenClawConfig, ...args: TArgs) => Omit<{ providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | ... 4 more ... | \"ollama\"; ... 4 more ...; primaryModelRef?: string | undefined; }, \"primaryModelRef\"> | null | undefined; primaryModelRef: string; }): ProviderOnboardPresetAppliers<...>;","entrypoint":"provider-onboard","exportName":"createDefaultModelPresetAppliers","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":213,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function createDefaultModelsPresetAppliers<TArgs extends unknown[]>(params: { resolveParams: (cfg: OpenClawConfig, ...args: TArgs) => Omit<{ providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | ... 4 more ... | \"ollama\"; ... 4 more ...; primaryModelRef?: string | undefined; }, \"primaryModelRef\"> | null | undefined; primaryModelRef: string; }): ProviderOnboardPresetAppliers<...>;","entrypoint":"provider-onboard","exportName":"createDefaultModelsPresetAppliers","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":255,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function createModelCatalogPresetAppliers<TArgs extends unknown[]>(params: { resolveParams: (cfg: OpenClawConfig, ...args: TArgs) => Omit<{ providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | ... 4 more ... | \"ollama\"; baseUrl: string; catalogModels: ModelDefinitionConfig[]; aliases?: readonly AgentModelAliasEntry[] | undefined; primaryModelRef?: string | undefined; }, \"primaryModelRef\"> | null | undefined; primaryModelRef: string; }): ProviderOnboardPresetAppliers<...>;","entrypoint":"provider-onboard","exportName":"createModelCatalogPresetAppliers","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":327,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function ensureModelAllowlistEntry(params: { cfg: OpenClawConfig; modelRef: string; defaultProvider?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"ensureModelAllowlistEntry","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":5,"sourcePath":"src/plugins/provider-model-allowlist.ts"}
|
||||
{"declaration":"export function withAgentModelAliases(existing: Record<string, AgentModelEntryConfig> | undefined, aliases: readonly AgentModelAliasEntry[]): Record<string, AgentModelEntryConfig>;","entrypoint":"provider-onboard","exportName":"withAgentModelAliases","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":38,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export const CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF: \"cloudflare-ai-gateway/claude-sonnet-4-5\";","entrypoint":"provider-onboard","exportName":"CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"const","recordType":"export","sourceLine":5,"sourcePath":"src/agents/cloudflare-ai-gateway.ts"}
|
||||
{"declaration":"export const VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF: \"vercel-ai-gateway/anthropic/claude-opus-4.6\";","entrypoint":"provider-onboard","exportName":"VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"const","recordType":"export","sourceLine":6,"sourcePath":"extensions/vercel-ai-gateway/onboard.ts"}
|
||||
{"declaration":"export type AgentModelAliasEntry = AgentModelAliasEntry;","entrypoint":"provider-onboard","exportName":"AgentModelAliasEntry","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":21,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export type ModelApi = \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\";","entrypoint":"provider-onboard","exportName":"ModelApi","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":15,"sourcePath":"src/config/types.models.ts"}
|
||||
{"declaration":"export type ModelDefinitionConfig = ModelDefinitionConfig;","entrypoint":"provider-onboard","exportName":"ModelDefinitionConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":46,"sourcePath":"src/config/types.models.ts"}
|
||||
{"declaration":"export type ModelProviderConfig = ModelProviderConfig;","entrypoint":"provider-onboard","exportName":"ModelProviderConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":64,"sourcePath":"src/config/types.models.ts"}
|
||||
{"declaration":"export type ModelDefinitionConfig = ModelDefinitionConfig;","entrypoint":"provider-onboard","exportName":"ModelDefinitionConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":47,"sourcePath":"src/config/types.models.ts"}
|
||||
{"declaration":"export type ModelProviderConfig = ModelProviderConfig;","entrypoint":"provider-onboard","exportName":"ModelProviderConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":65,"sourcePath":"src/config/types.models.ts"}
|
||||
{"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"provider-onboard","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"}
|
||||
{"declaration":"export type ProviderOnboardPresetAppliers = ProviderOnboardPresetAppliers<TArgs>;","entrypoint":"provider-onboard","exportName":"ProviderOnboardPresetAppliers","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":177,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"category":"utilities","entrypoint":"reply-payload","importSpecifier":"openclaw/plugin-sdk/reply-payload","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/reply-payload.ts"}
|
||||
{"declaration":"export function buildMediaPayload(mediaList: MediaPayloadInput[], opts?: { preserveMediaTypeCardinality?: boolean | undefined; } | undefined): MediaPayload;","entrypoint":"reply-payload","exportName":"buildMediaPayload","importSpecifier":"openclaw/plugin-sdk/reply-payload","kind":"function","recordType":"export","sourceLine":15,"sourcePath":"src/channels/plugins/media-payload.ts"}
|
||||
{"declaration":"export function countOutboundMedia(payload: { mediaUrls?: string[] | undefined; mediaUrl?: string | undefined; }): number;","entrypoint":"reply-payload","exportName":"countOutboundMedia","importSpecifier":"openclaw/plugin-sdk/reply-payload","kind":"function","recordType":"export","sourceLine":83,"sourcePath":"src/plugin-sdk/reply-payload.ts"}
|
||||
@@ -505,25 +521,25 @@
|
||||
{"declaration":"export type SendableOutboundReplyParts = SendableOutboundReplyParts;","entrypoint":"reply-payload","exportName":"SendableOutboundReplyParts","importSpecifier":"openclaw/plugin-sdk/reply-payload","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/plugin-sdk/reply-payload.ts"}
|
||||
{"category":"runtime","entrypoint":"runtime-store","importSpecifier":"openclaw/plugin-sdk/runtime-store","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/runtime-store.ts"}
|
||||
{"declaration":"export function createPluginRuntimeStore<T>(errorMessage: string): { setRuntime: (next: T) => void; clearRuntime: () => void; tryGetRuntime: () => T | null; getRuntime: () => T; };","entrypoint":"runtime-store","exportName":"createPluginRuntimeStore","importSpecifier":"openclaw/plugin-sdk/runtime-store","kind":"function","recordType":"export","sourceLine":4,"sourcePath":"src/plugin-sdk/runtime-store.ts"}
|
||||
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"runtime-store","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/runtime-store","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/plugins/runtime/types.ts"}
|
||||
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"runtime-store","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/runtime-store","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/plugins/runtime/types.ts"}
|
||||
{"category":"channel","entrypoint":"secret-input","importSpecifier":"openclaw/plugin-sdk/secret-input","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/secret-input.ts"}
|
||||
{"declaration":"export function buildOptionalSecretInputSchema(): ZodOptional<ZodUnion<readonly [ZodString, ZodDiscriminatedUnion<[ZodObject<{ source: ZodLiteral<\"env\">; provider: ZodString; id: ZodString; }, $strip>, ZodObject<...>, ZodObject<...>], \"source\">]>>;","entrypoint":"secret-input","exportName":"buildOptionalSecretInputSchema","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":17,"sourcePath":"src/plugin-sdk/secret-input.ts"}
|
||||
{"declaration":"export function buildSecretInputArraySchema(): ZodArray<ZodUnion<readonly [ZodString, ZodDiscriminatedUnion<[ZodObject<{ source: ZodLiteral<\"env\">; provider: ZodString; id: ZodString; }, $strip>, ZodObject<...>, ZodObject<...>], \"source\">]>>;","entrypoint":"secret-input","exportName":"buildSecretInputArraySchema","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":21,"sourcePath":"src/plugin-sdk/secret-input.ts"}
|
||||
{"declaration":"export function buildOptionalSecretInputSchema(): ZodOptional<ZodUnion<readonly [ZodString, ZodDiscriminatedUnion<[ZodObject<{ source: ZodLiteral<\"env\">; provider: ZodString; id: ZodString; }, $strip>, ZodObject<...>, ZodObject<...>], \"source\">]>>;","entrypoint":"secret-input","exportName":"buildOptionalSecretInputSchema","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":18,"sourcePath":"src/plugin-sdk/secret-input.ts"}
|
||||
{"declaration":"export function buildSecretInputArraySchema(): ZodArray<ZodUnion<readonly [ZodString, ZodDiscriminatedUnion<[ZodObject<{ source: ZodLiteral<\"env\">; provider: ZodString; id: ZodString; }, $strip>, ZodObject<...>, ZodObject<...>], \"source\">]>>;","entrypoint":"secret-input","exportName":"buildSecretInputArraySchema","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":23,"sourcePath":"src/plugin-sdk/secret-input.ts"}
|
||||
{"declaration":"export function buildSecretInputSchema(): ZodUnion<readonly [ZodString, ZodDiscriminatedUnion<[ZodObject<{ source: ZodLiteral<\"env\">; provider: ZodString; id: ZodString; }, $strip>, ZodObject<...>, ZodObject<...>], \"source\">]>;","entrypoint":"secret-input","exportName":"buildSecretInputSchema","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":11,"sourcePath":"src/plugin-sdk/secret-input-schema.ts"}
|
||||
{"declaration":"export function hasConfiguredSecretInput(value: unknown, defaults?: SecretDefaults | undefined): boolean;","entrypoint":"secret-input","exportName":"hasConfiguredSecretInput","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":106,"sourcePath":"src/config/types.secrets.ts"}
|
||||
{"declaration":"export function normalizeResolvedSecretInputString(params: { value: unknown; refValue?: unknown; defaults?: SecretDefaults | undefined; path: string; }): string | undefined;","entrypoint":"secret-input","exportName":"normalizeResolvedSecretInputString","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":144,"sourcePath":"src/config/types.secrets.ts"}
|
||||
{"declaration":"export function normalizeSecretInputString(value: unknown): string | undefined;","entrypoint":"secret-input","exportName":"normalizeSecretInputString","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":113,"sourcePath":"src/config/types.secrets.ts"}
|
||||
{"declaration":"export type SecretInput = SecretInput;","entrypoint":"secret-input","exportName":"SecretInput","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"type","recordType":"export","sourceLine":16,"sourcePath":"src/config/types.secrets.ts"}
|
||||
{"category":"utilities","entrypoint":"testing","importSpecifier":"openclaw/plugin-sdk/testing","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/testing.ts"}
|
||||
{"declaration":"export function createWindowsCmdShimFixture(params: { shimPath: string; scriptPath: string; shimLine: string; }): Promise<void>;","entrypoint":"testing","exportName":"createWindowsCmdShimFixture","importSpecifier":"openclaw/plugin-sdk/testing","kind":"function","recordType":"export","sourceLine":15,"sourcePath":"src/plugin-sdk/testing.ts"}
|
||||
{"declaration":"export function installCommonResolveTargetErrorCases(params: { resolveTarget: ResolveTargetFn; implicitAllowFrom: string[]; }): void;","entrypoint":"testing","exportName":"installCommonResolveTargetErrorCases","importSpecifier":"openclaw/plugin-sdk/testing","kind":"function","recordType":"export","sourceLine":40,"sourcePath":"src/plugin-sdk/testing.ts"}
|
||||
{"declaration":"export function createWindowsCmdShimFixture(params: { shimPath: string; scriptPath: string; shimLine: string; }): Promise<void>;","entrypoint":"testing","exportName":"createWindowsCmdShimFixture","importSpecifier":"openclaw/plugin-sdk/testing","kind":"function","recordType":"export","sourceLine":16,"sourcePath":"src/plugin-sdk/testing.ts"}
|
||||
{"declaration":"export function installCommonResolveTargetErrorCases(params: { resolveTarget: ResolveTargetFn; implicitAllowFrom: string[]; }): void;","entrypoint":"testing","exportName":"installCommonResolveTargetErrorCases","importSpecifier":"openclaw/plugin-sdk/testing","kind":"function","recordType":"export","sourceLine":42,"sourcePath":"src/plugin-sdk/testing.ts"}
|
||||
{"declaration":"export function removeAckReactionAfterReply(params: { removeAfterReply: boolean; ackReactionPromise: Promise<boolean> | null; ackReactionValue: string | null; remove: () => Promise<void>; onError?: ((err: unknown) => void) | undefined; }): void;","entrypoint":"testing","exportName":"removeAckReactionAfterReply","importSpecifier":"openclaw/plugin-sdk/testing","kind":"function","recordType":"export","sourceLine":81,"sourcePath":"src/channels/ack-reactions.ts"}
|
||||
{"declaration":"export function shouldAckReaction(params: AckReactionGateParams): boolean;","entrypoint":"testing","exportName":"shouldAckReaction","importSpecifier":"openclaw/plugin-sdk/testing","kind":"function","recordType":"export","sourceLine":16,"sourcePath":"src/channels/ack-reactions.ts"}
|
||||
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"testing","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":139,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"testing","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type ChannelGatewayContext = ChannelGatewayContext<ResolvedAccount>;","entrypoint":"testing","exportName":"ChannelGatewayContext","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":238,"sourcePath":"src/channels/plugins/types.adapters.ts"}
|
||||
{"declaration":"export type MockFn = MockFn<T>;","entrypoint":"testing","exportName":"MockFn","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":5,"sourcePath":"src/test-utils/vitest-mock-fn.ts"}
|
||||
{"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"testing","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"}
|
||||
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"testing","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/plugins/runtime/types.ts"}
|
||||
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"testing","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/plugins/runtime/types.ts"}
|
||||
{"declaration":"export type RuntimeEnv = RuntimeEnv;","entrypoint":"testing","exportName":"RuntimeEnv","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/runtime.ts"}
|
||||
{"category":"channel","entrypoint":"webhook-ingress","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/webhook-ingress.ts"}
|
||||
{"declaration":"export function applyBasicWebhookRequestGuards(params: { req: IncomingMessage; res: ServerResponse<IncomingMessage>; allowMethods?: readonly string[] | undefined; rateLimiter?: FixedWindowRateLimiter | undefined; rateLimitKey?: string | undefined; nowMs?: number | undefined; requireJsonContentType?: boolean | undefined; }): boolean;","entrypoint":"webhook-ingress","exportName":"applyBasicWebhookRequestGuards","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":148,"sourcePath":"src/plugin-sdk/webhook-request-guards.ts"}
|
||||
@@ -533,15 +549,16 @@
|
||||
{"declaration":"export function createWebhookAnomalyTracker(options?: { maxTrackedKeys?: number | undefined; ttlMs?: number | undefined; logEvery?: number | undefined; trackedStatusCodes?: readonly number[] | undefined; } | undefined): WebhookAnomalyTracker;","entrypoint":"webhook-ingress","exportName":"createWebhookAnomalyTracker","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":167,"sourcePath":"src/plugin-sdk/webhook-memory-guards.ts"}
|
||||
{"declaration":"export function createWebhookInFlightLimiter(options?: { maxInFlightPerKey?: number | undefined; maxTrackedKeys?: number | undefined; } | undefined): WebhookInFlightLimiter;","entrypoint":"webhook-ingress","exportName":"createWebhookInFlightLimiter","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":91,"sourcePath":"src/plugin-sdk/webhook-request-guards.ts"}
|
||||
{"declaration":"export function isJsonContentType(value: string | string[] | undefined): boolean;","entrypoint":"webhook-ingress","exportName":"isJsonContentType","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":138,"sourcePath":"src/plugin-sdk/webhook-request-guards.ts"}
|
||||
{"declaration":"export function isRequestBodyLimitError(error: unknown, code?: RequestBodyLimitErrorCode | undefined): error is RequestBodyLimitError;","entrypoint":"webhook-ingress","exportName":"isRequestBodyLimitError","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":46,"sourcePath":"src/infra/http-body.ts"}
|
||||
{"declaration":"export function isRequestBodyLimitError(error: unknown, code?: RequestBodyLimitErrorCode | undefined): error is RequestBodyLimitError;","entrypoint":"webhook-ingress","exportName":"isRequestBodyLimitError","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":47,"sourcePath":"src/infra/http-body.ts"}
|
||||
{"declaration":"export function normalizePluginHttpPath(path?: string | null | undefined, fallback?: string | null | undefined): string | null;","entrypoint":"webhook-ingress","exportName":"normalizePluginHttpPath","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":1,"sourcePath":"src/plugins/http-path.ts"}
|
||||
{"declaration":"export function normalizeWebhookPath(raw: string): string;","entrypoint":"webhook-ingress","exportName":"normalizeWebhookPath","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":2,"sourcePath":"src/plugin-sdk/webhook-path.ts"}
|
||||
{"declaration":"export function readJsonWebhookBodyOrReject(params: { req: IncomingMessage; res: ServerResponse<IncomingMessage>; maxBytes?: number | undefined; timeoutMs?: number | undefined; profile?: WebhookBodyReadProfile | undefined; emptyObjectOnEmpty?: boolean | undefined; invalidJsonMessage?: string | undefined; }): Promise<...>;","entrypoint":"webhook-ingress","exportName":"readJsonWebhookBodyOrReject","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":275,"sourcePath":"src/plugin-sdk/webhook-request-guards.ts"}
|
||||
{"declaration":"export function readRequestBodyWithLimit(req: IncomingMessage, options: ReadRequestBodyOptions): Promise<string>;","entrypoint":"webhook-ingress","exportName":"readRequestBodyWithLimit","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":121,"sourcePath":"src/infra/http-body.ts"}
|
||||
{"declaration":"export function readRequestBodyWithLimit(req: IncomingMessage, options: ReadRequestBodyOptions): Promise<string>;","entrypoint":"webhook-ingress","exportName":"readRequestBodyWithLimit","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":122,"sourcePath":"src/infra/http-body.ts"}
|
||||
{"declaration":"export function readWebhookBodyOrReject(params: { req: IncomingMessage; res: ServerResponse<IncomingMessage>; maxBytes?: number | undefined; timeoutMs?: number | undefined; profile?: WebhookBodyReadProfile | undefined; invalidBodyMessage?: string | undefined; }): Promise<...>;","entrypoint":"webhook-ingress","exportName":"readWebhookBodyOrReject","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":240,"sourcePath":"src/plugin-sdk/webhook-request-guards.ts"}
|
||||
{"declaration":"export function registerPluginHttpRoute(params: { path?: string | null | undefined; fallbackPath?: string | null | undefined; handler: PluginHttpRouteHandler; auth: OpenClawPluginHttpRouteAuth; ... 6 more ...; registry?: PluginRegistry | undefined; }): () => void;","entrypoint":"webhook-ingress","exportName":"registerPluginHttpRoute","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":12,"sourcePath":"src/plugins/http-registry.ts"}
|
||||
{"declaration":"export function registerWebhookTarget<T extends { path: string; }>(targetsByPath: Map<string, T[]>, target: T, opts?: RegisterWebhookTargetOptions<T> | undefined): RegisteredWebhookTarget<T>;","entrypoint":"webhook-ingress","exportName":"registerWebhookTarget","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":61,"sourcePath":"src/plugin-sdk/webhook-targets.ts"}
|
||||
{"declaration":"export function registerWebhookTargetWithPluginRoute<T extends { path: string; }>(params: { targetsByPath: Map<string, T[]>; target: T; route: RegisterWebhookPluginRouteOptions; onLastPathTargetRemoved?: ((params: { ...; }) => void) | undefined; }): RegisteredWebhookTarget<...>;","entrypoint":"webhook-ingress","exportName":"registerWebhookTargetWithPluginRoute","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":30,"sourcePath":"src/plugin-sdk/webhook-targets.ts"}
|
||||
{"declaration":"export function requestBodyErrorToText(code: RequestBodyLimitErrorCode): string;","entrypoint":"webhook-ingress","exportName":"requestBodyErrorToText","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":59,"sourcePath":"src/infra/http-body.ts"}
|
||||
{"declaration":"export function requestBodyErrorToText(code: RequestBodyLimitErrorCode): string;","entrypoint":"webhook-ingress","exportName":"requestBodyErrorToText","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":60,"sourcePath":"src/infra/http-body.ts"}
|
||||
{"declaration":"export function resolveSingleWebhookTarget<T>(targets: readonly T[], isMatch: (target: T) => boolean): WebhookTargetMatchResult<T>;","entrypoint":"webhook-ingress","exportName":"resolveSingleWebhookTarget","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":193,"sourcePath":"src/plugin-sdk/webhook-targets.ts"}
|
||||
{"declaration":"export function resolveSingleWebhookTargetAsync<T>(targets: readonly T[], isMatch: (target: T) => Promise<boolean>): Promise<WebhookTargetMatchResult<T>>;","entrypoint":"webhook-ingress","exportName":"resolveSingleWebhookTargetAsync","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":212,"sourcePath":"src/plugin-sdk/webhook-targets.ts"}
|
||||
{"declaration":"export function resolveWebhookPath(params: { webhookPath?: string | undefined; webhookUrl?: string | undefined; defaultPath?: string | null | undefined; }): string | null;","entrypoint":"webhook-ingress","exportName":"resolveWebhookPath","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":15,"sourcePath":"src/plugin-sdk/webhook-path.ts"}
|
||||
|
||||
@@ -261,7 +261,7 @@ Isolated jobs (`agentTurn`) can set `lightContext: true` to run with lightweight
|
||||
Isolated jobs can deliver output to a channel via the top-level `delivery` config:
|
||||
|
||||
- `delivery.mode`: `announce` (channel delivery), `webhook` (HTTP POST), or `none`.
|
||||
- `delivery.channel`: `whatsapp` / `telegram` / `discord` / `slack` / `mattermost` (plugin) / `signal` / `imessage` / `last`.
|
||||
- `delivery.channel`: `whatsapp` / `telegram` / `discord` / `slack` / `signal` / `imessage` / `irc` / `googlechat` / `line` / `last`, plus extension channels like `msteams` / `mattermost` (plugins).
|
||||
- `delivery.to`: channel-specific recipient target.
|
||||
|
||||
`announce` delivery is only valid for isolated jobs (`sessionTarget: "isolated"`).
|
||||
|
||||
@@ -8,7 +8,7 @@ title: "Hooks"
|
||||
|
||||
# Hooks
|
||||
|
||||
Hooks provide an extensible event-driven system for automating actions in response to agent commands and events. Hooks are automatically discovered from directories and can be managed via CLI commands, similar to how skills work in OpenClaw.
|
||||
Hooks provide an extensible event-driven system for automating actions in response to agent commands and events. Hooks are automatically discovered from directories and can be inspected with `openclaw hooks`, while hook-pack installation and updates now go through `openclaw plugins`.
|
||||
|
||||
## Getting Oriented
|
||||
|
||||
@@ -17,7 +17,7 @@ Hooks are small scripts that run when something happens. There are two kinds:
|
||||
- **Hooks** (this page): run inside the Gateway when agent events fire, like `/new`, `/reset`, `/stop`, or lifecycle events.
|
||||
- **Webhooks**: external HTTP webhooks that let other systems trigger work in OpenClaw. See [Webhook Hooks](/automation/webhook) or use `openclaw webhooks` for Gmail helper commands.
|
||||
|
||||
Hooks can also be bundled inside plugins; see [Plugin hooks](/plugins/architecture#provider-runtime-hooks).
|
||||
Hooks can also be bundled inside plugins; see [Plugin hooks](/plugins/architecture#provider-runtime-hooks). `openclaw hooks list` shows both standalone hooks and plugin-managed hooks.
|
||||
|
||||
Common uses:
|
||||
|
||||
@@ -26,7 +26,7 @@ Common uses:
|
||||
- Trigger follow-up automation when a session starts or ends
|
||||
- Write files into the agent workspace or call external APIs when events fire
|
||||
|
||||
If you can write a small TypeScript function, you can write a hook. Hooks are discovered automatically, and you enable or disable them via the CLI.
|
||||
If you can write a small TypeScript function, you can write a hook. Managed and bundled hooks are trusted local code. Workspace hooks are discovered automatically, but OpenClaw keeps them disabled until you explicitly enable them via the CLI or config.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -43,7 +43,7 @@ The hooks system allows you to:
|
||||
|
||||
OpenClaw ships with four bundled hooks that are automatically discovered:
|
||||
|
||||
- **💾 session-memory**: Saves session context to your agent workspace (default `~/.openclaw/workspace/memory/`) when you issue `/new`
|
||||
- **💾 session-memory**: Saves session context to your agent workspace (default `~/.openclaw/workspace/memory/`) when you issue `/new` or `/reset`
|
||||
- **📎 bootstrap-extra-files**: Injects additional workspace bootstrap files from configured glob/path patterns during `agent:bootstrap`
|
||||
- **📝 command-logger**: Logs all command events to `~/.openclaw/logs/commands.log`
|
||||
- **🚀 boot-md**: Runs `BOOT.md` when the gateway starts (requires internal hooks enabled)
|
||||
@@ -76,13 +76,20 @@ openclaw hooks info session-memory
|
||||
|
||||
During onboarding (`openclaw onboard`), you'll be prompted to enable recommended hooks. The wizard automatically discovers eligible hooks and presents them for selection.
|
||||
|
||||
### Trust Boundary
|
||||
|
||||
Hooks run inside the Gateway process. Treat bundled hooks, managed hooks, and `hooks.internal.load.extraDirs` as trusted local code. Workspace hooks under `<workspace>/hooks/` are repo-local code, so OpenClaw requires an explicit enable step before loading them.
|
||||
|
||||
## Hook Discovery
|
||||
|
||||
Hooks are automatically discovered from three directories (in order of precedence):
|
||||
Hooks are automatically discovered from these directories, in order of increasing override precedence:
|
||||
|
||||
1. **Workspace hooks**: `<workspace>/hooks/` (per-agent, highest precedence)
|
||||
2. **Managed hooks**: `~/.openclaw/hooks/` (user-installed, shared across workspaces)
|
||||
3. **Bundled hooks**: `<openclaw>/dist/hooks/bundled/` (shipped with OpenClaw)
|
||||
1. **Bundled hooks**: shipped with OpenClaw; located at `<openclaw>/dist/hooks/bundled/` for npm installs (or a sibling `hooks/bundled/` for compiled binaries)
|
||||
2. **Plugin hooks**: hooks bundled inside installed plugins (see [Plugin hooks](/plugins/architecture#provider-runtime-hooks))
|
||||
3. **Managed hooks**: `~/.openclaw/hooks/` (user-installed, shared across workspaces; can override bundled and plugin hooks). **Extra hook directories** configured via `hooks.internal.load.extraDirs` are also treated as managed hooks and share the same override precedence.
|
||||
4. **Workspace hooks**: `<workspace>/hooks/` (per-agent, disabled by default until explicitly enabled; cannot override hooks from other sources)
|
||||
|
||||
Workspace hooks can add new hook names for a repo, but they cannot override bundled, managed, or plugin-provided hooks with the same name.
|
||||
|
||||
Managed hook directories can be either a **single hook** or a **hook pack** (package directory).
|
||||
|
||||
@@ -100,7 +107,7 @@ Hook packs are standard npm packages that export one or more hooks via `openclaw
|
||||
`package.json`. Install them with:
|
||||
|
||||
```bash
|
||||
openclaw hooks install <path-or-spec>
|
||||
openclaw plugins install <path-or-spec>
|
||||
```
|
||||
|
||||
Npm specs are registry-only (package name + optional exact version or dist-tag).
|
||||
@@ -127,7 +134,7 @@ Hook packs can ship dependencies; they will be installed under `~/.openclaw/hook
|
||||
Each `openclaw.hooks` entry must stay inside the package directory after symlink
|
||||
resolution; entries that escape are rejected.
|
||||
|
||||
Security note: `openclaw hooks install` installs dependencies with `npm install --ignore-scripts`
|
||||
Security note: `openclaw plugins install` installs hook-pack dependencies with `npm install --ignore-scripts`
|
||||
(no lifecycle scripts). Keep hook pack dependency trees "pure JS/TS" and avoid packages that rely
|
||||
on `postinstall` builds.
|
||||
|
||||
@@ -173,12 +180,12 @@ The `metadata.openclaw` object supports:
|
||||
- **`events`**: Array of events to listen for (e.g., `["command:new", "command:reset"]`)
|
||||
- **`export`**: Named export to use (defaults to `"default"`)
|
||||
- **`homepage`**: Documentation URL
|
||||
- **`os`**: Required platforms (e.g., `["darwin", "linux"]`)
|
||||
- **`requires`**: Optional requirements
|
||||
- **`bins`**: Required binaries on PATH (e.g., `["git", "node"]`)
|
||||
- **`anyBins`**: At least one of these binaries must be present
|
||||
- **`env`**: Required environment variables
|
||||
- **`config`**: Required config paths (e.g., `["workspace.dir"]`)
|
||||
- **`os`**: Required platforms (e.g., `["darwin", "linux"]`)
|
||||
- **`always`**: Bypass eligibility checks (boolean)
|
||||
- **`install`**: Installation methods (for bundled hooks: `[{"id":"bundled","kind":"bundled"}]`)
|
||||
|
||||
@@ -218,15 +225,17 @@ Each event includes:
|
||||
timestamp: Date, // When the event occurred
|
||||
messages: string[], // Push messages here to send to user
|
||||
context: {
|
||||
// Command events:
|
||||
sessionEntry?: SessionEntry,
|
||||
sessionId?: string,
|
||||
sessionFile?: string,
|
||||
commandSource?: string, // e.g., 'whatsapp', 'telegram'
|
||||
// Command events (command:new, command:reset):
|
||||
sessionEntry?: SessionEntry, // current session entry
|
||||
previousSessionEntry?: SessionEntry, // pre-reset entry (preferred for session-memory)
|
||||
commandSource?: string, // e.g., 'whatsapp', 'telegram'
|
||||
senderId?: string,
|
||||
workspaceDir?: string,
|
||||
bootstrapFiles?: WorkspaceBootstrapFile[],
|
||||
cfg?: OpenClawConfig,
|
||||
// Command events (command:stop only):
|
||||
sessionId?: string,
|
||||
// Agent bootstrap events (agent:bootstrap):
|
||||
bootstrapFiles?: WorkspaceBootstrapFile[],
|
||||
// Message events (see Message Events section for full details):
|
||||
from?: string, // message:received
|
||||
to?: string, // message:sent
|
||||
@@ -294,11 +303,13 @@ Message events include rich context about the message:
|
||||
to?: string,
|
||||
provider?: string,
|
||||
surface?: string,
|
||||
threadId?: string,
|
||||
threadId?: string | number,
|
||||
senderId?: string,
|
||||
senderName?: string,
|
||||
senderUsername?: string,
|
||||
senderE164?: string,
|
||||
guildId?: string, // Discord guild / server ID
|
||||
channelName?: string, // Channel name (e.g., Discord channel name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,22 +329,42 @@ Message events include rich context about the message:
|
||||
|
||||
// message:transcribed context
|
||||
{
|
||||
from?: string, // Sender identifier
|
||||
to?: string, // Recipient identifier
|
||||
body?: string, // Raw inbound body before enrichment
|
||||
bodyForAgent?: string, // Enriched body visible to the agent
|
||||
transcript: string, // Audio transcript text
|
||||
timestamp?: number, // Unix timestamp when received
|
||||
channelId: string, // Channel (e.g., "telegram", "whatsapp")
|
||||
conversationId?: string,
|
||||
messageId?: string,
|
||||
senderId?: string, // Sender user ID
|
||||
senderName?: string, // Sender display name
|
||||
senderUsername?: string,
|
||||
provider?: string, // Provider name
|
||||
surface?: string, // Surface name
|
||||
mediaPath?: string, // Path to the media file that was transcribed
|
||||
mediaType?: string, // MIME type of the media
|
||||
}
|
||||
|
||||
// message:preprocessed context
|
||||
{
|
||||
from?: string, // Sender identifier
|
||||
to?: string, // Recipient identifier
|
||||
body?: string, // Raw inbound body
|
||||
bodyForAgent?: string, // Final enriched body after media/link understanding
|
||||
transcript?: string, // Transcript when audio was present
|
||||
timestamp?: number, // Unix timestamp when received
|
||||
channelId: string, // Channel (e.g., "telegram", "whatsapp")
|
||||
conversationId?: string,
|
||||
messageId?: string,
|
||||
senderId?: string, // Sender user ID
|
||||
senderName?: string, // Sender display name
|
||||
senderUsername?: string,
|
||||
provider?: string, // Provider name
|
||||
surface?: string, // Surface name
|
||||
mediaPath?: string, // Path to the media file
|
||||
mediaType?: string, // MIME type of the media
|
||||
isGroup?: boolean,
|
||||
groupId?: string,
|
||||
}
|
||||
@@ -383,8 +414,8 @@ Planned event types:
|
||||
|
||||
### 1. Choose Location
|
||||
|
||||
- **Workspace hooks** (`<workspace>/hooks/`): Per-agent, highest precedence
|
||||
- **Managed hooks** (`~/.openclaw/hooks/`): Shared across workspaces
|
||||
- **Workspace hooks** (`<workspace>/hooks/`): Per-agent; can add new hook names but cannot override bundled, managed, or plugin hooks with the same name
|
||||
- **Managed hooks** (`~/.openclaw/hooks/`): Shared across workspaces; can override bundled and plugin hooks
|
||||
|
||||
### 2. Create Directory Structure
|
||||
|
||||
@@ -479,7 +510,7 @@ Hooks can have custom configuration:
|
||||
|
||||
### Extra Directories
|
||||
|
||||
Load hooks from additional directories:
|
||||
Load hooks from additional directories (treated as managed hooks, same override precedence):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -571,9 +602,9 @@ openclaw hooks disable command-logger
|
||||
|
||||
### session-memory
|
||||
|
||||
Saves session context to memory when you issue `/new`.
|
||||
Saves session context to memory when you issue `/new` or `/reset`.
|
||||
|
||||
**Events**: `command:new`
|
||||
**Events**: `command:new`, `command:reset`
|
||||
|
||||
**Requirements**: `workspace.dir` must be configured
|
||||
|
||||
@@ -582,7 +613,7 @@ Saves session context to memory when you issue `/new`.
|
||||
**What it does**:
|
||||
|
||||
1. Uses the pre-reset session entry to locate the correct transcript
|
||||
2. Extracts the last 15 lines of conversation
|
||||
2. Extracts the last 15 user/assistant messages from the conversation (configurable)
|
||||
3. Uses LLM to generate a descriptive filename slug
|
||||
4. Saves session metadata to a dated memory file
|
||||
|
||||
@@ -594,6 +625,11 @@ Saves session context to memory when you issue `/new`.
|
||||
- **Session Key**: agent:main:main
|
||||
- **Session ID**: abc123def456
|
||||
- **Source**: telegram
|
||||
|
||||
## Conversation Summary
|
||||
|
||||
user: Can you help me design the API?
|
||||
assistant: Sure! Let's start with the endpoints...
|
||||
```
|
||||
|
||||
**Filename examples**:
|
||||
@@ -636,12 +672,18 @@ Injects additional bootstrap files (for example monorepo-local `AGENTS.md` / `TO
|
||||
}
|
||||
```
|
||||
|
||||
**Config options**:
|
||||
|
||||
- `paths` (string[]): glob/path patterns to resolve from the workspace.
|
||||
- `patterns` (string[]): alias of `paths`.
|
||||
- `files` (string[]): alias of `paths`.
|
||||
|
||||
**Notes**:
|
||||
|
||||
- Paths are resolved relative to workspace.
|
||||
- Files must stay inside workspace (realpath-checked).
|
||||
- Only recognized bootstrap basenames are loaded.
|
||||
- Subagent allowlist is preserved (`AGENTS.md` and `TOOLS.md` only).
|
||||
- Only recognized bootstrap basenames are loaded (`AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md`, `MEMORY.md`, `memory.md`).
|
||||
- For subagent/cron sessions a narrower allowlist applies (`AGENTS.md`, `TOOLS.md`, `SOUL.md`, `IDENTITY.md`, `USER.md`).
|
||||
|
||||
**Enable**:
|
||||
|
||||
@@ -874,10 +916,12 @@ test("my handler works", async () => {
|
||||
```
|
||||
Gateway startup
|
||||
↓
|
||||
Scan directories (workspace → managed → bundled)
|
||||
Scan directories (bundled → plugin → managed + extra dirs → workspace)
|
||||
↓
|
||||
Parse HOOK.md files
|
||||
↓
|
||||
Sort by override precedence (bundled < plugin < managed < workspace)
|
||||
↓
|
||||
Check eligibility (bins, env, config, os)
|
||||
↓
|
||||
Load handlers from eligible hooks
|
||||
|
||||
@@ -43,7 +43,7 @@ Each program specifies:
|
||||
The agent loads these instructions every session via the workspace bootstrap files (see [Agent Workspace](/concepts/agent-workspace) for the full list of auto-injected files) and executes against them, combined with [cron jobs](/automation/cron-jobs) for time-based enforcement.
|
||||
|
||||
<Tip>
|
||||
Put standing orders in `AGENTS.md` to guarantee they're loaded every session. The workspace bootstrap automatically injects `AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, and `MEMORY.md` — but not arbitrary files in subdirectories.
|
||||
Put standing orders in `AGENTS.md` to guarantee they're loaded every session. The workspace bootstrap automatically injects `AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md`, and `MEMORY.md` — but not arbitrary files in subdirectories.
|
||||
</Tip>
|
||||
|
||||
## Anatomy of a Standing Order
|
||||
@@ -86,7 +86,7 @@ Agent: Reads standing orders → executes steps → reports results
|
||||
The cron job prompt should reference the standing order rather than duplicating it:
|
||||
|
||||
```bash
|
||||
openclaw cron create \
|
||||
openclaw cron add \
|
||||
--name daily-inbox-triage \
|
||||
--cron "0 8 * * 1-5" \
|
||||
--tz America/New_York \
|
||||
@@ -237,7 +237,7 @@ Each program should have:
|
||||
- Review agent logs weekly to verify standing orders are being followed
|
||||
- Update standing orders as your needs evolve — they're living documents
|
||||
|
||||
### Don't
|
||||
### Avoid
|
||||
|
||||
- Grant broad authority on day one ("do whatever you think is best")
|
||||
- Skip escalation rules — every program needs a "when to stop and ask" clause
|
||||
|
||||
@@ -84,7 +84,7 @@ Payload:
|
||||
- `sessionKey` optional (string): The key used to identify the agent's session. By default this field is rejected unless `hooks.allowRequestSessionKey=true`.
|
||||
- `wakeMode` optional (`now` | `next-heartbeat`): Whether to trigger an immediate heartbeat (default `now`) or wait for the next periodic check.
|
||||
- `deliver` optional (boolean): If `true`, the agent's response will be sent to the messaging channel. Defaults to `true`. Responses that are only heartbeat acknowledgments are automatically skipped.
|
||||
- `channel` optional (string): The messaging channel for delivery. One of: `last`, `whatsapp`, `telegram`, `discord`, `slack`, `mattermost` (plugin), `signal`, `imessage`, `msteams`. Defaults to `last`.
|
||||
- `channel` optional (string): The messaging channel for delivery. Core channels: `last`, `whatsapp`, `telegram`, `discord`, `slack`, `signal`, `imessage`, `irc`, `googlechat`, `line`. Extension channels (plugins): `msteams`, `mattermost`, and others. Defaults to `last`.
|
||||
- `to` optional (string): The recipient identifier for the channel (e.g., phone number for WhatsApp/Signal, chat ID for Telegram, channel ID for Discord/Slack/Mattermost (plugin), conversation ID for Microsoft Teams). Defaults to the last recipient in the main session.
|
||||
- `model` optional (string): Model override (e.g., `anthropic/claude-3-5-sonnet` or an alias). Must be in the allowed model list if restricted.
|
||||
- `thinking` optional (string): Thinking level override (e.g., `low`, `medium`, `high`).
|
||||
|
||||
@@ -3,7 +3,7 @@ summary: "Brave Search API setup for web_search"
|
||||
read_when:
|
||||
- You want to use Brave Search for web_search
|
||||
- You need a BRAVE_API_KEY or plan details
|
||||
title: "Brave Search"
|
||||
title: "Brave Search (legacy path)"
|
||||
---
|
||||
|
||||
# Brave Search API
|
||||
|
||||
@@ -13,7 +13,7 @@ host configuration.
|
||||
|
||||
## Key terms
|
||||
|
||||
- **Channel**: `whatsapp`, `telegram`, `discord`, `slack`, `signal`, `imessage`, `webchat`.
|
||||
- **Channel**: `telegram`, `whatsapp`, `discord`, `irc`, `googlechat`, `slack`, `signal`, `imessage`, `line`, plus extension channels. `webchat` is the internal WebChat UI channel and is not a configurable outbound channel.
|
||||
- **AccountId**: per‑channel account instance (when supported).
|
||||
- Optional channel default account: `channels.<channel>.defaultAccount` chooses
|
||||
which account is used when an outbound path does not specify `accountId`.
|
||||
|
||||
@@ -92,7 +92,7 @@ You will need to create a new application with a bot, add the bot to your server
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Step 0: Set your bot token securely (do not send it in chat)">
|
||||
<Step title="Set your bot token securely (do not send it in chat)">
|
||||
Your Discord bot token is a secret (like a password). Set it on the machine running OpenClaw before messaging your agent.
|
||||
|
||||
```bash
|
||||
@@ -582,6 +582,7 @@ Default slash command settings:
|
||||
OpenClaw can stream draft replies by sending a temporary message and editing it as text arrives.
|
||||
|
||||
- `channels.discord.streaming` controls preview streaming (`off` | `partial` | `block` | `progress`, default: `off`).
|
||||
- Default stays `off` because Discord preview edits can hit rate limits quickly, especially when multiple bots or gateways share the same account or guild traffic.
|
||||
- `progress` is accepted for cross-channel consistency and maps to `partial` on Discord.
|
||||
- `channels.discord.streamMode` is a legacy alias and is auto-migrated.
|
||||
- `partial` edits a single preview message as tokens arrive.
|
||||
|
||||
@@ -116,7 +116,7 @@ Want “groups can only see folder X” instead of “no host access”? Keep `w
|
||||
|
||||
Related:
|
||||
|
||||
- Configuration keys and defaults: [Gateway configuration](/gateway/configuration-reference#agents-defaults-sandbox)
|
||||
- Configuration keys and defaults: [Gateway configuration](/gateway/configuration-reference#agentsdefaultssandbox)
|
||||
- Debugging why a tool is blocked: [Sandbox vs Tool Policy vs Elevated](/gateway/sandbox-vs-tool-policy-vs-elevated)
|
||||
- Bind mounts details: [Sandboxing](/gateway/sandboxing#custom-bind-mounts)
|
||||
|
||||
|
||||
@@ -130,6 +130,12 @@ Notes:
|
||||
- **open**: public inbound DMs (requires `allowFrom: ["*"]`).
|
||||
- **disabled**: ignore inbound DMs.
|
||||
|
||||
Enforcement notes:
|
||||
|
||||
- Sender policy is checked before signature verification and NIP-04 decryption.
|
||||
- Pairing replies are sent without processing the original DM body.
|
||||
- Inbound DMs are rate-limited and oversized payloads are dropped before decrypt.
|
||||
|
||||
### Allowlist example
|
||||
|
||||
```json5
|
||||
@@ -234,6 +240,7 @@ docker run -p 7777:7777 ghcr.io/hoytech/strfry
|
||||
- Never commit private keys.
|
||||
- Use environment variables for keys.
|
||||
- Consider `allowlist` for production bots.
|
||||
- Pairing and allowlist policy is enforced before decrypt, so unknown senders cannot force full crypto work.
|
||||
|
||||
## Limitations (MVP)
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ openclaw pairing list telegram
|
||||
openclaw pairing approve telegram <CODE>
|
||||
```
|
||||
|
||||
Supported channels: `telegram`, `whatsapp`, `signal`, `imessage`, `discord`, `slack`, `feishu`.
|
||||
Supported channels: `bluebubbles`, `discord`, `feishu`, `googlechat`, `imessage`, `irc`, `line`, `matrix`, `mattermost`, `msteams`, `nextcloud-talk`, `nostr`, `signal`, `slack`, `synology-chat`, `telegram`, `twitch`, `whatsapp`, `zalo`, `zalouser`.
|
||||
|
||||
### Where the state lives
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ Config values override env vars.
|
||||
- In `allowlist` mode, an empty `allowedUserIds` list is treated as misconfiguration and the webhook route will not start (use `dmPolicy: "open"` for allow-all).
|
||||
- `dmPolicy: "open"` allows any sender.
|
||||
- `dmPolicy: "disabled"` blocks DMs.
|
||||
- Reply recipient binding stays on stable numeric `user_id` by default. `channels.synology-chat.dangerouslyAllowNameMatching: true` is break-glass compatibility mode that re-enables mutable username/nickname lookup for reply delivery.
|
||||
- Pairing approvals work with:
|
||||
- `openclaw pairing list synology-chat`
|
||||
- `openclaw pairing approve synology-chat <CODE>`
|
||||
@@ -102,6 +103,11 @@ Multiple Synology Chat accounts are supported under `channels.synology-chat.acco
|
||||
Each account can override token, incoming URL, webhook path, DM policy, and limits.
|
||||
Direct-message sessions are isolated per account and user, so the same numeric `user_id`
|
||||
on two different Synology accounts does not share transcript state.
|
||||
Give each enabled account a distinct `webhookPath`. OpenClaw now rejects duplicate exact paths
|
||||
and refuses to start named accounts that only inherit a shared webhook path in multi-account setups.
|
||||
If you intentionally need legacy inheritance for a named account, set
|
||||
`dangerouslyAllowInheritedWebhookPath: true` on that account or at `channels.synology-chat`,
|
||||
but duplicate exact paths are still rejected fail-closed. Prefer explicit per-account paths.
|
||||
|
||||
```json5
|
||||
{
|
||||
@@ -132,3 +138,5 @@ on two different Synology accounts does not share transcript state.
|
||||
- Keep `allowInsecureSsl: false` unless you explicitly trust a self-signed local NAS cert.
|
||||
- Inbound webhook requests are token-verified and rate-limited per sender.
|
||||
- Prefer `dmPolicy: "allowlist"` for production.
|
||||
- Keep `dangerouslyAllowNameMatching` off unless you explicitly need legacy username-based reply delivery.
|
||||
- Keep `dangerouslyAllowInheritedWebhookPath` off unless you explicitly accept shared-path routing risk in a multi-account setup.
|
||||
|
||||
@@ -115,4 +115,4 @@ Full troubleshooting: [/channels/signal#troubleshooting](/channels/signal#troubl
|
||||
| DMs do not process | `openclaw pairing list matrix` | Approve sender or adjust DM policy. |
|
||||
| Encrypted rooms fail | Verify crypto module and encryption settings | Enable encryption support and rejoin/sync room. |
|
||||
|
||||
Full troubleshooting: [/channels/matrix#troubleshooting](/channels/matrix#troubleshooting)
|
||||
Full setup and config: [Matrix](/channels/matrix)
|
||||
|
||||
30
docs/ci.md
30
docs/ci.md
@@ -12,20 +12,21 @@ The CI runs on every push to `main` and every pull request. It uses smart scopin
|
||||
|
||||
## Job Overview
|
||||
|
||||
| Job | Purpose | When it runs |
|
||||
| ----------------- | ------------------------------------------------------- | ---------------------------------- |
|
||||
| `docs-scope` | Detect docs-only changes | Always |
|
||||
| `changed-scope` | Detect which areas changed (node/macos/android/windows) | Non-doc changes |
|
||||
| `check` | TypeScript types, lint, format | Non-docs, node changes |
|
||||
| `check-docs` | Markdown lint + broken link check | Docs changed |
|
||||
| `secrets` | Detect leaked secrets | Always |
|
||||
| `build-artifacts` | Build dist once, share with `release-check` | Pushes to `main`, node changes |
|
||||
| `release-check` | Validate npm pack contents | Pushes to `main` after build |
|
||||
| `checks` | Node tests + protocol check on PRs; Bun compat on push | Non-docs, node changes |
|
||||
| `compat-node22` | Minimum supported Node runtime compatibility | Pushes to `main`, node changes |
|
||||
| `checks-windows` | Windows-specific tests | Non-docs, windows-relevant changes |
|
||||
| `macos` | Swift lint/build/test + TS tests | PRs with macos changes |
|
||||
| `android` | Gradle build + tests | Non-docs, android changes |
|
||||
| Job | Purpose | When it runs |
|
||||
| ----------------- | ------------------------------------------------------------------------- | ------------------------------------------------ |
|
||||
| `preflight` | Docs scope, change scope, key scan, workflow audit, prod dependency audit | Always; node-based audit only on non-doc changes |
|
||||
| `docs-scope` | Detect docs-only changes | Always |
|
||||
| `changed-scope` | Detect which areas changed (node/macos/android/windows) | Non-doc changes |
|
||||
| `check` | TypeScript types, lint, format | Non-docs, node changes |
|
||||
| `check-docs` | Markdown lint + broken link check | Docs changed |
|
||||
| `secrets` | Detect leaked secrets | Always |
|
||||
| `build-artifacts` | Build dist once, share with `release-check` | Pushes to `main`, node changes |
|
||||
| `release-check` | Validate npm pack contents | Pushes to `main` after build |
|
||||
| `checks` | Node tests + protocol check on PRs; Bun compat on push | Non-docs, node changes |
|
||||
| `compat-node22` | Minimum supported Node runtime compatibility | Pushes to `main`, node changes |
|
||||
| `checks-windows` | Windows-specific tests | Non-docs, windows-relevant changes |
|
||||
| `macos` | Swift lint/build/test + TS tests | PRs with macos changes |
|
||||
| `android` | Gradle build + tests | Non-docs, android changes |
|
||||
|
||||
## Fail-Fast Order
|
||||
|
||||
@@ -36,6 +37,7 @@ Jobs are ordered so cheap checks fail before expensive ones run:
|
||||
3. Pushes to `main`: `build-artifacts` + `release-check` + Bun compat + `compat-node22`
|
||||
|
||||
Scope logic lives in `scripts/ci-changed-scope.mjs` and is covered by unit tests in `src/scripts/ci-changed-scope.test.ts`.
|
||||
The same shared scope module also drives the separate `install-smoke` workflow through a narrower `changed-smoke` gate, so Docker/install smoke only runs for install, packaging, and container-relevant changes.
|
||||
|
||||
## Runners
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ Notes:
|
||||
- When token auth requires a token and `gateway.auth.token` is SecretRef-managed, `gateway install` validates that the SecretRef is resolvable but does not persist the resolved token into service environment metadata.
|
||||
- If token auth requires a token and the configured token SecretRef is unresolved, install fails closed instead of persisting fallback plaintext.
|
||||
- For password auth on `gateway run`, prefer `OPENCLAW_GATEWAY_PASSWORD`, `--password-file`, or a SecretRef-backed `gateway.auth.password` over inline `--password`.
|
||||
- In inferred auth mode, shell-only `OPENCLAW_GATEWAY_PASSWORD`/`CLAWDBOT_GATEWAY_PASSWORD` does not relax install token requirements; use durable config (`gateway.auth.password` or config `env`) when installing a managed service.
|
||||
- In inferred auth mode, shell-only `OPENCLAW_GATEWAY_PASSWORD` does not relax install token requirements; use durable config (`gateway.auth.password` or config `env`) when installing a managed service.
|
||||
- If both `gateway.auth.token` and `gateway.auth.password` are configured and `gateway.auth.mode` is unset, install is blocked until mode is set explicitly.
|
||||
- Lifecycle commands accept `--json` for scripting.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
summary: "CLI reference for `openclaw hooks` (agent hooks)"
|
||||
read_when:
|
||||
- You want to manage agent hooks
|
||||
- You want to install or update hooks
|
||||
- You want to inspect hook availability or enable workspace hooks
|
||||
title: "hooks"
|
||||
---
|
||||
|
||||
@@ -21,7 +21,7 @@ Related:
|
||||
openclaw hooks list
|
||||
```
|
||||
|
||||
List all discovered hooks from workspace, managed, and bundled directories.
|
||||
List all discovered hooks from workspace, managed, extra, and bundled directories.
|
||||
|
||||
**Options:**
|
||||
|
||||
@@ -38,7 +38,7 @@ Ready:
|
||||
🚀 boot-md ✓ - Run BOOT.md on gateway startup
|
||||
📎 bootstrap-extra-files ✓ - Inject extra workspace bootstrap files during agent bootstrap
|
||||
📝 command-logger ✓ - Log all command events to a centralized audit file
|
||||
💾 session-memory ✓ - Save session context to memory when /new command is issued
|
||||
💾 session-memory ✓ - Save session context to memory when /new or /reset command is issued
|
||||
```
|
||||
|
||||
**Example (verbose):**
|
||||
@@ -84,14 +84,14 @@ openclaw hooks info session-memory
|
||||
```
|
||||
💾 session-memory ✓ Ready
|
||||
|
||||
Save session context to memory when /new command is issued
|
||||
Save session context to memory when /new or /reset command is issued
|
||||
|
||||
Details:
|
||||
Source: openclaw-bundled
|
||||
Path: /path/to/openclaw/hooks/bundled/session-memory/HOOK.md
|
||||
Handler: /path/to/openclaw/hooks/bundled/session-memory/handler.ts
|
||||
Homepage: https://docs.openclaw.ai/automation/hooks#session-memory
|
||||
Events: command:new
|
||||
Events: command:new, command:reset
|
||||
|
||||
Requirements:
|
||||
Config: ✓ workspace.dir
|
||||
@@ -127,8 +127,7 @@ openclaw hooks enable <name>
|
||||
|
||||
Enable a specific hook by adding it to your config (`~/.openclaw/config.json`).
|
||||
|
||||
**Note:** Hooks managed by plugins show `plugin:<id>` in `openclaw hooks list` and
|
||||
can’t be enabled/disabled here. Enable/disable the plugin instead.
|
||||
**Note:** Workspace hooks are disabled by default until enabled here or in config. Hooks managed by plugins show `plugin:<id>` in `openclaw hooks list` and can’t be enabled/disabled here. Enable/disable the plugin instead.
|
||||
|
||||
**Arguments:**
|
||||
|
||||
@@ -152,6 +151,9 @@ openclaw hooks enable session-memory
|
||||
- Updates `hooks.internal.entries.<name>.enabled = true` in your config
|
||||
- Saves config to disk
|
||||
|
||||
If the hook came from `<workspace>/hooks/`, this opt-in step is required before
|
||||
the Gateway will load it.
|
||||
|
||||
**After enabling:**
|
||||
|
||||
- Restart the gateway so hooks reload (menu bar app restart on macOS, or restart your gateway process in dev).
|
||||
@@ -184,14 +186,18 @@ openclaw hooks disable command-logger
|
||||
|
||||
- Restart the gateway so hooks reload
|
||||
|
||||
## Install Hooks
|
||||
## Install Hook Packs
|
||||
|
||||
```bash
|
||||
openclaw hooks install <path-or-spec>
|
||||
openclaw hooks install <npm-spec> --pin
|
||||
openclaw plugins install <package> # ClawHub first, then npm
|
||||
openclaw plugins install <package> --pin # pin version
|
||||
openclaw plugins install <path> # local path
|
||||
```
|
||||
|
||||
Install a hook pack from a local folder/archive or npm.
|
||||
Install hook packs through the unified plugins installer.
|
||||
|
||||
`openclaw hooks install` still works as a compatibility alias, but it prints a
|
||||
deprecation warning and forwards to `openclaw plugins install`.
|
||||
|
||||
Npm specs are **registry-only** (package name + optional **exact version** or
|
||||
**dist-tag**). Git/URL/file specs and semver ranges are rejected. Dependency
|
||||
@@ -218,26 +224,32 @@ prerelease tag such as `@beta`/`@rc` or an exact prerelease version.
|
||||
|
||||
```bash
|
||||
# Local directory
|
||||
openclaw hooks install ./my-hook-pack
|
||||
openclaw plugins install ./my-hook-pack
|
||||
|
||||
# Local archive
|
||||
openclaw hooks install ./my-hook-pack.zip
|
||||
openclaw plugins install ./my-hook-pack.zip
|
||||
|
||||
# NPM package
|
||||
openclaw hooks install @openclaw/my-hook-pack
|
||||
openclaw plugins install @openclaw/my-hook-pack
|
||||
|
||||
# Link a local directory without copying
|
||||
openclaw hooks install -l ./my-hook-pack
|
||||
openclaw plugins install -l ./my-hook-pack
|
||||
```
|
||||
|
||||
## Update Hooks
|
||||
Linked hook packs are treated as managed hooks from an operator-configured
|
||||
directory, not as workspace hooks.
|
||||
|
||||
## Update Hook Packs
|
||||
|
||||
```bash
|
||||
openclaw hooks update <id>
|
||||
openclaw hooks update --all
|
||||
openclaw plugins update <id>
|
||||
openclaw plugins update --all
|
||||
```
|
||||
|
||||
Update installed hook packs (npm installs only).
|
||||
Update tracked npm-based hook packs through the unified plugins updater.
|
||||
|
||||
`openclaw hooks update` still works as a compatibility alias, but it prints a
|
||||
deprecation warning and forwards to `openclaw plugins update`.
|
||||
|
||||
**Options:**
|
||||
|
||||
@@ -252,7 +264,7 @@ global `--yes` to bypass prompts in CI/non-interactive runs.
|
||||
|
||||
### session-memory
|
||||
|
||||
Saves session context to memory when you issue `/new`.
|
||||
Saves session context to memory when you issue `/new` or `/reset`.
|
||||
|
||||
**Enable:**
|
||||
|
||||
|
||||
@@ -485,6 +485,9 @@ List and inspect available skills plus readiness info.
|
||||
|
||||
Subcommands:
|
||||
|
||||
- `skills search [query...]`: search ClawHub skills.
|
||||
- `skills install <slug>`: install a skill from ClawHub into the active workspace.
|
||||
- `skills update <slug|--all>`: update tracked ClawHub skills.
|
||||
- `skills list`: list skills (default when no subcommand).
|
||||
- `skills info <name>`: show details for one skill.
|
||||
- `skills check`: summary of ready vs missing requirements.
|
||||
@@ -495,7 +498,7 @@ Options:
|
||||
- `--json`: output JSON (no styling).
|
||||
- `-v`, `--verbose`: include missing requirements detail.
|
||||
|
||||
Tip: use `npx clawhub` to search, install, and sync skills.
|
||||
Tip: use `openclaw skills search`, `openclaw skills install`, and `openclaw skills update` for ClawHub-backed skills.
|
||||
|
||||
### `pairing`
|
||||
|
||||
@@ -1032,7 +1035,7 @@ Subcommands:
|
||||
Auth notes:
|
||||
|
||||
- `node` resolves gateway auth from env/config (no `--token`/`--password` flags): `OPENCLAW_GATEWAY_TOKEN` / `OPENCLAW_GATEWAY_PASSWORD`, then `gateway.auth.*`. In local mode, node host intentionally ignores `gateway.remote.*`; in `gateway.mode=remote`, `gateway.remote.*` participates per remote precedence rules.
|
||||
- Legacy `CLAWDBOT_GATEWAY_*` env vars are intentionally ignored for node-host auth resolution.
|
||||
- Node-host auth resolution only honors `OPENCLAW_GATEWAY_*` env vars.
|
||||
|
||||
## Nodes
|
||||
|
||||
|
||||
@@ -31,6 +31,11 @@ Node hosts automatically advertise a browser proxy if `browser.enabled` is not
|
||||
disabled on the node. This lets the agent use browser automation on that node
|
||||
without extra configuration.
|
||||
|
||||
By default, the proxy exposes the node's normal browser profile surface. If you
|
||||
set `nodeHost.browserProxy.allowProfiles`, the proxy becomes restrictive:
|
||||
non-allowlisted profile targeting is rejected, and persistent profile
|
||||
create/delete routes are blocked through the proxy.
|
||||
|
||||
Disable it on the node if needed:
|
||||
|
||||
```json5
|
||||
@@ -67,7 +72,7 @@ Options:
|
||||
- In local mode, node host intentionally does not inherit `gateway.remote.token` / `gateway.remote.password`.
|
||||
- If `gateway.auth.token` / `gateway.auth.password` is explicitly configured via SecretRef and unresolved, node auth resolution fails closed (no remote fallback masking).
|
||||
- In `gateway.mode=remote`, remote client fields (`gateway.remote.token` / `gateway.remote.password`) are also eligible per remote precedence rules.
|
||||
- Legacy `CLAWDBOT_GATEWAY_*` env vars are ignored for node host auth resolution.
|
||||
- Node host auth resolution only honors `OPENCLAW_GATEWAY_*` env vars.
|
||||
|
||||
## Service (background)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ title: "plugins"
|
||||
|
||||
# `openclaw plugins`
|
||||
|
||||
Manage Gateway plugins/extensions and compatible bundles.
|
||||
Manage Gateway plugins/extensions, hook packs, and compatible bundles.
|
||||
|
||||
Related:
|
||||
|
||||
@@ -46,13 +46,20 @@ capabilities.
|
||||
### Install
|
||||
|
||||
```bash
|
||||
openclaw plugins install <path-or-spec>
|
||||
openclaw plugins install <npm-spec> --pin
|
||||
openclaw plugins install <plugin>@<marketplace>
|
||||
openclaw plugins install <plugin> --marketplace <marketplace>
|
||||
openclaw plugins install <package> # ClawHub first, then npm
|
||||
openclaw plugins install clawhub:<package> # ClawHub only
|
||||
openclaw plugins install <package> --pin # pin version
|
||||
openclaw plugins install <path> # local path
|
||||
openclaw plugins install <plugin>@<marketplace> # marketplace
|
||||
openclaw plugins install <plugin> --marketplace <name> # marketplace (explicit)
|
||||
```
|
||||
|
||||
Security note: treat plugin installs like running code. Prefer pinned versions.
|
||||
Bare package names are checked against ClawHub first, then npm. Security note:
|
||||
treat plugin installs like running code. Prefer pinned versions.
|
||||
|
||||
`plugins install` is also the install surface for hook packs that expose
|
||||
`openclaw.hooks` in `package.json`. Use `openclaw hooks` for filtered hook
|
||||
visibility and per-hook enablement, not package installation.
|
||||
|
||||
Npm specs are **registry-only** (package name + optional **exact version** or
|
||||
**dist-tag**). Git/URL/file specs and semver ranges are rejected. Dependency
|
||||
@@ -71,6 +78,25 @@ Supported archives: `.zip`, `.tgz`, `.tar.gz`, `.tar`.
|
||||
|
||||
Claude marketplace installs are also supported.
|
||||
|
||||
ClawHub installs use an explicit `clawhub:<package>` locator:
|
||||
|
||||
```bash
|
||||
openclaw plugins install clawhub:openclaw-codex-app-server
|
||||
openclaw plugins install clawhub:openclaw-codex-app-server@1.2.3
|
||||
```
|
||||
|
||||
OpenClaw now also prefers ClawHub for bare npm-safe plugin specs. It only falls
|
||||
back to npm if ClawHub does not have that package or version:
|
||||
|
||||
```bash
|
||||
openclaw plugins install openclaw-codex-app-server
|
||||
```
|
||||
|
||||
OpenClaw downloads the package archive from ClawHub, checks the advertised
|
||||
plugin API / minimum gateway compatibility, then installs it through the normal
|
||||
archive path. Recorded installs keep their ClawHub source metadata for later
|
||||
updates.
|
||||
|
||||
Use `plugin@marketplace` shorthand when the marketplace name exists in Claude's
|
||||
local registry cache at `~/.claude/plugins/known_marketplaces.json`:
|
||||
|
||||
@@ -94,6 +120,11 @@ Marketplace sources can be:
|
||||
- a GitHub repo shorthand such as `owner/repo`
|
||||
- a git URL
|
||||
|
||||
For remote marketplaces loaded from GitHub or git, plugin entries must stay
|
||||
inside the cloned marketplace repo. OpenClaw accepts relative path sources from
|
||||
that repo and rejects external git, GitHub, URL/archive, and absolute-path
|
||||
plugin sources from remote manifests.
|
||||
|
||||
For local paths and archives, OpenClaw auto-detects:
|
||||
|
||||
- native OpenClaw plugins (`openclaw.plugin.json`)
|
||||
@@ -144,8 +175,8 @@ openclaw plugins update <id-or-npm-spec> --dry-run
|
||||
openclaw plugins update @openclaw/voice-call@beta
|
||||
```
|
||||
|
||||
Updates apply to tracked installs in `plugins.installs`, currently npm and
|
||||
marketplace installs.
|
||||
Updates apply to tracked installs in `plugins.installs` and tracked hook-pack
|
||||
installs in `hooks.internal.installs`.
|
||||
|
||||
When you pass a plugin id, OpenClaw reuses the recorded install spec for that
|
||||
plugin. That means previously stored dist-tags such as `@beta` and exact pinned
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
---
|
||||
summary: "CLI reference for `openclaw skills` (list/info/check) and skill eligibility"
|
||||
summary: "CLI reference for `openclaw skills` (search/install/update/list/info/check)"
|
||||
read_when:
|
||||
- You want to see which skills are available and ready to run
|
||||
- You want to search, install, or update skills from ClawHub
|
||||
- You want to debug missing binaries/env/config for skills
|
||||
title: "skills"
|
||||
---
|
||||
|
||||
# `openclaw skills`
|
||||
|
||||
Inspect skills (bundled + workspace + managed overrides) and see what’s eligible vs missing requirements.
|
||||
Inspect local skills and install/update skills from ClawHub.
|
||||
|
||||
Related:
|
||||
|
||||
@@ -19,8 +20,17 @@ Related:
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
openclaw skills search "calendar"
|
||||
openclaw skills install <slug>
|
||||
openclaw skills install <slug> --version <version>
|
||||
openclaw skills update <slug>
|
||||
openclaw skills update --all
|
||||
openclaw skills list
|
||||
openclaw skills list --eligible
|
||||
openclaw skills info <name>
|
||||
openclaw skills check
|
||||
```
|
||||
|
||||
`search`/`install`/`update` use ClawHub directly and install into the active
|
||||
workspace `skills/` directory. `list`/`info`/`check` still inspect the local
|
||||
skills visible to the current workspace and config.
|
||||
|
||||
@@ -81,10 +81,10 @@ Legacy session folders from other tools are not read.
|
||||
## Steering while streaming
|
||||
|
||||
When queue mode is `steer`, inbound messages are injected into the current run.
|
||||
The queue is checked **after each tool call**; if a queued message is present,
|
||||
remaining tool calls from the current assistant message are skipped (error tool
|
||||
results with "Skipped due to queued user message."), then the queued user
|
||||
message is injected before the next assistant response.
|
||||
Queued steering is delivered **after the current assistant turn finishes
|
||||
executing its tool calls**, before the next LLM call. Steering no longer skips
|
||||
remaining tool calls from the current assistant message; it injects the queued
|
||||
message at the next model boundary instead.
|
||||
|
||||
When queue mode is `followup` or `collect`, inbound messages are held until the
|
||||
current turn ends, then a new agent turn starts with the queued payloads. See
|
||||
|
||||
@@ -23,8 +23,7 @@ The default workspace layout uses two memory layers:
|
||||
- Read today + yesterday at session start.
|
||||
- `MEMORY.md` (optional)
|
||||
- Curated long-term memory.
|
||||
- If both `MEMORY.md` and `memory.md` exist at the workspace root, OpenClaw only loads `MEMORY.md`.
|
||||
- Lowercase `memory.md` is only used as a fallback when `MEMORY.md` is absent.
|
||||
- If both `MEMORY.md` and `memory.md` exist at the workspace root, OpenClaw loads both (deduplicated by realpath so symlinks pointing to the same file are not injected twice).
|
||||
- **Only load in the main, private session** (never in group contexts).
|
||||
|
||||
These files live under the workspace (`agents.defaults.workspace`, default
|
||||
|
||||
@@ -26,7 +26,7 @@ Related:
|
||||
|
||||
- `agents.defaults.models` is the allowlist/catalog of models OpenClaw can use (plus aliases).
|
||||
- `agents.defaults.imageModel` is used **only when** the primary model can’t accept images.
|
||||
- `agents.defaults.imageGenerationModel` is used by the shared image-generation capability. If omitted, `image_generate` can still infer a provider default from compatible auth-backed image-generation plugins.
|
||||
- `agents.defaults.imageGenerationModel` is used by the shared image-generation capability. If omitted, `image_generate` can still infer a provider default from compatible auth-backed image-generation plugins. If you set a specific provider/model, also configure that provider's auth/API key.
|
||||
- Per-agent defaults can override `agents.defaults.model` via `agents.list[].model` plus bindings (see [/concepts/multi-agent](/concepts/multi-agent)).
|
||||
|
||||
## Quick model policy
|
||||
|
||||
@@ -162,13 +162,20 @@ Enforcement points:
|
||||
|
||||
## sessions_spawn
|
||||
|
||||
Spawn a sub-agent run in an isolated session and announce the result back to the requester chat channel.
|
||||
Spawn an isolated delegated session.
|
||||
|
||||
- Default runtime: OpenClaw sub-agent (`runtime: "subagent"`).
|
||||
- ACP harness sessions use `runtime: "acp"` and follow ACP-specific targeting/policy rules.
|
||||
- This section focuses on sub-agent behavior unless noted otherwise. For ACP-specific behavior, see [ACP Agents](/tools/acp-agents).
|
||||
|
||||
Parameters:
|
||||
|
||||
- `task` (required)
|
||||
- `runtime?` (`subagent|acp`; defaults to `subagent`)
|
||||
- `label?` (optional; used for logs/UI)
|
||||
- `agentId?` (optional; spawn under another agent id if allowed)
|
||||
- `agentId?` (optional)
|
||||
- `runtime: "subagent"`: target another OpenClaw agent id if allowed by `subagents.allowAgents`
|
||||
- `runtime: "acp"`: target an ACP harness id if allowed by `acp.allowedAgents`
|
||||
- `model?` (optional; overrides the sub-agent model; invalid values error)
|
||||
- `thinking?` (optional; overrides thinking level for the sub-agent run)
|
||||
- `runTimeoutSeconds?` (defaults to `agents.defaults.subagents.runTimeoutSeconds` when set, otherwise `0`; when set, aborts the sub-agent run after N seconds)
|
||||
@@ -181,12 +188,14 @@ Parameters:
|
||||
|
||||
Allowlist:
|
||||
|
||||
- `agents.list[].subagents.allowAgents`: list of agent ids allowed via `agentId` (`["*"]` to allow any). Default: only the requester agent.
|
||||
- `runtime: "subagent"`: `agents.list[].subagents.allowAgents` controls which OpenClaw agent ids are allowed via `agentId` (`["*"]` to allow any). Default: only the requester agent.
|
||||
- `runtime: "acp"`: `acp.allowedAgents` controls which ACP harness ids are allowed. This is a separate policy from `subagents.allowAgents`.
|
||||
- Sandbox inheritance guard: if the requester session is sandboxed, `sessions_spawn` rejects targets that would run unsandboxed.
|
||||
|
||||
Discovery:
|
||||
|
||||
- Use `agents_list` to discover which agent ids are allowed for `sessions_spawn`.
|
||||
- Use `agents_list` to discover allowed targets for `runtime: "subagent"`.
|
||||
- For `runtime: "acp"`, use configured ACP harness ids and `acp.allowedAgents`; `agents_list` does not list ACP harness targets.
|
||||
|
||||
Behavior:
|
||||
|
||||
|
||||
@@ -84,6 +84,30 @@
|
||||
"source": "/perplexity",
|
||||
"destination": "/tools/perplexity-search"
|
||||
},
|
||||
{
|
||||
"source": "/web-fetch",
|
||||
"destination": "/tools/web-fetch"
|
||||
},
|
||||
{
|
||||
"source": "/duckduckgo-search",
|
||||
"destination": "/tools/duckduckgo-search"
|
||||
},
|
||||
{
|
||||
"source": "/exa-search",
|
||||
"destination": "/tools/exa-search"
|
||||
},
|
||||
{
|
||||
"source": "/gemini-search",
|
||||
"destination": "/tools/gemini-search"
|
||||
},
|
||||
{
|
||||
"source": "/grok-search",
|
||||
"destination": "/tools/grok-search"
|
||||
},
|
||||
{
|
||||
"source": "/kimi-search",
|
||||
"destination": "/tools/kimi-search"
|
||||
},
|
||||
{
|
||||
"source": "/tts",
|
||||
"destination": "/tools/tts"
|
||||
@@ -1037,24 +1061,29 @@
|
||||
"group": "Plugins",
|
||||
"pages": [
|
||||
"tools/plugin",
|
||||
"plugins/building-plugins",
|
||||
"plugins/community",
|
||||
"plugins/bundles",
|
||||
"plugins/manifest",
|
||||
"plugins/sdk-migration",
|
||||
"plugins/architecture"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Plugin SDK",
|
||||
"pages": [
|
||||
"plugins/sdk-overview",
|
||||
"plugins/sdk-entrypoints",
|
||||
"plugins/sdk-runtime",
|
||||
"plugins/sdk-setup",
|
||||
"plugins/sdk-channel-plugins",
|
||||
"plugins/sdk-provider-plugins",
|
||||
"plugins/sdk-testing"
|
||||
{
|
||||
"group": "Building Plugins",
|
||||
"pages": [
|
||||
"plugins/building-plugins",
|
||||
"plugins/sdk-channel-plugins",
|
||||
"plugins/sdk-provider-plugins",
|
||||
"plugins/sdk-migration"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "SDK Reference",
|
||||
"pages": [
|
||||
"plugins/sdk-overview",
|
||||
"plugins/sdk-entrypoints",
|
||||
"plugins/sdk-runtime",
|
||||
"plugins/sdk-setup",
|
||||
"plugins/sdk-testing",
|
||||
"plugins/manifest",
|
||||
"plugins/architecture"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1087,7 +1116,7 @@
|
||||
"pages": [
|
||||
"tools/apply-patch",
|
||||
{
|
||||
"group": "Browser",
|
||||
"group": "Web Browser",
|
||||
"pages": [
|
||||
"tools/browser",
|
||||
"tools/browser-login",
|
||||
@@ -1095,6 +1124,22 @@
|
||||
"tools/browser-wsl2-windows-remote-cdp-troubleshooting"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Web Tools",
|
||||
"pages": [
|
||||
"tools/web-fetch",
|
||||
"tools/web",
|
||||
"tools/brave-search",
|
||||
"tools/duckduckgo-search",
|
||||
"tools/exa-search",
|
||||
"tools/firecrawl",
|
||||
"tools/gemini-search",
|
||||
"tools/grok-search",
|
||||
"tools/kimi-search",
|
||||
"tools/perplexity-search",
|
||||
"tools/tavily"
|
||||
]
|
||||
},
|
||||
"tools/btw",
|
||||
"tools/diffs",
|
||||
"tools/elevated",
|
||||
@@ -1105,17 +1150,7 @@
|
||||
"tools/loop-detection",
|
||||
"tools/pdf",
|
||||
"tools/reactions",
|
||||
"tools/thinking",
|
||||
{
|
||||
"group": "Web and search",
|
||||
"pages": [
|
||||
"tools/web",
|
||||
"tools/brave-search",
|
||||
"tools/firecrawl",
|
||||
"tools/perplexity-search",
|
||||
"tools/tavily"
|
||||
]
|
||||
}
|
||||
"tools/thinking"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -179,7 +179,7 @@ WhatsApp runs through the gateway's web channel (Baileys Web). It starts automat
|
||||
historyLimit: 50,
|
||||
replyToMode: "first", // off | first | all
|
||||
linkPreview: true,
|
||||
streaming: "partial", // off | partial | block | progress (default: off)
|
||||
streaming: "partial", // off | partial | block | progress (default: off; opt in explicitly to avoid preview-edit rate limits)
|
||||
actions: { reactions: true, sendMessage: true },
|
||||
reactionNotifications: "own", // off | own | all
|
||||
mediaMaxMb: 100,
|
||||
@@ -905,8 +905,8 @@ Time format in system prompt. Default: `auto` (OS preference).
|
||||
- `imageGenerationModel`: accepts either a string (`"provider/model"`) or an object (`{ primary, fallbacks }`).
|
||||
- Used by the shared image-generation capability and any future tool/plugin surface that generates images.
|
||||
- Typical values: `google/gemini-3-pro-image-preview` for the native Nano Banana-style flow, `fal/fal-ai/flux/dev` for fal, or `openai/gpt-image-1` for OpenAI Images.
|
||||
- If you select a provider/model directly, configure the matching provider auth/API key too (for example `GEMINI_API_KEY` or `GOOGLE_API_KEY` for `google/*`, `OPENAI_API_KEY` for `openai/*`, `FAL_KEY` for `fal/*`).
|
||||
- If omitted, `image_generate` can still infer a best-effort provider default from compatible auth-backed image-generation providers.
|
||||
- Typical values: `google/gemini-3-pro-image-preview`, `fal/fal-ai/flux/dev`, `openai/gpt-image-1`.
|
||||
- `pdfModel`: accepts either a string (`"provider/model"`) or an object (`{ primary, fallbacks }`).
|
||||
- Used by the `pdf` tool for model routing.
|
||||
- If omitted, the PDF tool falls back to `imageModel`, then to best-effort provider defaults.
|
||||
|
||||
@@ -251,7 +251,7 @@ When validation fails:
|
||||
|
||||
Build the image first: `scripts/sandbox-setup.sh`
|
||||
|
||||
See [Sandboxing](/gateway/sandboxing) for the full guide and [full reference](/gateway/configuration-reference#agents-defaults-sandbox) for all options.
|
||||
See [Sandboxing](/gateway/sandboxing) for the full guide and [full reference](/gateway/configuration-reference#agentsdefaultssandbox) for all options.
|
||||
|
||||
</Accordion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ summary: "Logging surfaces, file logs, WS log styles, and console formatting"
|
||||
read_when:
|
||||
- Changing logging output or formats
|
||||
- Debugging CLI or gateway output
|
||||
title: "Logging"
|
||||
title: "Gateway Logging"
|
||||
---
|
||||
|
||||
# Logging
|
||||
|
||||
@@ -117,7 +117,7 @@ Gateway credential resolution follows one shared contract across call/probe/stat
|
||||
- password: `OPENCLAW_GATEWAY_PASSWORD` -> `gateway.remote.password` -> `gateway.auth.password`
|
||||
- Node-host local-mode exception: `gateway.remote.token` / `gateway.remote.password` are ignored.
|
||||
- Remote probe/status token checks are strict by default: they use `gateway.remote.token` only (no local token fallback) when targeting remote mode.
|
||||
- Legacy `CLAWDBOT_GATEWAY_*` env vars are only used by compatibility call paths; probe/status/auth resolution uses `OPENCLAW_GATEWAY_*` only.
|
||||
- Gateway env overrides use `OPENCLAW_GATEWAY_*` only.
|
||||
|
||||
## Chat UI over SSH
|
||||
|
||||
|
||||
@@ -402,7 +402,7 @@ Docker installs and the containerized gateway live here:
|
||||
For Docker gateway deployments, `scripts/docker/setup.sh` can bootstrap sandbox config.
|
||||
Set `OPENCLAW_SANDBOX=1` (or `true`/`yes`/`on`) to enable that path. You can
|
||||
override socket location with `OPENCLAW_DOCKER_SOCKET`. Full setup and env
|
||||
reference: [Docker](/install/docker#enable-agent-sandbox-for-docker-gateway-opt-in).
|
||||
reference: [Docker](/install/docker#enable-agent-sandbox-for-docker-gateway).
|
||||
|
||||
## setupCommand (one-time container setup)
|
||||
|
||||
@@ -463,7 +463,7 @@ See [Multi-Agent Sandbox & Tools](/tools/multi-agent-sandbox-tools) for preceden
|
||||
## Related docs
|
||||
|
||||
- [OpenShell](/gateway/openshell) -- managed sandbox backend setup, workspace modes, and config reference
|
||||
- [Sandbox Configuration](/gateway/configuration-reference#agents-defaults-sandbox)
|
||||
- [Sandbox Configuration](/gateway/configuration-reference#agentsdefaultssandbox)
|
||||
- [Sandbox vs Tool Policy vs Elevated](/gateway/sandbox-vs-tool-policy-vs-elevated) -- debugging "why is this blocked?"
|
||||
- [Multi-Agent Sandbox & Tools](/tools/multi-agent-sandbox-tools) -- per-agent overrides and precedence
|
||||
- [Security](/gateway/security)
|
||||
|
||||
@@ -51,7 +51,7 @@ Examples of inactive surfaces:
|
||||
- In local mode without those remote surfaces:
|
||||
- `gateway.remote.token` is active when token auth can win and no env/auth token is configured.
|
||||
- `gateway.remote.password` is active only when password auth can win and no env/auth password is configured.
|
||||
- `gateway.auth.token` SecretRef is inactive for startup auth resolution when `OPENCLAW_GATEWAY_TOKEN` (or `CLAWDBOT_GATEWAY_TOKEN`) is set, because env token input wins for that runtime.
|
||||
- `gateway.auth.token` SecretRef is inactive for startup auth resolution when `OPENCLAW_GATEWAY_TOKEN` is set, because env token input wins for that runtime.
|
||||
|
||||
## Gateway auth surface diagnostics
|
||||
|
||||
|
||||
@@ -259,6 +259,7 @@ High-signal `checkId` values you will most likely see in real deployments (not e
|
||||
| `tools.exec.auto_allow_skills_enabled` | warn | Exec approvals trust skill bins implicitly | `~/.openclaw/exec-approvals.json` | no |
|
||||
| `tools.exec.allowlist_interpreter_without_strict_inline_eval` | warn | Interpreter allowlists permit inline eval without forced reapproval | `tools.exec.strictInlineEval`, `agents.list[].tools.exec.strictInlineEval`, exec approvals allowlist | no |
|
||||
| `tools.exec.safe_bins_interpreter_unprofiled` | warn | Interpreter/runtime bins in `safeBins` without explicit profiles broaden exec risk | `tools.exec.safeBins`, `tools.exec.safeBinProfiles`, `agents.list[].tools.exec.*` | no |
|
||||
| `tools.exec.safe_bins_broad_behavior` | warn | Broad-behavior tools in `safeBins` weaken the low-risk stdin-filter trust model | `tools.exec.safeBins`, `agents.list[].tools.exec.safeBins` | no |
|
||||
| `skills.workspace.symlink_escape` | warn | Workspace `skills/**/SKILL.md` resolves outside workspace root (symlink-chain drift) | workspace `skills/**` filesystem state | no |
|
||||
| `security.exposure.open_channels_with_exec` | warn/critical | Shared/public rooms can reach exec-enabled agents | `channels.*.dmPolicy`, `channels.*.groupPolicy`, `tools.exec.*`, `agents.list[].tools.exec.*` | no |
|
||||
| `security.exposure.open_groups_with_elevated` | critical | Open groups + elevated tools create high-impact prompt-injection paths | `channels.*.groupPolicy`, `tools.elevated.*` | no |
|
||||
@@ -312,6 +313,8 @@ schema:
|
||||
- `channels.googlechat.dangerouslyAllowNameMatching`
|
||||
- `channels.googlechat.accounts.<accountId>.dangerouslyAllowNameMatching`
|
||||
- `channels.msteams.dangerouslyAllowNameMatching`
|
||||
- `channels.synology-chat.dangerouslyAllowNameMatching` (extension channel)
|
||||
- `channels.synology-chat.accounts.<accountId>.dangerouslyAllowNameMatching` (extension channel)
|
||||
- `channels.zalouser.dangerouslyAllowNameMatching` (extension channel)
|
||||
- `channels.irc.dangerouslyAllowNameMatching` (extension channel)
|
||||
- `channels.irc.accounts.<accountId>.dangerouslyAllowNameMatching` (extension channel)
|
||||
@@ -455,7 +458,7 @@ Plugins run **in-process** with the Gateway. Treat them as trusted code:
|
||||
- Prefer explicit `plugins.allow` allowlists.
|
||||
- Review plugin config before enabling.
|
||||
- Restart the Gateway after plugin changes.
|
||||
- If you install plugins from npm (`openclaw plugins install <npm-spec>`), treat it like running untrusted code:
|
||||
- If you install plugins (`openclaw plugins install <package>`), treat it like running untrusted code:
|
||||
- The install path is `~/.openclaw/extensions/<pluginId>/` (or `$OPENCLAW_STATE_DIR/extensions/<pluginId>/`).
|
||||
- OpenClaw uses `npm pack` and then runs `npm install --omit=dev` in that directory (npm lifecycle scripts can execute code during install).
|
||||
- Prefer pinned, exact versions (`@scope/pkg@1.2.3`), and inspect the unpacked code on disk before enabling.
|
||||
|
||||
@@ -267,7 +267,7 @@ Quick answers plus deeper troubleshooting for real-world setups (local dev, VPS,
|
||||
<Accordion title="Cannot access docs.openclaw.ai (SSL error)">
|
||||
Some Comcast/Xfinity connections incorrectly block `docs.openclaw.ai` via Xfinity
|
||||
Advanced Security. Disable it or allowlist `docs.openclaw.ai`, then retry. More
|
||||
detail: [Troubleshooting](/help/faq#docsopenclawai-shows-an-ssl-error-comcast-xfinity).
|
||||
detail: [Troubleshooting](/help/faq#cannot-access-docsopenclaw-ai-ssl-error).
|
||||
Please help us unblock it by reporting here: [https://spa.xfinity.com/check_url_status](https://spa.xfinity.com/check_url_status).
|
||||
|
||||
If you still can't reach the site, the docs are mirrored on GitHub:
|
||||
@@ -992,18 +992,16 @@ Quick answers plus deeper troubleshooting for real-world setups (local dev, VPS,
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How do I install skills on Linux?">
|
||||
Use **ClawHub** (CLI) or drop skills into your workspace. The macOS Skills UI isn't available on Linux.
|
||||
Use native `openclaw skills` commands or drop skills into your workspace. The macOS Skills UI isn't available on Linux.
|
||||
Browse skills at [https://clawhub.com](https://clawhub.com).
|
||||
|
||||
Install the ClawHub CLI (pick one package manager):
|
||||
|
||||
```bash
|
||||
npm i -g clawhub
|
||||
openclaw skills search "calendar"
|
||||
openclaw skills install <skill-slug>
|
||||
openclaw skills update --all
|
||||
```
|
||||
|
||||
```bash
|
||||
pnpm add -g clawhub
|
||||
```
|
||||
Install the separate `clawhub` CLI only if you want to publish or sync your own skills.
|
||||
|
||||
</Accordion>
|
||||
|
||||
@@ -1075,11 +1073,11 @@ Quick answers plus deeper troubleshooting for real-world setups (local dev, VPS,
|
||||
Install skills:
|
||||
|
||||
```bash
|
||||
clawhub install <skill-slug>
|
||||
clawhub update --all
|
||||
openclaw skills install <skill-slug>
|
||||
openclaw skills update --all
|
||||
```
|
||||
|
||||
ClawHub installs into `./skills` under your current directory (or falls back to your configured OpenClaw workspace); OpenClaw treats that as `<workspace>/skills` on the next session. For shared skills across agents, place them in `~/.openclaw/skills/<name>/SKILL.md`. Some skills expect binaries installed via Homebrew; on Linux that means Linuxbrew (see the Homebrew Linux FAQ entry above). See [Skills](/tools/skills) and [ClawHub](/tools/clawhub).
|
||||
Native installs land in the active workspace `skills/` directory. For shared skills across agents, place them in `~/.openclaw/skills/<name>/SKILL.md`. Some skills expect binaries installed via Homebrew; on Linux that means Linuxbrew (see the Homebrew Linux FAQ entry above). See [Skills](/tools/skills) and [ClawHub](/tools/clawhub).
|
||||
|
||||
</Accordion>
|
||||
|
||||
@@ -1131,7 +1129,7 @@ Quick answers plus deeper troubleshooting for real-world setups (local dev, VPS,
|
||||
|
||||
Setup walkthrough + example config: [Groups: personal DMs + public groups](/channels/groups#pattern-personal-dms-public-groups-single-agent)
|
||||
|
||||
Key config reference: [Gateway configuration](/gateway/configuration-reference#agents-defaults-sandbox)
|
||||
Key config reference: [Gateway configuration](/gateway/configuration-reference#agentsdefaultssandbox)
|
||||
|
||||
</Accordion>
|
||||
|
||||
@@ -2148,12 +2146,11 @@ Quick answers plus deeper troubleshooting for real-world setups (local dev, VPS,
|
||||
|
||||
<Accordion title='Why do I see "Unknown model: minimax/MiniMax-M2.7"?'>
|
||||
This means the **provider isn't configured** (no MiniMax provider config or auth
|
||||
profile was found), so the model can't be resolved. A fix for this detection is
|
||||
in **2026.1.12** (unreleased at the time of writing).
|
||||
profile was found), so the model can't be resolved.
|
||||
|
||||
Fix checklist:
|
||||
|
||||
1. Upgrade to **2026.1.12** (or run from source `main`), then restart the gateway.
|
||||
1. Upgrade to a current OpenClaw release (or run from source `main`), then restart the gateway.
|
||||
2. Make sure MiniMax is configured (wizard or JSON), or that a MiniMax API key
|
||||
exists in env/auth profiles so the provider can be injected.
|
||||
3. Use the exact model id (case-sensitive): `minimax/MiniMax-M2.7`,
|
||||
|
||||
@@ -54,7 +54,10 @@ Think of the suites as “increasing realism” (and increasing flakiness/cost):
|
||||
- Should be fast and stable
|
||||
- Scheduler note:
|
||||
- `pnpm test` now keeps a small checked-in behavioral manifest for true pool/isolation overrides and a separate timing snapshot for the slowest unit files.
|
||||
- Shared unit coverage stays on, but the wrapper peels the heaviest measured files into dedicated lanes instead of relying on a growing hand-maintained exclusion list.
|
||||
- Shared unit coverage now defaults to `threads`, while the manifest keeps the measured fork-only exceptions and heavy singleton lanes explicit.
|
||||
- The shared extension lane still defaults to `threads`; the wrapper keeps explicit fork-only exceptions in `test/fixtures/test-parallel.behavior.json` when a file cannot safely share a non-isolated worker.
|
||||
- The channel suite (`vitest.channels.config.ts`) now also defaults to `threads`; the March 22, 2026 direct full-suite control run passed clean without channel-specific fork exceptions.
|
||||
- The wrapper peels the heaviest measured files into dedicated lanes instead of relying on a growing hand-maintained exclusion list.
|
||||
- Refresh the timing snapshot with `pnpm test:perf:update-timings` after major suite shape changes.
|
||||
- Embedded runner note:
|
||||
- When you change message-tool discovery inputs or compaction runtime context,
|
||||
@@ -68,9 +71,24 @@ Think of the suites as “increasing realism” (and increasing flakiness/cost):
|
||||
through the real `run.ts` / `compact.ts` paths; helper-only tests are not a
|
||||
sufficient substitute for those integration paths.
|
||||
- Pool note:
|
||||
- OpenClaw uses Vitest `vmForks` on Node 22, 23, and 24 for faster unit shards.
|
||||
- On Node 25+, OpenClaw automatically falls back to regular `forks` until the repo is re-validated there.
|
||||
- Override manually with `OPENCLAW_TEST_VM_FORKS=0` (force `forks`) or `OPENCLAW_TEST_VM_FORKS=1` (force `vmForks`).
|
||||
- Base Vitest config still defaults to `forks`.
|
||||
- Unit wrapper lanes default to `threads`, with explicit manifest fork-only exceptions.
|
||||
- Extension scoped config defaults to `threads`.
|
||||
- Channel scoped config defaults to `threads`.
|
||||
- Unit, channel, and extension configs default to `isolate: false` for faster file startup.
|
||||
- `pnpm test` also passes `--isolate=false` at the wrapper level.
|
||||
- Opt back into Vitest file isolation with `OPENCLAW_TEST_ISOLATE=1 pnpm test`.
|
||||
- `OPENCLAW_TEST_NO_ISOLATE=0` or `OPENCLAW_TEST_NO_ISOLATE=false` also force isolated runs.
|
||||
- Fast-local iteration note:
|
||||
- `pnpm test:changed` runs the wrapper with `--changed origin/main`.
|
||||
- The base Vitest config marks the wrapper manifests/config files as `forceRerunTriggers` so changed-mode reruns stay correct when scheduler inputs change.
|
||||
- Vitest's filesystem module cache is now enabled by default for Node-side test reruns.
|
||||
- Opt out with `OPENCLAW_VITEST_FS_MODULE_CACHE=0` or `OPENCLAW_VITEST_FS_MODULE_CACHE=false` if you suspect stale transform cache behavior.
|
||||
- Perf-debug note:
|
||||
- `pnpm test:perf:imports` enables Vitest import-duration reporting plus import-breakdown output.
|
||||
- `pnpm test:perf:imports:changed` scopes the same profiling view to files changed since `origin/main`.
|
||||
- `pnpm test:perf:profile:main` writes a main-thread CPU profile for Vitest/Vite startup and transform overhead.
|
||||
- `pnpm test:perf:profile:runner` writes runner CPU+heap profiles for the unit suite with file parallelism disabled.
|
||||
|
||||
### E2E (gateway smoke)
|
||||
|
||||
@@ -78,8 +96,8 @@ Think of the suites as “increasing realism” (and increasing flakiness/cost):
|
||||
- Config: `vitest.e2e.config.ts`
|
||||
- Files: `src/**/*.e2e.test.ts`, `test/**/*.e2e.test.ts`
|
||||
- Runtime defaults:
|
||||
- Uses Vitest `vmForks` for faster file startup.
|
||||
- Uses adaptive workers (CI: 2-4, local: 4-8).
|
||||
- Uses Vitest `forks` for deterministic cross-file isolation.
|
||||
- Uses adaptive workers (CI: up to 2, local: 1 by default).
|
||||
- Runs in silent mode by default to reduce console I/O overhead.
|
||||
- Useful overrides:
|
||||
- `OPENCLAW_E2E_WORKERS=<n>` to force worker count (capped at 16).
|
||||
@@ -124,6 +142,11 @@ Think of the suites as “increasing realism” (and increasing flakiness/cost):
|
||||
- Prefer running narrowed subsets instead of “everything”
|
||||
- Live runs will source `~/.profile` to pick up missing API keys
|
||||
- API key rotation (provider-specific): set `*_API_KEYS` with comma/semicolon format or `*_API_KEY_1`, `*_API_KEY_2` (for example `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`) or per-live override via `OPENCLAW_LIVE_*_KEY`; tests retry on rate limit responses.
|
||||
- Progress/heartbeat output:
|
||||
- Live suites now emit progress lines to stderr so long provider calls are visibly active even when Vitest console capture is quiet.
|
||||
- `vitest.live.config.ts` disables Vitest console interception so provider/gateway progress lines stream immediately during live runs.
|
||||
- Tune direct-model heartbeats with `OPENCLAW_LIVE_HEARTBEAT_MS`.
|
||||
- Tune gateway/probe heartbeats with `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS`.
|
||||
|
||||
## Which suite should I run?
|
||||
|
||||
@@ -168,7 +191,7 @@ Live tests are split into two layers so we can isolate failures:
|
||||
- `pnpm test:live` (or `OPENCLAW_LIVE_TEST=1` if invoking Vitest directly)
|
||||
- Set `OPENCLAW_LIVE_MODELS=modern` (or `all`, alias for modern) to actually run this suite; otherwise it skips to keep `pnpm test:live` focused on gateway smoke
|
||||
- How to select models:
|
||||
- `OPENCLAW_LIVE_MODELS=modern` to run the modern allowlist (Opus/Sonnet/Haiku 4.5, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.5, Grok 4)
|
||||
- `OPENCLAW_LIVE_MODELS=modern` to run the modern allowlist (Opus/Sonnet/Haiku 4.5, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4)
|
||||
- `OPENCLAW_LIVE_MODELS=all` is an alias for the modern allowlist
|
||||
- or `OPENCLAW_LIVE_MODELS="openai/gpt-5.2,anthropic/claude-opus-4-6,..."` (comma allowlist)
|
||||
- How to select providers:
|
||||
@@ -199,7 +222,7 @@ Live tests are split into two layers so we can isolate failures:
|
||||
- How to enable:
|
||||
- `pnpm test:live` (or `OPENCLAW_LIVE_TEST=1` if invoking Vitest directly)
|
||||
- How to select models:
|
||||
- Default: modern allowlist (Opus/Sonnet/Haiku 4.5, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.5, Grok 4)
|
||||
- Default: modern allowlist (Opus/Sonnet/Haiku 4.5, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4)
|
||||
- `OPENCLAW_LIVE_GATEWAY_MODELS=all` is an alias for the modern allowlist
|
||||
- Or set `OPENCLAW_LIVE_GATEWAY_MODELS="provider/model"` (or comma list) to narrow
|
||||
- How to select providers (avoid “OpenRouter everything”):
|
||||
@@ -283,7 +306,7 @@ Narrow, explicit allowlists are fastest and least flaky:
|
||||
- `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.2" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
|
||||
|
||||
- Tool calling across several providers:
|
||||
- `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.2,anthropic/claude-opus-4-6,google/gemini-3-flash-preview,zai/glm-4.7,minimax/minimax-m2.5" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
|
||||
- `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.2,anthropic/claude-opus-4-6,google/gemini-3-flash-preview,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
|
||||
|
||||
- Google focus (Gemini API key + Antigravity):
|
||||
- Gemini (API key): `OPENCLAW_LIVE_GATEWAY_MODELS="google/gemini-3-flash-preview" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
|
||||
@@ -312,10 +335,10 @@ This is the “common models” run we expect to keep working:
|
||||
- Google (Gemini API): `google/gemini-3.1-pro-preview` and `google/gemini-3-flash-preview` (avoid older Gemini 2.x models)
|
||||
- Google (Antigravity): `google-antigravity/claude-opus-4-6-thinking` and `google-antigravity/gemini-3-flash`
|
||||
- Z.AI (GLM): `zai/glm-4.7`
|
||||
- MiniMax: `minimax/minimax-m2.5`
|
||||
- MiniMax: `minimax/MiniMax-M2.7`
|
||||
|
||||
Run gateway smoke with tools + image:
|
||||
`OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.2,openai-codex/gpt-5.4,anthropic/claude-opus-4-6,google/gemini-3.1-pro-preview,google/gemini-3-flash-preview,google-antigravity/claude-opus-4-6-thinking,google-antigravity/gemini-3-flash,zai/glm-4.7,minimax/minimax-m2.5" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
|
||||
`OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.2,openai-codex/gpt-5.4,anthropic/claude-opus-4-6,google/gemini-3.1-pro-preview,google/gemini-3-flash-preview,google-antigravity/claude-opus-4-6-thinking,google-antigravity/gemini-3-flash,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
|
||||
|
||||
### Baseline: tool calling (Read + optional Exec)
|
||||
|
||||
@@ -325,7 +348,7 @@ Pick at least one per provider family:
|
||||
- Anthropic: `anthropic/claude-opus-4-6` (or `anthropic/claude-sonnet-4-6`)
|
||||
- Google: `google/gemini-3-flash-preview` (or `google/gemini-3.1-pro-preview`)
|
||||
- Z.AI (GLM): `zai/glm-4.7`
|
||||
- MiniMax: `minimax/minimax-m2.5`
|
||||
- MiniMax: `minimax/MiniMax-M2.7`
|
||||
|
||||
Optional additional coverage (nice to have):
|
||||
|
||||
@@ -401,17 +424,19 @@ If you want to rely on env keys (e.g. exported in your `~/.profile`), run local
|
||||
|
||||
## Docker runners (optional "works in Linux" checks)
|
||||
|
||||
These run `pnpm test:live` inside the repo Docker image, mounting your local config dir and workspace (and sourcing `~/.profile` if mounted). They also bind-mount CLI auth homes like `~/.codex`, `~/.claude`, `~/.qwen`, and `~/.minimax` when present, then copy them into the container home before the run so external-CLI OAuth can refresh tokens without mutating the host auth store:
|
||||
These run `pnpm test:live` inside the repo Docker image, mounting your local config dir and workspace (and sourcing `~/.profile` if mounted). They also bind-mount only the needed CLI auth homes (or all supported ones when the run is not narrowed), then copy them into the container home before the run so external-CLI OAuth can refresh tokens without mutating the host auth store:
|
||||
|
||||
- Direct models: `pnpm test:docker:live-models` (script: `scripts/test-live-models-docker.sh`)
|
||||
- Gateway + dev agent: `pnpm test:docker:live-gateway` (script: `scripts/test-live-gateway-models-docker.sh`)
|
||||
- Onboarding wizard (TTY, full scaffolding): `pnpm test:docker:onboard` (script: `scripts/e2e/onboard-docker.sh`)
|
||||
- Gateway networking (two containers, WS auth + health): `pnpm test:docker:gateway-network` (script: `scripts/e2e/gateway-network-docker.sh`)
|
||||
- Plugins (custom extension load + registry smoke): `pnpm test:docker:plugins` (script: `scripts/e2e/plugins-docker.sh`)
|
||||
- Plugins (install smoke + `/plugin` alias + Claude-bundle restart semantics): `pnpm test:docker:plugins` (script: `scripts/e2e/plugins-docker.sh`)
|
||||
|
||||
The live-model Docker runners also bind-mount the current checkout read-only and
|
||||
stage it into a temporary workdir inside the container. This keeps the runtime
|
||||
image slim while still running Vitest against your exact local source/config.
|
||||
They also set `OPENCLAW_SKIP_CHANNELS=1` so gateway live probes do not start
|
||||
real Telegram/Discord/etc. channel workers inside the container.
|
||||
`test:docker:live-models` still runs `pnpm test:live`, so pass through
|
||||
`OPENCLAW_LIVE_GATEWAY_*` as well when you need to narrow or exclude gateway
|
||||
live coverage from that Docker lane.
|
||||
@@ -426,7 +451,10 @@ Useful env vars:
|
||||
- `OPENCLAW_CONFIG_DIR=...` (default: `~/.openclaw`) mounted to `/home/node/.openclaw`
|
||||
- `OPENCLAW_WORKSPACE_DIR=...` (default: `~/.openclaw/workspace`) mounted to `/home/node/.openclaw/workspace`
|
||||
- `OPENCLAW_PROFILE_FILE=...` (default: `~/.profile`) mounted to `/home/node/.profile` and sourced before running tests
|
||||
- External CLI auth dirs under `$HOME` (`.codex`, `.claude`, `.qwen`, `.minimax`) are mounted read-only under `/host-auth/...`, then copied into `/home/node/...` before tests start
|
||||
- External CLI auth dirs under `$HOME` are mounted read-only under `/host-auth/...`, then copied into `/home/node/...` before tests start
|
||||
- Default: mount all supported dirs (`.codex`, `.claude`, `.qwen`, `.minimax`)
|
||||
- Narrowed provider runs mount only the needed dirs inferred from `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS`
|
||||
- Override manually with `OPENCLAW_DOCKER_AUTH_DIRS=all`, `OPENCLAW_DOCKER_AUTH_DIRS=none`, or a comma list like `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex`
|
||||
- `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...` to narrow the run
|
||||
- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` to filter providers in-container
|
||||
- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` to ensure creds come from the profile store (not env)
|
||||
|
||||
@@ -49,7 +49,7 @@ Fix in the plugin package:
|
||||
|
||||
1. Add `openclaw.extensions` to `package.json`.
|
||||
2. Point entries at built runtime files (usually `./dist/index.js`).
|
||||
3. Republish the plugin and run `openclaw plugins install <npm-spec>` again.
|
||||
3. Republish the plugin and run `openclaw plugins install <package>` again.
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ title: "Azure"
|
||||
|
||||
This guide sets up an Azure Linux VM with the Azure CLI, applies Network Security Group (NSG) hardening, configures Azure Bastion for SSH access, and installs OpenClaw.
|
||||
|
||||
## What you'll do
|
||||
## What you will do
|
||||
|
||||
- Create Azure networking (VNet, subnets, NSG) and compute resources with the Azure CLI
|
||||
- Apply Network Security Group rules so VM SSH is allowed only from Azure Bastion
|
||||
|
||||
@@ -48,7 +48,7 @@ update **without** changing your persisted channel:
|
||||
|
||||
```bash
|
||||
# Install a specific version
|
||||
openclaw update --tag 2026.3.14
|
||||
openclaw update --tag 2026.3.22
|
||||
|
||||
# Install from the beta dist-tag (one-off, does not persist)
|
||||
openclaw update --tag beta
|
||||
@@ -57,7 +57,7 @@ openclaw update --tag beta
|
||||
openclaw update --tag main
|
||||
|
||||
# Install a specific npm package spec
|
||||
openclaw update --tag openclaw@2026.3.12
|
||||
openclaw update --tag openclaw@2026.3.22
|
||||
```
|
||||
|
||||
Notes:
|
||||
@@ -75,7 +75,7 @@ Preview what `openclaw update` would do without making changes:
|
||||
```bash
|
||||
openclaw update --dry-run
|
||||
openclaw update --channel beta --dry-run
|
||||
openclaw update --tag 2026.3.14 --dry-run
|
||||
openclaw update --tag 2026.3.22 --dry-run
|
||||
openclaw update --dry-run --json
|
||||
```
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ Docker is **optional**. Use it only if you want a containerized gateway or to va
|
||||
- At least 2 GB RAM for image build (`pnpm install` may be OOM-killed on 1 GB hosts with exit 137)
|
||||
- Enough disk for images and logs
|
||||
- If running on a VPS/public host, review
|
||||
[Security hardening for network exposure](/gateway/security#0-4-network-exposure-bind-port-firewall),
|
||||
[Security hardening for network exposure](/gateway/security),
|
||||
especially Docker `DOCKER-USER` firewall policy.
|
||||
|
||||
## Containerized Gateway
|
||||
|
||||
@@ -2,46 +2,32 @@
|
||||
summary: "Deploy OpenClaw on Northflank with one-click template"
|
||||
read_when:
|
||||
- Deploying OpenClaw to Northflank
|
||||
- You want a one-click cloud deploy with browser-based setup
|
||||
- You want a one-click cloud deploy with browser-based Control UI
|
||||
title: "Northflank"
|
||||
---
|
||||
|
||||
Deploy OpenClaw on Northflank with a one-click template and finish setup in your browser.
|
||||
This is the easiest “no terminal on the server” path: Northflank runs the Gateway for you,
|
||||
and you configure everything via the `/setup` web wizard.
|
||||
Deploy OpenClaw on Northflank with a one-click template and access it through the web Control UI.
|
||||
This is the easiest "no terminal on the server" path: Northflank runs the Gateway for you.
|
||||
|
||||
## How to get started
|
||||
|
||||
1. Click [Deploy OpenClaw](https://northflank.com/stacks/deploy-openclaw) to open the template.
|
||||
2. Create an [account on Northflank](https://app.northflank.com/signup) if you don’t already have one.
|
||||
2. Create an [account on Northflank](https://app.northflank.com/signup) if you don't already have one.
|
||||
3. Click **Deploy OpenClaw now**.
|
||||
4. Set the required environment variable: `SETUP_PASSWORD`.
|
||||
4. Set the required environment variable: `OPENCLAW_GATEWAY_TOKEN` (use a strong random value).
|
||||
5. Click **Deploy stack** to build and run the OpenClaw template.
|
||||
6. Wait for the deployment to complete, then click **View resources**.
|
||||
7. Open the OpenClaw service.
|
||||
8. Open the public OpenClaw URL and complete setup at `/setup`.
|
||||
9. Open the Control UI at `/openclaw`.
|
||||
8. Open the public OpenClaw URL at `/openclaw` and connect using your `OPENCLAW_GATEWAY_TOKEN`.
|
||||
|
||||
## What you get
|
||||
|
||||
- Hosted OpenClaw Gateway + Control UI
|
||||
- Web setup at `/setup` (no terminal commands)
|
||||
- Persistent storage via Northflank Volume (`/data`) so config/credentials/workspace survive redeploys
|
||||
|
||||
## Setup flow
|
||||
|
||||
1. Visit `https://<your-northflank-domain>/setup` and enter your `SETUP_PASSWORD`.
|
||||
2. Choose a model/auth provider and paste your key.
|
||||
3. (Optional) Add Telegram/Discord/Slack tokens.
|
||||
4. Click **Run setup**.
|
||||
5. Open the Control UI at `https://<your-northflank-domain>/openclaw`
|
||||
|
||||
If Telegram DMs are set to pairing, web setup can approve the pairing code.
|
||||
|
||||
## Connect a channel
|
||||
|
||||
Paste your Telegram or Discord token into the `/setup` wizard. For setup
|
||||
instructions, see the channel docs:
|
||||
Use the Control UI at `/openclaw` or run `openclaw onboard` via SSH for channel setup instructions:
|
||||
|
||||
- [Telegram](/channels/telegram) (fastest — just a bot token)
|
||||
- [Discord](/channels/discord)
|
||||
|
||||
@@ -2,21 +2,20 @@
|
||||
summary: "Deploy OpenClaw on Railway with one-click template"
|
||||
read_when:
|
||||
- Deploying OpenClaw to Railway
|
||||
- You want a one-click cloud deploy with browser-based setup
|
||||
- You want a one-click cloud deploy with browser-based Control UI
|
||||
title: "Railway"
|
||||
---
|
||||
|
||||
Deploy OpenClaw on Railway with a one-click template and finish setup in your browser.
|
||||
This is the easiest “no terminal on the server” path: Railway runs the Gateway for you,
|
||||
and you configure everything via the `/setup` web wizard.
|
||||
Deploy OpenClaw on Railway with a one-click template and access it through the web Control UI.
|
||||
This is the easiest "no terminal on the server" path: Railway runs the Gateway for you.
|
||||
|
||||
## Quick checklist (new users)
|
||||
|
||||
1. Click **Deploy on Railway** (below).
|
||||
2. Add a **Volume** mounted at `/data`.
|
||||
3. Set the required **Variables** (at least `SETUP_PASSWORD`).
|
||||
3. Set the required **Variables** (at least `OPENCLAW_GATEWAY_PORT` and `OPENCLAW_GATEWAY_TOKEN`).
|
||||
4. Enable **HTTP Proxy** on port `8080`.
|
||||
5. Open `https://<your-railway-domain>/setup` and finish the wizard.
|
||||
5. Open `https://<your-railway-domain>/openclaw` and connect using your `OPENCLAW_GATEWAY_TOKEN`.
|
||||
|
||||
## One-click deploy
|
||||
|
||||
@@ -33,15 +32,12 @@ Railway will either:
|
||||
|
||||
Then open:
|
||||
|
||||
- `https://<your-railway-domain>/setup` — web setup (password protected)
|
||||
- `https://<your-railway-domain>/openclaw` — Control UI
|
||||
|
||||
## What you get
|
||||
|
||||
- Hosted OpenClaw Gateway + Control UI
|
||||
- Web setup at `/setup` (no terminal commands)
|
||||
- Persistent storage via Railway Volume (`/data`) so config/credentials/workspace survive redeploys
|
||||
- Backup export at `/setup/export` to migrate off Railway later
|
||||
|
||||
## Required Railway settings
|
||||
|
||||
@@ -61,25 +57,14 @@ Attach a volume mounted at:
|
||||
|
||||
Set these variables on the service:
|
||||
|
||||
- `SETUP_PASSWORD` (required)
|
||||
- `PORT=8080` (required — must match the port in Public Networking)
|
||||
- `OPENCLAW_GATEWAY_PORT=8080` (required — must match the port in Public Networking)
|
||||
- `OPENCLAW_GATEWAY_TOKEN` (required; treat as an admin secret)
|
||||
- `OPENCLAW_STATE_DIR=/data/.openclaw` (recommended)
|
||||
- `OPENCLAW_WORKSPACE_DIR=/data/workspace` (recommended)
|
||||
- `OPENCLAW_GATEWAY_TOKEN` (recommended; treat as an admin secret)
|
||||
|
||||
## Setup flow
|
||||
|
||||
1. Visit `https://<your-railway-domain>/setup` and enter your `SETUP_PASSWORD`.
|
||||
2. Choose a model/auth provider and paste your key.
|
||||
3. (Optional) Add Telegram/Discord/Slack tokens.
|
||||
4. Click **Run setup**.
|
||||
|
||||
If Telegram DMs are set to pairing, web setup can approve the pairing code.
|
||||
|
||||
## Connect a channel
|
||||
|
||||
Paste your Telegram or Discord token into the `/setup` wizard. For setup
|
||||
instructions, see the channel docs:
|
||||
Use the Control UI at `/openclaw` or run `openclaw onboard` via Railway's shell for channel setup instructions:
|
||||
|
||||
- [Telegram](/channels/telegram) (fastest — just a bot token)
|
||||
- [Discord](/channels/discord)
|
||||
@@ -87,11 +72,13 @@ instructions, see the channel docs:
|
||||
|
||||
## Backups & migration
|
||||
|
||||
Download a backup at:
|
||||
Export your configuration and workspace:
|
||||
|
||||
- `https://<your-railway-domain>/setup/export`
|
||||
```bash
|
||||
openclaw backup create
|
||||
```
|
||||
|
||||
This exports your OpenClaw state + workspace so you can migrate to another host without losing config or memory.
|
||||
This creates a portable backup archive you can restore on any OpenClaw host. See [Backup](/cli/backup) for details.
|
||||
|
||||
## Next steps
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@ Deploy OpenClaw on Render using Infrastructure as Code. The included `render.yam
|
||||
Clicking this link will:
|
||||
|
||||
1. Create a new Render service from the `render.yaml` Blueprint at the root of this repo.
|
||||
2. Prompt you to set `SETUP_PASSWORD`
|
||||
3. Build the Docker image and deploy
|
||||
2. Build the Docker image and deploy
|
||||
|
||||
Once deployed, your service URL follows the pattern `https://<service-name>.onrender.com`.
|
||||
|
||||
@@ -38,10 +37,8 @@ services:
|
||||
plan: starter
|
||||
healthCheckPath: /health
|
||||
envVars:
|
||||
- key: PORT
|
||||
- key: OPENCLAW_GATEWAY_PORT
|
||||
value: "8080"
|
||||
- key: SETUP_PASSWORD
|
||||
sync: false # prompts during deploy
|
||||
- key: OPENCLAW_STATE_DIR
|
||||
value: /data/.openclaw
|
||||
- key: OPENCLAW_WORKSPACE_DIR
|
||||
@@ -60,7 +57,6 @@ Key Blueprint features used:
|
||||
| --------------------- | ---------------------------------------------------------- |
|
||||
| `runtime: docker` | Builds from the repo's Dockerfile |
|
||||
| `healthCheckPath` | Render monitors `/health` and restarts unhealthy instances |
|
||||
| `sync: false` | Prompts for value during deploy (secrets) |
|
||||
| `generateValue: true` | Auto-generates a cryptographically secure value |
|
||||
| `disk` | Persistent storage that survives redeploys |
|
||||
|
||||
@@ -77,17 +73,11 @@ The Blueprint defaults to `starter`. To use free tier, change `plan: free` in yo
|
||||
|
||||
## After deployment
|
||||
|
||||
### Complete web setup
|
||||
|
||||
1. Navigate to `https://<your-service>.onrender.com/setup`
|
||||
2. Enter your `SETUP_PASSWORD`
|
||||
3. Select a model provider and paste your API key
|
||||
4. Optionally configure messaging channels (Telegram, Discord, Slack)
|
||||
5. Click **Run setup**
|
||||
|
||||
### Access the Control UI
|
||||
|
||||
The web dashboard is available at `https://<your-service>.onrender.com/openclaw`.
|
||||
The web dashboard is available at `https://<your-service>.onrender.com/`.
|
||||
|
||||
Connect using the `OPENCLAW_GATEWAY_TOKEN` value that was auto-generated during deploy (find it in **Dashboard → your service → Environment**).
|
||||
|
||||
## Render Dashboard features
|
||||
|
||||
@@ -129,13 +119,13 @@ For OpenClaw, vertical scaling is usually sufficient. Horizontal scaling require
|
||||
|
||||
## Backups and migration
|
||||
|
||||
Export your configuration and workspace at any time:
|
||||
Export your configuration and workspace at any time using the shell access in the Render Dashboard:
|
||||
|
||||
```
|
||||
https://<your-service>.onrender.com/setup/export
|
||||
```bash
|
||||
openclaw backup create
|
||||
```
|
||||
|
||||
This downloads a portable backup you can restore on any OpenClaw host.
|
||||
This creates a portable backup archive you can restore on any OpenClaw host. See [Backup](/cli/backup) for details.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -143,8 +133,8 @@ This downloads a portable backup you can restore on any OpenClaw host.
|
||||
|
||||
Check the deploy logs in the Render Dashboard. Common issues:
|
||||
|
||||
- Missing `SETUP_PASSWORD` — the Blueprint prompts for this, but verify it's set
|
||||
- Port mismatch — ensure `PORT=8080` matches the Dockerfile's exposed port
|
||||
- Missing `OPENCLAW_GATEWAY_TOKEN` — verify it is set in **Dashboard → Environment**
|
||||
- Port mismatch — ensure `OPENCLAW_GATEWAY_PORT=8080` is set so the gateway binds to the port Render expects
|
||||
|
||||
### Slow cold starts (free tier)
|
||||
|
||||
@@ -153,7 +143,7 @@ Free tier services spin down after 15 minutes of inactivity. The first request a
|
||||
### Data loss after redeploy
|
||||
|
||||
This happens on free tier (no persistent disk). Upgrade to a paid plan, or
|
||||
regularly export your config via `/setup/export`.
|
||||
regularly export your config via `openclaw backup create` in the Render shell.
|
||||
|
||||
### Health check failures
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ read_when:
|
||||
- You need a beginner-friendly overview of logging
|
||||
- You want to configure log levels or formats
|
||||
- You are troubleshooting and need to find logs quickly
|
||||
title: "Logging"
|
||||
title: "Logging Overview"
|
||||
---
|
||||
|
||||
# Logging
|
||||
|
||||
@@ -25,7 +25,7 @@ The WhatsApp channel runs via **Baileys Web**. This document captures the curren
|
||||
|
||||
- Input: local file path **or** HTTP(S) URL.
|
||||
- Flow: load into a Buffer, detect media kind, and build the correct payload:
|
||||
- **Images:** resize & recompress to JPEG (max side 2048px) targeting `agents.defaults.mediaMaxMb` (default 5 MB), capped at 6 MB.
|
||||
- **Images:** resize & recompress to JPEG (max side 2048px) targeting `channels.whatsapp.mediaMaxMb` (default: 50 MB).
|
||||
- **Audio/Voice/Video:** pass-through up to 16 MB; audio is sent as a voice note (`ptt: true`).
|
||||
- **Documents:** anything else, up to 100 MB, with filename preserved when available.
|
||||
- WhatsApp GIF-style playback: send an MP4 with `gifPlayback: true` (CLI: `--gif-playback`) so mobile clients loop inline.
|
||||
@@ -54,7 +54,7 @@ The WhatsApp channel runs via **Baileys Web**. This document captures the curren
|
||||
|
||||
**Outbound send caps (WhatsApp web send)**
|
||||
|
||||
- Images: ~6 MB cap after recompression.
|
||||
- Images: up to `channels.whatsapp.mediaMaxMb` (default: 50 MB) after recompression.
|
||||
- Audio/voice/video: 16 MB cap; documents: 100 MB cap.
|
||||
- Oversize or unreadable media → clear error in logs and the reply is skipped.
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ Notes:
|
||||
- In local mode, node host intentionally ignores `gateway.remote.token` / `gateway.remote.password`.
|
||||
- In remote mode, `gateway.remote.token` / `gateway.remote.password` are eligible per remote precedence rules.
|
||||
- If active local `gateway.auth.*` SecretRefs are configured but unresolved, node-host auth fails closed.
|
||||
- Legacy `CLAWDBOT_GATEWAY_*` env vars are intentionally ignored by node-host auth resolution.
|
||||
- Node-host auth resolution only honors `OPENCLAW_GATEWAY_*` env vars.
|
||||
|
||||
### Start a node host (service)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ summary: "Perplexity Search API and Sonar/OpenRouter compatibility for web_searc
|
||||
read_when:
|
||||
- You want to use Perplexity Search for web search
|
||||
- You need PERPLEXITY_API_KEY or OPENROUTER_API_KEY setup
|
||||
title: "Perplexity Search"
|
||||
title: "Perplexity Search (legacy path)"
|
||||
---
|
||||
|
||||
# Perplexity Search API
|
||||
@@ -91,7 +91,7 @@ That field also accepts SecretRef objects.
|
||||
|
||||
**Via environment:** set `PERPLEXITY_API_KEY` or `OPENROUTER_API_KEY`
|
||||
in the Gateway process environment. For a gateway install, put it in
|
||||
`~/.openclaw/.env` (or your service environment). See [Env vars](/help/faq#how-does-openclaw-load-environment-variables).
|
||||
`~/.openclaw/.env` (or your service environment). See [Env vars](/help/faq#env-vars-and-env-loading).
|
||||
|
||||
If `provider: "perplexity"` is configured and the Perplexity key SecretRef is unresolved with no env fallback, startup/reload fails fast.
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@ OpenClaw uses the pi SDK to embed an AI coding agent into its messaging gateway
|
||||
|
||||
```json
|
||||
{
|
||||
"@mariozechner/pi-agent-core": "0.49.3",
|
||||
"@mariozechner/pi-ai": "0.49.3",
|
||||
"@mariozechner/pi-coding-agent": "0.49.3",
|
||||
"@mariozechner/pi-tui": "0.49.3"
|
||||
"@mariozechner/pi-agent-core": "0.61.1",
|
||||
"@mariozechner/pi-ai": "0.61.1",
|
||||
"@mariozechner/pi-coding-agent": "0.61.1",
|
||||
"@mariozechner/pi-tui": "0.61.1"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ summary: "OpenClaw on DigitalOcean (simple paid VPS option)"
|
||||
read_when:
|
||||
- Setting up OpenClaw on DigitalOcean
|
||||
- Looking for cheap VPS hosting for OpenClaw
|
||||
title: "DigitalOcean"
|
||||
title: "DigitalOcean (Platform)"
|
||||
---
|
||||
|
||||
# OpenClaw on DigitalOcean
|
||||
|
||||
@@ -4,7 +4,7 @@ read_when:
|
||||
- Setting up OpenClaw on Oracle Cloud
|
||||
- Looking for low-cost VPS hosting for OpenClaw
|
||||
- Want 24/7 OpenClaw on a small server
|
||||
title: "Oracle Cloud"
|
||||
title: "Oracle Cloud (Platform)"
|
||||
---
|
||||
|
||||
# OpenClaw on Oracle Cloud (OCI)
|
||||
|
||||
@@ -4,7 +4,7 @@ read_when:
|
||||
- Setting up OpenClaw on a Raspberry Pi
|
||||
- Running OpenClaw on ARM devices
|
||||
- Building a cheap always-on personal AI
|
||||
title: "Raspberry Pi"
|
||||
title: "Raspberry Pi (Platform)"
|
||||
---
|
||||
|
||||
# OpenClaw on Raspberry Pi
|
||||
|
||||
@@ -12,9 +12,12 @@ sidebarTitle: "Internals"
|
||||
# Plugin Internals
|
||||
|
||||
<Info>
|
||||
This page is for **plugin developers and contributors**. If you just want to
|
||||
install and use plugins, see [Plugins](/tools/plugin). If you want to build
|
||||
a plugin, see [Building Plugins](/plugins/building-plugins).
|
||||
This is the **deep architecture reference**. For practical guides, see:
|
||||
- [Install and use plugins](/tools/plugin) — user guide
|
||||
- [Getting Started](/plugins/building-plugins) — first plugin tutorial
|
||||
- [Channel Plugins](/plugins/sdk-channel-plugins) — build a messaging channel
|
||||
- [Provider Plugins](/plugins/sdk-provider-plugins) — build a model provider
|
||||
- [SDK Overview](/plugins/sdk-overview) — import map and registration API
|
||||
</Info>
|
||||
|
||||
This page covers the internal architecture of the OpenClaw plugin system.
|
||||
@@ -432,6 +435,11 @@ skills.
|
||||
Use allowlists and explicit install/load paths for non-bundled plugins. Treat
|
||||
workspace plugins as development-time code, not production defaults.
|
||||
|
||||
For bundled workspace package names, keep the plugin id anchored in the npm
|
||||
name: `@openclaw/<id>` by default, or an approved typed suffix such as
|
||||
`-provider`, `-plugin`, `-speech`, `-sandbox`, or `-media-understanding` when
|
||||
the package intentionally exposes a narrower plugin role.
|
||||
|
||||
Important trust note:
|
||||
|
||||
- `plugins.allow` trusts **plugin ids**, not source provenance.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "Building Plugins"
|
||||
title: "Building Plugins (redirect)"
|
||||
summary: "Redirects to the current Building Plugins guide"
|
||||
read_when:
|
||||
- Legacy link to building-extensions
|
||||
|
||||
@@ -1,337 +1,182 @@
|
||||
---
|
||||
title: "Building Plugins"
|
||||
sidebarTitle: "Building Plugins"
|
||||
summary: "Step-by-step guide for creating OpenClaw plugins with any combination of capabilities"
|
||||
sidebarTitle: "Getting Started"
|
||||
summary: "Create your first OpenClaw plugin in minutes"
|
||||
read_when:
|
||||
- You want to create a new OpenClaw plugin
|
||||
- You need to understand the plugin SDK import patterns
|
||||
- You need a quick-start for plugin development
|
||||
- You are adding a new channel, provider, tool, or other capability to OpenClaw
|
||||
---
|
||||
|
||||
# Building Plugins
|
||||
|
||||
Plugins extend OpenClaw with new capabilities: channels, model providers, speech,
|
||||
image generation, web search, agent tools, or any combination. A single plugin
|
||||
can register multiple capabilities.
|
||||
image generation, web search, agent tools, or any combination.
|
||||
|
||||
OpenClaw encourages **external plugin development**. You do not need to add your
|
||||
plugin to the OpenClaw repository. Publish your plugin on npm, and users install
|
||||
it with `openclaw plugins install <npm-spec>`. OpenClaw also maintains a set of
|
||||
core plugins in-repo, but the plugin system is designed for independent ownership
|
||||
and distribution.
|
||||
You do not need to add your plugin to the OpenClaw repository. Publish to
|
||||
[ClawHub](/tools/clawhub) or npm and users install with
|
||||
`openclaw plugins install <package-name>`. OpenClaw tries ClawHub first and
|
||||
falls back to npm automatically.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node >= 22 and a package manager (npm or pnpm)
|
||||
- Familiarity with TypeScript (ESM)
|
||||
- For in-repo plugins: OpenClaw repository cloned and `pnpm install` done
|
||||
- For in-repo plugins: repository cloned and `pnpm install` done
|
||||
|
||||
## Plugin capabilities
|
||||
## What kind of plugin?
|
||||
|
||||
A plugin can register one or more capabilities. The capability you register
|
||||
determines what your plugin provides to OpenClaw:
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Channel plugin" icon="messages-square" href="/plugins/sdk-channel-plugins">
|
||||
Connect OpenClaw to a messaging platform (Discord, IRC, etc.)
|
||||
</Card>
|
||||
<Card title="Provider plugin" icon="cpu" href="/plugins/sdk-provider-plugins">
|
||||
Add a model provider (LLM, proxy, or custom endpoint)
|
||||
</Card>
|
||||
<Card title="Tool / hook plugin" icon="wrench">
|
||||
Register agent tools, event hooks, or services — continue below
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
| Capability | Registration method | What it adds |
|
||||
| ------------------- | --------------------------------------------- | ------------------------------ |
|
||||
| Text inference | `api.registerProvider(...)` | Model provider (LLM) |
|
||||
| Channel / messaging | `api.registerChannel(...)` | Chat channel (e.g. Slack, IRC) |
|
||||
| Speech | `api.registerSpeechProvider(...)` | Text-to-speech / STT |
|
||||
| Media understanding | `api.registerMediaUnderstandingProvider(...)` | Image/audio/video analysis |
|
||||
| Image generation | `api.registerImageGenerationProvider(...)` | Image generation |
|
||||
| Web search | `api.registerWebSearchProvider(...)` | Web search provider |
|
||||
| Agent tools | `api.registerTool(...)` | Tools callable by the agent |
|
||||
## Quick start: tool plugin
|
||||
|
||||
A plugin that registers zero capabilities but provides hooks or services is a
|
||||
**hook-only** plugin. That pattern is still supported.
|
||||
|
||||
## Plugin structure
|
||||
|
||||
Plugins follow this layout (whether in-repo or standalone):
|
||||
|
||||
```
|
||||
my-plugin/
|
||||
├── package.json # npm metadata + openclaw config
|
||||
├── openclaw.plugin.json # Plugin manifest
|
||||
├── index.ts # Entry point
|
||||
├── setup-entry.ts # Setup wizard (optional)
|
||||
├── api.ts # Public exports (optional)
|
||||
├── runtime-api.ts # Internal exports (optional)
|
||||
└── src/
|
||||
├── provider.ts # Capability implementation
|
||||
├── runtime.ts # Runtime wiring
|
||||
└── *.test.ts # Colocated tests
|
||||
```
|
||||
|
||||
## Create a plugin
|
||||
This walkthrough creates a minimal plugin that registers an agent tool. Channel
|
||||
and provider plugins have dedicated guides linked above.
|
||||
|
||||
<Steps>
|
||||
<Step title="Create the package">
|
||||
Create `package.json` with the `openclaw` metadata block. The structure
|
||||
depends on what capabilities your plugin provides.
|
||||
|
||||
**Channel plugin example:**
|
||||
|
||||
```json
|
||||
<Step title="Create the package and manifest">
|
||||
<CodeGroup>
|
||||
```json package.json
|
||||
{
|
||||
"name": "@myorg/openclaw-my-channel",
|
||||
"name": "@myorg/openclaw-my-plugin",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"openclaw": {
|
||||
"extensions": ["./index.ts"],
|
||||
"channel": {
|
||||
"id": "my-channel",
|
||||
"label": "My Channel",
|
||||
"blurb": "Short description of the channel."
|
||||
}
|
||||
"extensions": ["./index.ts"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Provider plugin example:**
|
||||
|
||||
```json
|
||||
```json openclaw.plugin.json
|
||||
{
|
||||
"name": "@myorg/openclaw-my-provider",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"openclaw": {
|
||||
"extensions": ["./index.ts"],
|
||||
"providers": ["my-provider"]
|
||||
"id": "my-plugin",
|
||||
"name": "My Plugin",
|
||||
"description": "Adds a custom tool to OpenClaw",
|
||||
"configSchema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
The `openclaw` field tells the plugin system what your plugin provides.
|
||||
A plugin can declare both `channel` and `providers` if it provides multiple
|
||||
capabilities.
|
||||
Every plugin needs a manifest, even with no config. See
|
||||
[Manifest](/plugins/manifest) for the full schema.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Define the entry point">
|
||||
The entry point registers your capabilities with the plugin API.
|
||||
|
||||
**Channel plugin:**
|
||||
|
||||
```typescript
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
id: "my-channel",
|
||||
name: "My Channel",
|
||||
description: "Connects OpenClaw to My Channel",
|
||||
plugin: {
|
||||
// Channel adapter implementation
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**Provider plugin:**
|
||||
<Step title="Write the entry point">
|
||||
|
||||
```typescript
|
||||
// index.ts
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { Type } from "@sinclair/typebox";
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "my-provider",
|
||||
name: "My Provider",
|
||||
id: "my-plugin",
|
||||
name: "My Plugin",
|
||||
description: "Adds a custom tool to OpenClaw",
|
||||
register(api) {
|
||||
api.registerProvider({
|
||||
// Provider implementation
|
||||
api.registerTool({
|
||||
name: "my_tool",
|
||||
description: "Do a thing",
|
||||
parameters: Type.Object({ input: Type.String() }),
|
||||
async execute(_id, params) {
|
||||
return { content: [{ type: "text", text: `Got: ${params.input}` }] };
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**Multi-capability plugin** (provider + tool):
|
||||
|
||||
```typescript
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "my-plugin",
|
||||
name: "My Plugin",
|
||||
register(api) {
|
||||
api.registerProvider({ /* ... */ });
|
||||
api.registerTool({ /* ... */ });
|
||||
api.registerImageGenerationProvider({ /* ... */ });
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Use `defineChannelPluginEntry` from `plugin-sdk/core` for channel plugins
|
||||
and `definePluginEntry` from `plugin-sdk/plugin-entry` for everything else.
|
||||
A single plugin can register as many capabilities as needed.
|
||||
|
||||
For chat-style channels, `plugin-sdk/core` also exposes
|
||||
`createChatChannelPlugin(...)` so you can compose common DM security,
|
||||
text pairing, reply threading, and attached outbound send results without
|
||||
wiring each adapter separately.
|
||||
`definePluginEntry` is for non-channel plugins. For channels, use
|
||||
`defineChannelPluginEntry` — see [Channel Plugins](/plugins/sdk-channel-plugins).
|
||||
For full entry point options, see [Entry Points](/plugins/sdk-entrypoints).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Import from focused SDK subpaths">
|
||||
Always import from specific `openclaw/plugin-sdk/\<subpath\>` paths. The old
|
||||
monolithic import is deprecated (see [SDK Migration](/plugins/sdk-migration)).
|
||||
<Step title="Test and publish">
|
||||
|
||||
If older plugin code still imports `openclaw/extension-api`, treat that as a
|
||||
temporary compatibility bridge only. New code should use injected runtime
|
||||
helpers such as `api.runtime.agent.*` instead of importing host-side agent
|
||||
helpers directly.
|
||||
|
||||
```typescript
|
||||
// Correct: focused subpaths
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
||||
import { buildOauthProviderAuthResult } from "openclaw/plugin-sdk/provider-auth";
|
||||
|
||||
// Wrong: monolithic root (lint will reject this)
|
||||
import { ... } from "openclaw/plugin-sdk";
|
||||
|
||||
// Deprecated: legacy host bridge
|
||||
import { runEmbeddedPiAgent } from "openclaw/extension-api";
|
||||
```
|
||||
|
||||
<Accordion title="Common subpaths reference">
|
||||
| Subpath | Purpose |
|
||||
| --- | --- |
|
||||
| `plugin-sdk/plugin-entry` | Canonical `definePluginEntry` helper + provider/plugin entry types |
|
||||
| `plugin-sdk/core` | Channel entry helpers, channel builders, and shared base types |
|
||||
| `plugin-sdk/runtime-store` | Safe module-level runtime storage |
|
||||
| `plugin-sdk/setup` | Shared setup-wizard helpers |
|
||||
| `plugin-sdk/channel-setup` | Channel setup adapters |
|
||||
| `plugin-sdk/channel-pairing` | DM pairing primitives |
|
||||
| `plugin-sdk/channel-actions` | Shared `message` tool schema helpers |
|
||||
| `plugin-sdk/channel-contract` | Pure channel types |
|
||||
| `plugin-sdk/secret-input` | Secret input parsing/helpers |
|
||||
| `plugin-sdk/webhook-ingress` | Webhook request/target helpers |
|
||||
| `plugin-sdk/reply-payload` | Message reply types |
|
||||
| `plugin-sdk/provider-auth` | Provider auth and OAuth helpers |
|
||||
| `plugin-sdk/provider-onboard` | Provider onboarding config patches |
|
||||
| `plugin-sdk/provider-models` | Model catalog helpers |
|
||||
| `plugin-sdk/testing` | Test utilities |
|
||||
</Accordion>
|
||||
|
||||
Use the narrowest subpath that matches the job. For the curated map and
|
||||
examples, see [Plugin SDK Overview](/plugins/sdk-overview).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Use local modules for internal imports">
|
||||
Within your plugin, create local module files for internal code sharing
|
||||
instead of re-importing through the plugin SDK:
|
||||
|
||||
```typescript
|
||||
// api.ts — public exports for this plugin
|
||||
export { MyConfig } from "./src/config.js";
|
||||
export { MyRuntime } from "./src/runtime.js";
|
||||
|
||||
// runtime-api.ts — internal-only exports
|
||||
export { internalHelper } from "./src/helpers.js";
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Never import your own plugin back through its published SDK path from
|
||||
production files. Route internal imports through local files like `./api.ts`
|
||||
or `./runtime-api.ts`. The SDK path is for external consumers only.
|
||||
</Warning>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Add a plugin manifest">
|
||||
Create `openclaw.plugin.json` in your plugin root:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "my-plugin",
|
||||
"kind": "provider",
|
||||
"name": "My Plugin",
|
||||
"description": "Adds My Provider to OpenClaw"
|
||||
}
|
||||
```
|
||||
|
||||
For channel plugins, set `"kind": "channel"` and add `"channels": ["my-channel"]`.
|
||||
|
||||
See [Plugin Manifest](/plugins/manifest) for the full schema.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Test your plugin">
|
||||
**External plugins:** run your own test suite against the plugin SDK contracts.
|
||||
|
||||
**In-repo plugins:** OpenClaw runs contract tests against all registered plugins:
|
||||
**External plugins:** publish to [ClawHub](/tools/clawhub) or npm, then install:
|
||||
|
||||
```bash
|
||||
pnpm test:contracts:channels # channel plugins
|
||||
pnpm test:contracts:plugins # provider plugins
|
||||
```
|
||||
|
||||
For unit tests, import test helpers from the testing surface:
|
||||
|
||||
```typescript
|
||||
import { createWindowsCmdShimFixture } from "openclaw/plugin-sdk/testing";
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Publish and install">
|
||||
**External plugins:** publish to npm, then install:
|
||||
|
||||
```bash
|
||||
npm publish
|
||||
openclaw plugins install @myorg/openclaw-my-plugin
|
||||
```
|
||||
|
||||
**In-repo plugins:** place the plugin under `extensions/` and it is
|
||||
automatically discovered during build.
|
||||
OpenClaw checks ClawHub first, then falls back to npm.
|
||||
|
||||
Users can browse and install community plugins with:
|
||||
**In-repo plugins:** place under `extensions/` — automatically discovered.
|
||||
|
||||
```bash
|
||||
openclaw plugins search <query>
|
||||
openclaw plugins install <npm-spec>
|
||||
pnpm test -- extensions/my-plugin/
|
||||
```
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Plugin capabilities
|
||||
|
||||
A single plugin can register any number of capabilities via the `api` object:
|
||||
|
||||
| Capability | Registration method | Detailed guide |
|
||||
| -------------------- | --------------------------------------------- | ------------------------------------------------------------------------------- |
|
||||
| Text inference (LLM) | `api.registerProvider(...)` | [Provider Plugins](/plugins/sdk-provider-plugins) |
|
||||
| Channel / messaging | `api.registerChannel(...)` | [Channel Plugins](/plugins/sdk-channel-plugins) |
|
||||
| Speech (TTS/STT) | `api.registerSpeechProvider(...)` | [Provider Plugins](/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
|
||||
| Media understanding | `api.registerMediaUnderstandingProvider(...)` | [Provider Plugins](/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
|
||||
| Image generation | `api.registerImageGenerationProvider(...)` | [Provider Plugins](/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
|
||||
| Web search | `api.registerWebSearchProvider(...)` | [Provider Plugins](/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
|
||||
| Agent tools | `api.registerTool(...)` | Below |
|
||||
| Custom commands | `api.registerCommand(...)` | [Entry Points](/plugins/sdk-entrypoints) |
|
||||
| Event hooks | `api.registerHook(...)` | [Entry Points](/plugins/sdk-entrypoints) |
|
||||
| HTTP routes | `api.registerHttpRoute(...)` | [Internals](/plugins/architecture#gateway-http-routes) |
|
||||
| CLI subcommands | `api.registerCli(...)` | [Entry Points](/plugins/sdk-entrypoints) |
|
||||
|
||||
For the full registration API, see [SDK Overview](/plugins/sdk-overview#registration-api).
|
||||
|
||||
## Registering agent tools
|
||||
|
||||
Plugins can register **agent tools** — typed functions the LLM can call. Tools
|
||||
can be required (always available) or optional (users opt in via allowlists).
|
||||
Tools are typed functions the LLM can call. They can be required (always
|
||||
available) or optional (user opt-in):
|
||||
|
||||
```typescript
|
||||
import { Type } from "@sinclair/typebox";
|
||||
register(api) {
|
||||
// Required tool — always available
|
||||
api.registerTool({
|
||||
name: "my_tool",
|
||||
description: "Do a thing",
|
||||
parameters: Type.Object({ input: Type.String() }),
|
||||
async execute(_id, params) {
|
||||
return { content: [{ type: "text", text: params.input }] };
|
||||
},
|
||||
});
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "my-plugin",
|
||||
name: "My Plugin",
|
||||
register(api) {
|
||||
// Required tool (always available)
|
||||
api.registerTool({
|
||||
name: "my_tool",
|
||||
description: "Do a thing",
|
||||
parameters: Type.Object({ input: Type.String() }),
|
||||
// Optional tool — user must add to allowlist
|
||||
api.registerTool(
|
||||
{
|
||||
name: "workflow_tool",
|
||||
description: "Run a workflow",
|
||||
parameters: Type.Object({ pipeline: Type.String() }),
|
||||
async execute(_id, params) {
|
||||
return { content: [{ type: "text", text: params.input }] };
|
||||
return { content: [{ type: "text", text: params.pipeline }] };
|
||||
},
|
||||
});
|
||||
|
||||
// Optional tool (user must add to allowlist)
|
||||
api.registerTool(
|
||||
{
|
||||
name: "workflow_tool",
|
||||
description: "Run a workflow",
|
||||
parameters: Type.Object({ pipeline: Type.String() }),
|
||||
async execute(_id, params) {
|
||||
return { content: [{ type: "text", text: params.pipeline }] };
|
||||
},
|
||||
},
|
||||
{ optional: true },
|
||||
);
|
||||
},
|
||||
});
|
||||
},
|
||||
{ optional: true },
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Enable optional tools in config:
|
||||
Users enable optional tools in config:
|
||||
|
||||
```json5
|
||||
{
|
||||
@@ -339,46 +184,56 @@ Enable optional tools in config:
|
||||
}
|
||||
```
|
||||
|
||||
Tips:
|
||||
|
||||
- Tool names must not clash with core tool names (conflicts are skipped)
|
||||
- Use `optional: true` for tools that trigger side effects or require extra binaries
|
||||
- Tool names must not clash with core tools (conflicts are skipped)
|
||||
- Use `optional: true` for tools with side effects or extra binary requirements
|
||||
- Users can enable all tools from a plugin by adding the plugin id to `tools.allow`
|
||||
|
||||
## Lint enforcement (in-repo plugins)
|
||||
## Import conventions
|
||||
|
||||
Three scripts enforce SDK boundaries for plugins in the OpenClaw repository:
|
||||
Always import from focused `openclaw/plugin-sdk/<subpath>` paths:
|
||||
|
||||
1. **No monolithic root imports** — `openclaw/plugin-sdk` root is rejected
|
||||
2. **No direct src/ imports** — plugins cannot import `../../src/` directly
|
||||
3. **No self-imports** — plugins cannot import their own `plugin-sdk/\<name\>` subpath
|
||||
```typescript
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
||||
|
||||
Run `pnpm check` to verify all boundaries before committing.
|
||||
// Wrong: monolithic root (deprecated, will be removed)
|
||||
import { ... } from "openclaw/plugin-sdk";
|
||||
```
|
||||
|
||||
External plugins are not subject to these lint rules, but following the same
|
||||
patterns is strongly recommended.
|
||||
For the full subpath reference, see [SDK Overview](/plugins/sdk-overview).
|
||||
|
||||
Within your plugin, use local barrel files (`api.ts`, `runtime-api.ts`) for
|
||||
internal imports — never import your own plugin through its SDK path.
|
||||
|
||||
## Pre-submission checklist
|
||||
|
||||
<Check>**package.json** has correct `openclaw` metadata</Check>
|
||||
<Check>**openclaw.plugin.json** manifest is present and valid</Check>
|
||||
<Check>Entry point uses `defineChannelPluginEntry` or `definePluginEntry`</Check>
|
||||
<Check>All imports use focused `plugin-sdk/\<subpath\>` paths</Check>
|
||||
<Check>All imports use focused `plugin-sdk/<subpath>` paths</Check>
|
||||
<Check>Internal imports use local modules, not SDK self-imports</Check>
|
||||
<Check>`openclaw.plugin.json` manifest is present and valid</Check>
|
||||
<Check>Tests pass</Check>
|
||||
<Check>Tests pass (`pnpm test -- extensions/my-plugin/`)</Check>
|
||||
<Check>`pnpm check` passes (in-repo plugins)</Check>
|
||||
|
||||
## Related
|
||||
## Next steps
|
||||
|
||||
- [Plugin SDK Migration](/plugins/sdk-migration) — migrating from deprecated compat surfaces
|
||||
- [Plugin SDK Overview](/plugins/sdk-overview) — public SDK map and subpath guidance
|
||||
- [Plugin Entry Points](/plugins/sdk-entrypoints) — `definePluginEntry` and `defineChannelPluginEntry`
|
||||
- [Plugin Runtime](/plugins/sdk-runtime) — injected runtime and runtime-store
|
||||
- [Plugin Setup](/plugins/sdk-setup) — setup, channel setup, and secret input helpers
|
||||
- [Channel Plugin SDK](/plugins/sdk-channel-plugins) — channel contracts and actions
|
||||
- [Provider Plugin SDK](/plugins/sdk-provider-plugins) — provider auth, onboarding, and catalogs
|
||||
- [Plugin SDK Testing](/plugins/sdk-testing) — public test helpers
|
||||
- [Plugin Architecture](/plugins/architecture) — internals and capability model
|
||||
- [Plugin Manifest](/plugins/manifest) — full manifest schema
|
||||
- [Plugin Agent Tools](/plugins/building-plugins#registering-agent-tools) — adding agent tools in a plugin
|
||||
- [Community Plugins](/plugins/community) — listing and quality bar
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Channel Plugins" icon="messages-square" href="/plugins/sdk-channel-plugins">
|
||||
Build a messaging channel plugin
|
||||
</Card>
|
||||
<Card title="Provider Plugins" icon="cpu" href="/plugins/sdk-provider-plugins">
|
||||
Build a model provider plugin
|
||||
</Card>
|
||||
<Card title="SDK Overview" icon="book-open" href="/plugins/sdk-overview">
|
||||
Import map and registration API reference
|
||||
</Card>
|
||||
<Card title="Runtime Helpers" icon="settings" href="/plugins/sdk-runtime">
|
||||
TTS, search, subagent via api.runtime
|
||||
</Card>
|
||||
<Card title="Testing" icon="test-tubes" href="/plugins/sdk-testing">
|
||||
Test utilities and patterns
|
||||
</Card>
|
||||
<Card title="Plugin Manifest" icon="file-json" href="/plugins/manifest">
|
||||
Full manifest schema reference
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -10,12 +10,15 @@ title: "Community Plugins"
|
||||
|
||||
Community plugins are third-party packages that extend OpenClaw with new
|
||||
channels, tools, providers, or other capabilities. They are built and maintained
|
||||
by the community, published on npm, and installable with a single command.
|
||||
by the community, published on [ClawHub](/tools/clawhub) or npm, and
|
||||
installable with a single command.
|
||||
|
||||
```bash
|
||||
openclaw plugins install <npm-spec>
|
||||
openclaw plugins install <package-name>
|
||||
```
|
||||
|
||||
OpenClaw checks ClawHub first and falls back to npm automatically.
|
||||
|
||||
## Listed plugins
|
||||
|
||||
### Codex App Server Bridge
|
||||
@@ -99,8 +102,9 @@ openclaw plugins install @wecom/wecom-openclaw-plugin
|
||||
We welcome community plugins that are useful, documented, and safe to operate.
|
||||
|
||||
<Steps>
|
||||
<Step title="Publish to npm">
|
||||
Your plugin must be installable via `openclaw plugins install \<npm-spec\>`.
|
||||
<Step title="Publish to ClawHub or npm">
|
||||
Your plugin must be installable via `openclaw plugins install \<package-name\>`.
|
||||
Publish to [ClawHub](/tools/clawhub) (preferred) or npm.
|
||||
See [Building Plugins](/plugins/building-plugins) for the full guide.
|
||||
|
||||
</Step>
|
||||
@@ -125,12 +129,12 @@ We welcome community plugins that are useful, documented, and safe to operate.
|
||||
|
||||
## Quality bar
|
||||
|
||||
| Requirement | Why |
|
||||
| -------------------- | --------------------------------------------- |
|
||||
| Published on npm | Users need `openclaw plugins install` to work |
|
||||
| Public GitHub repo | Source review, issue tracking, transparency |
|
||||
| Setup and usage docs | Users need to know how to configure it |
|
||||
| Active maintenance | Recent updates or responsive issue handling |
|
||||
| Requirement | Why |
|
||||
| --------------------------- | --------------------------------------------- |
|
||||
| Published on ClawHub or npm | Users need `openclaw plugins install` to work |
|
||||
| Public GitHub repo | Source review, issue tracking, transparency |
|
||||
| Setup and usage docs | Users need to know how to configure it |
|
||||
| Active maintenance | Recent updates or responsive issue handling |
|
||||
|
||||
Low-effort wrappers, unclear ownership, or unmaintained packages may be declined.
|
||||
|
||||
|
||||
@@ -35,7 +35,28 @@ See the full plugin system guide: [Plugins](/tools/plugin).
|
||||
For the native capability model and current external-compatibility guidance:
|
||||
[Capability model](/plugins/architecture#public-capability-model).
|
||||
|
||||
## Required fields
|
||||
## What this file does
|
||||
|
||||
`openclaw.plugin.json` is the metadata OpenClaw reads before it loads your
|
||||
plugin code.
|
||||
|
||||
Use it for:
|
||||
|
||||
- plugin identity
|
||||
- config validation
|
||||
- auth and onboarding metadata that should be available without booting plugin
|
||||
runtime
|
||||
- config UI hints
|
||||
|
||||
Do not use it for:
|
||||
|
||||
- registering runtime behavior
|
||||
- declaring code entrypoints
|
||||
- npm install metadata
|
||||
|
||||
Those belong in your plugin code and `package.json`.
|
||||
|
||||
## Minimal example
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -48,45 +69,18 @@ For the native capability model and current external-compatibility guidance:
|
||||
}
|
||||
```
|
||||
|
||||
Required keys:
|
||||
|
||||
- `id` (string): canonical plugin id.
|
||||
- `configSchema` (object): JSON Schema for plugin config (inline).
|
||||
|
||||
Optional keys:
|
||||
|
||||
- `kind` (string): plugin kind (examples: `"memory"`, `"context-engine"`).
|
||||
- `channels` (array): channel ids registered by this plugin (channel capability; example: `["matrix"]`).
|
||||
- `providers` (array): provider ids registered by this plugin (text inference capability).
|
||||
- `providerAuthEnvVars` (object): auth env vars keyed by provider id. Use this
|
||||
when OpenClaw should resolve provider credentials from env without loading
|
||||
plugin runtime first.
|
||||
- `providerAuthChoices` (array): cheap onboarding/auth-choice metadata keyed by
|
||||
provider + auth method. Use this when OpenClaw should show a provider in
|
||||
auth-choice pickers, preferred-provider resolution, and CLI help without
|
||||
loading plugin runtime first.
|
||||
- `skills` (array): skill directories to load (relative to the plugin root).
|
||||
- `name` (string): display name for the plugin.
|
||||
- `description` (string): short plugin summary.
|
||||
- `uiHints` (object): config field labels/placeholders/sensitive flags for UI rendering.
|
||||
- `version` (string): plugin version (informational).
|
||||
|
||||
### `providerAuthChoices` shape
|
||||
|
||||
Each entry can declare:
|
||||
|
||||
- `provider`: provider id
|
||||
- `method`: auth method id
|
||||
- `choiceId`: stable onboarding/auth-choice id
|
||||
- `choiceLabel` / `choiceHint`: picker label + short hint
|
||||
- `groupId` / `groupLabel` / `groupHint`: grouped onboarding bucket metadata
|
||||
- `optionKey` / `cliFlag` / `cliOption` / `cliDescription`: optional one-flag
|
||||
CLI wiring for simple auth flows such as API keys
|
||||
|
||||
Example:
|
||||
## Rich example
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "openrouter",
|
||||
"name": "OpenRouter",
|
||||
"description": "OpenRouter provider plugin",
|
||||
"version": "1.0.0",
|
||||
"providers": ["openrouter"],
|
||||
"providerAuthEnvVars": {
|
||||
"openrouter": ["OPENROUTER_API_KEY"]
|
||||
},
|
||||
"providerAuthChoices": [
|
||||
{
|
||||
"provider": "openrouter",
|
||||
@@ -98,12 +92,110 @@ Example:
|
||||
"optionKey": "openrouterApiKey",
|
||||
"cliFlag": "--openrouter-api-key",
|
||||
"cliOption": "--openrouter-api-key <key>",
|
||||
"cliDescription": "OpenRouter API key"
|
||||
"cliDescription": "OpenRouter API key",
|
||||
"onboardingScopes": ["text-inference"]
|
||||
}
|
||||
]
|
||||
],
|
||||
"uiHints": {
|
||||
"apiKey": {
|
||||
"label": "API key",
|
||||
"placeholder": "sk-or-v1-...",
|
||||
"sensitive": true
|
||||
}
|
||||
},
|
||||
"configSchema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"apiKey": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Top-level field reference
|
||||
|
||||
| Field | Required | Type | What it means |
|
||||
| --------------------- | -------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `id` | Yes | `string` | Canonical plugin id. This is the id used in `plugins.entries.<id>`. |
|
||||
| `configSchema` | Yes | `object` | Inline JSON Schema for this plugin's config. |
|
||||
| `enabledByDefault` | No | `true` | Marks a bundled plugin as enabled by default. Omit it, or set any non-`true` value, to leave the plugin disabled by default. |
|
||||
| `kind` | No | `"memory"` \| `"context-engine"` | Declares an exclusive plugin kind used by `plugins.slots.*`. |
|
||||
| `channels` | No | `string[]` | Channel ids owned by this plugin. Used for discovery and config validation. |
|
||||
| `providers` | No | `string[]` | Provider ids owned by this plugin. |
|
||||
| `providerAuthEnvVars` | No | `Record<string, string[]>` | Cheap provider-auth env metadata that OpenClaw can inspect without loading plugin code. |
|
||||
| `providerAuthChoices` | No | `object[]` | Cheap auth-choice metadata for onboarding pickers, preferred-provider resolution, and simple CLI flag wiring. |
|
||||
| `skills` | No | `string[]` | Skill directories to load, relative to the plugin root. |
|
||||
| `name` | No | `string` | Human-readable plugin name. |
|
||||
| `description` | No | `string` | Short summary shown in plugin surfaces. |
|
||||
| `version` | No | `string` | Informational plugin version. |
|
||||
| `uiHints` | No | `Record<string, object>` | UI labels, placeholders, and sensitivity hints for config fields. |
|
||||
|
||||
## providerAuthChoices reference
|
||||
|
||||
Each `providerAuthChoices` entry describes one onboarding or auth choice.
|
||||
OpenClaw reads this before provider runtime loads.
|
||||
|
||||
| Field | Required | Type | What it means |
|
||||
| ------------------ | -------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| `provider` | Yes | `string` | Provider id this choice belongs to. |
|
||||
| `method` | Yes | `string` | Auth method id to dispatch to. |
|
||||
| `choiceId` | Yes | `string` | Stable auth-choice id used by onboarding and CLI flows. |
|
||||
| `choiceLabel` | No | `string` | User-facing label. If omitted, OpenClaw falls back to `choiceId`. |
|
||||
| `choiceHint` | No | `string` | Short helper text for the picker. |
|
||||
| `groupId` | No | `string` | Optional group id for grouping related choices. |
|
||||
| `groupLabel` | No | `string` | User-facing label for that group. |
|
||||
| `groupHint` | No | `string` | Short helper text for the group. |
|
||||
| `optionKey` | No | `string` | Internal option key for simple one-flag auth flows. |
|
||||
| `cliFlag` | No | `string` | CLI flag name, such as `--openrouter-api-key`. |
|
||||
| `cliOption` | No | `string` | Full CLI option shape, such as `--openrouter-api-key <key>`. |
|
||||
| `cliDescription` | No | `string` | Description used in CLI help. |
|
||||
| `onboardingScopes` | No | `Array<"text-inference" \| "image-generation">` | Which onboarding surfaces this choice should appear in. If omitted, it defaults to `["text-inference"]`. |
|
||||
|
||||
## uiHints reference
|
||||
|
||||
`uiHints` is a map from config field names to small rendering hints.
|
||||
|
||||
```json
|
||||
{
|
||||
"uiHints": {
|
||||
"apiKey": {
|
||||
"label": "API key",
|
||||
"help": "Used for OpenRouter requests",
|
||||
"placeholder": "sk-or-v1-...",
|
||||
"sensitive": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each field hint can include:
|
||||
|
||||
| Field | Type | What it means |
|
||||
| ------------- | ---------- | --------------------------------------- |
|
||||
| `label` | `string` | User-facing field label. |
|
||||
| `help` | `string` | Short helper text. |
|
||||
| `tags` | `string[]` | Optional UI tags. |
|
||||
| `advanced` | `boolean` | Marks the field as advanced. |
|
||||
| `sensitive` | `boolean` | Marks the field as secret or sensitive. |
|
||||
| `placeholder` | `string` | Placeholder text for form inputs. |
|
||||
|
||||
## Manifest versus package.json
|
||||
|
||||
The two files serve different jobs:
|
||||
|
||||
| File | Use it for |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| `openclaw.plugin.json` | Discovery, config validation, auth-choice metadata, and UI hints that must exist before plugin code runs |
|
||||
| `package.json` | npm metadata, dependency installation, and the `openclaw` block used for entrypoints and setup or catalog metadata |
|
||||
|
||||
If you are unsure where a piece of metadata belongs, use this rule:
|
||||
|
||||
- if OpenClaw must know it before loading plugin code, put it in `openclaw.plugin.json`
|
||||
- if it is about packaging, entry files, or npm install behavior, put it in `package.json`
|
||||
|
||||
## JSON Schema requirements
|
||||
|
||||
- **Every plugin must ship a JSON Schema**, even if it accepts no config.
|
||||
@@ -121,13 +213,15 @@ Example:
|
||||
- If plugin config exists but the plugin is **disabled**, the config is kept and
|
||||
a **warning** is surfaced in Doctor + logs.
|
||||
|
||||
See [Configuration reference](/configuration) for the full `plugins.*` schema.
|
||||
See [Configuration reference](/gateway/configuration) for the full `plugins.*` schema.
|
||||
|
||||
## Notes
|
||||
|
||||
- The manifest is **required for native OpenClaw plugins**, including local filesystem loads.
|
||||
- Runtime still loads the plugin module separately; the manifest is only for
|
||||
discovery + validation.
|
||||
- Only documented manifest fields are read by the manifest loader. Avoid adding
|
||||
custom top-level keys here.
|
||||
- `providerAuthEnvVars` is the cheap metadata path for auth probes, env-marker
|
||||
validation, and similar provider-auth surfaces that should not boot plugin
|
||||
runtime just to inspect env names.
|
||||
@@ -140,6 +234,8 @@ See [Configuration reference](/configuration) for the full `plugins.*` schema.
|
||||
- `kind: "memory"` is selected by `plugins.slots.memory`.
|
||||
- `kind: "context-engine"` is selected by `plugins.slots.contextEngine`
|
||||
(default: built-in `legacy`).
|
||||
- `channels`, `providers`, and `skills` can be omitted when a plugin does not
|
||||
need them.
|
||||
- If your plugin depends on native modules, document the build steps and any
|
||||
package-manager allowlist requirements (for example, pnpm `allow-build-scripts`
|
||||
- `pnpm rebuild <package>`).
|
||||
|
||||
@@ -1,161 +1,370 @@
|
||||
---
|
||||
title: "Channel Plugin SDK"
|
||||
title: "Building Channel Plugins"
|
||||
sidebarTitle: "Channel Plugins"
|
||||
summary: "Contracts and helpers for native messaging channel plugins, including actions, routing, pairing, and setup"
|
||||
summary: "Step-by-step guide to building a messaging channel plugin for OpenClaw"
|
||||
read_when:
|
||||
- You are building a native channel plugin
|
||||
- You need to implement the shared `message` tool for a channel
|
||||
- You need pairing, setup, or routing helpers for a channel
|
||||
- You are building a new messaging channel plugin
|
||||
- You want to connect OpenClaw to a messaging platform
|
||||
- You need to understand the ChannelPlugin adapter surface
|
||||
---
|
||||
|
||||
# Channel Plugin SDK
|
||||
# Building Channel Plugins
|
||||
|
||||
Channel plugins use `defineChannelPluginEntry(...)` from
|
||||
`openclaw/plugin-sdk/core` and implement the `ChannelPlugin` contract.
|
||||
This guide walks through building a channel plugin that connects OpenClaw to a
|
||||
messaging platform. By the end you will have a working channel with DM security,
|
||||
pairing, reply threading, and outbound messaging.
|
||||
|
||||
## Minimal channel entry
|
||||
<Info>
|
||||
If you have not built any OpenClaw plugin before, read
|
||||
[Getting Started](/plugins/building-plugins) first for the basic package
|
||||
structure and manifest setup.
|
||||
</Info>
|
||||
|
||||
```ts
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { exampleChannelPlugin } from "./src/channel.js";
|
||||
import { setExampleRuntime } from "./src/runtime.js";
|
||||
## How channel plugins work
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
id: "example-channel",
|
||||
name: "Example Channel",
|
||||
description: "Example native channel plugin",
|
||||
plugin: exampleChannelPlugin,
|
||||
setRuntime: setExampleRuntime,
|
||||
});
|
||||
```
|
||||
Channel plugins do not need their own send/edit/react tools. OpenClaw keeps one
|
||||
shared `message` tool in core. Your plugin owns:
|
||||
|
||||
## `ChannelPlugin` shape
|
||||
- **Config** — account resolution and setup wizard
|
||||
- **Security** — DM policy and allowlists
|
||||
- **Pairing** — DM approval flow
|
||||
- **Outbound** — sending text, media, and polls to the platform
|
||||
- **Threading** — how replies are threaded
|
||||
|
||||
Important sections of the contract:
|
||||
Core owns the shared message tool, prompt wiring, session bookkeeping, and
|
||||
dispatch.
|
||||
|
||||
- `meta`: docs, labels, and picker metadata
|
||||
- `capabilities`: replies, polls, reactions, threads, media, and chat types
|
||||
- `config` and `configSchema`: account resolution and config parsing
|
||||
- `setup` and `setupWizard`: onboarding/setup flow
|
||||
- `security`: DM policy and allowlist behavior
|
||||
- `messaging`: target parsing and outbound session routing
|
||||
- `actions`: shared `message` tool discovery and execution
|
||||
- `pairing`, `threading`, `status`, `lifecycle`, `groups`, `directory`
|
||||
## Walkthrough
|
||||
|
||||
For pure types, import from `openclaw/plugin-sdk/channel-contract`.
|
||||
<Steps>
|
||||
<Step title="Package and manifest">
|
||||
Create the standard plugin files. The `channel` field in `package.json` is
|
||||
what makes this a channel plugin:
|
||||
|
||||
## Shared `message` tool
|
||||
<CodeGroup>
|
||||
```json package.json
|
||||
{
|
||||
"name": "@myorg/openclaw-acme-chat",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"openclaw": {
|
||||
"extensions": ["./index.ts"],
|
||||
"setupEntry": "./setup-entry.ts",
|
||||
"channel": {
|
||||
"id": "acme-chat",
|
||||
"label": "Acme Chat",
|
||||
"blurb": "Connect OpenClaw to Acme Chat."
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Channel plugins own their channel-specific part of the shared `message` tool
|
||||
through `ChannelMessageActionAdapter`.
|
||||
```json openclaw.plugin.json
|
||||
{
|
||||
"id": "acme-chat",
|
||||
"kind": "channel",
|
||||
"channels": ["acme-chat"],
|
||||
"name": "Acme Chat",
|
||||
"description": "Acme Chat channel plugin",
|
||||
"configSchema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"acme-chat": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"token": { "type": "string" },
|
||||
"allowFrom": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
```ts
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { createMessageToolButtonsSchema } from "openclaw/plugin-sdk/channel-actions";
|
||||
</Step>
|
||||
|
||||
export const exampleActions = {
|
||||
describeMessageTool() {
|
||||
return {
|
||||
actions: ["send", "edit"],
|
||||
capabilities: ["buttons"],
|
||||
schema: {
|
||||
visibility: "current-channel",
|
||||
properties: {
|
||||
buttons: createMessageToolButtonsSchema(),
|
||||
threadId: Type.String(),
|
||||
},
|
||||
},
|
||||
<Step title="Build the channel plugin object">
|
||||
The `ChannelPlugin` interface has many optional adapter surfaces. Start with
|
||||
the minimum — `id` and `setup` — and add adapters as you need them.
|
||||
|
||||
Create `src/channel.ts`:
|
||||
|
||||
```typescript src/channel.ts
|
||||
import {
|
||||
createChatChannelPlugin,
|
||||
createChannelPluginBase,
|
||||
} from "openclaw/plugin-sdk/core";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/core";
|
||||
import { acmeChatApi } from "./client.js"; // your platform API client
|
||||
|
||||
type ResolvedAccount = {
|
||||
accountId: string | null;
|
||||
token: string;
|
||||
allowFrom: string[];
|
||||
dmPolicy: string | undefined;
|
||||
};
|
||||
},
|
||||
async handleAction(ctx) {
|
||||
if (ctx.action === "send") {
|
||||
|
||||
function resolveAccount(
|
||||
cfg: OpenClawConfig,
|
||||
accountId?: string | null,
|
||||
): ResolvedAccount {
|
||||
const section = (cfg.channels as Record<string, any>)?.["acme-chat"];
|
||||
const token = section?.token;
|
||||
if (!token) throw new Error("acme-chat: token is required");
|
||||
return {
|
||||
content: [{ type: "text", text: `send to ${String(ctx.params.to)}` }],
|
||||
accountId: accountId ?? null,
|
||||
token,
|
||||
allowFrom: section?.allowFrom ?? [],
|
||||
dmPolicy: section?.dmSecurity,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
content: [{ type: "text", text: `unsupported action: ${ctx.action}` }],
|
||||
};
|
||||
},
|
||||
};
|
||||
```
|
||||
export const acmeChatPlugin = createChatChannelPlugin<ResolvedAccount>({
|
||||
base: createChannelPluginBase({
|
||||
id: "acme-chat",
|
||||
setup: {
|
||||
resolveAccount,
|
||||
inspectAccount(cfg, accountId) {
|
||||
const section =
|
||||
(cfg.channels as Record<string, any>)?.["acme-chat"];
|
||||
return {
|
||||
enabled: Boolean(section?.token),
|
||||
configured: Boolean(section?.token),
|
||||
tokenStatus: section?.token ? "available" : "missing",
|
||||
};
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
Key types:
|
||||
// DM security: who can message the bot
|
||||
security: {
|
||||
dm: {
|
||||
channelKey: "acme-chat",
|
||||
resolvePolicy: (account) => account.dmPolicy,
|
||||
resolveAllowFrom: (account) => account.allowFrom,
|
||||
defaultPolicy: "allowlist",
|
||||
},
|
||||
},
|
||||
|
||||
- `ChannelMessageActionAdapter`
|
||||
- `ChannelMessageActionContext`
|
||||
- `ChannelMessageActionDiscoveryContext`
|
||||
- `ChannelMessageToolDiscovery`
|
||||
// Pairing: approval flow for new DM contacts
|
||||
pairing: {
|
||||
text: {
|
||||
idLabel: "Acme Chat username",
|
||||
message: "Send this code to verify your identity:",
|
||||
notify: async ({ target, code }) => {
|
||||
await acmeChatApi.sendDm(target, `Pairing code: ${code}`);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
## Outbound routing helpers
|
||||
// Threading: how replies are delivered
|
||||
threading: { topLevelReplyToMode: "reply" },
|
||||
|
||||
When a channel plugin needs custom outbound routing, implement
|
||||
`messaging.resolveOutboundSessionRoute(...)`.
|
||||
|
||||
Use `buildChannelOutboundSessionRoute(...)` from `plugin-sdk/core` to return the
|
||||
standard route payload:
|
||||
|
||||
```ts
|
||||
import { buildChannelOutboundSessionRoute } from "openclaw/plugin-sdk/core";
|
||||
|
||||
const messaging = {
|
||||
resolveOutboundSessionRoute({ cfg, agentId, accountId, target }) {
|
||||
return buildChannelOutboundSessionRoute({
|
||||
cfg,
|
||||
agentId,
|
||||
channel: "example-channel",
|
||||
accountId,
|
||||
peer: { kind: "direct", id: target },
|
||||
chatType: "direct",
|
||||
from: accountId ?? "default",
|
||||
to: target,
|
||||
// Outbound: send messages to the platform
|
||||
outbound: {
|
||||
attachedResults: {
|
||||
sendText: async (params) => {
|
||||
const result = await acmeChatApi.sendMessage(
|
||||
params.to,
|
||||
params.text,
|
||||
);
|
||||
return { messageId: result.id };
|
||||
},
|
||||
},
|
||||
base: {
|
||||
sendMedia: async (params) => {
|
||||
await acmeChatApi.sendFile(params.to, params.filePath);
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
<Accordion title="What createChatChannelPlugin does for you">
|
||||
Instead of implementing low-level adapter interfaces manually, you pass
|
||||
declarative options and the builder composes them:
|
||||
|
||||
| Option | What it wires |
|
||||
| --- | --- |
|
||||
| `security.dm` | Scoped DM security resolver from config fields |
|
||||
| `pairing.text` | Text-based DM pairing flow with code exchange |
|
||||
| `threading` | Reply-to-mode resolver (fixed, account-scoped, or custom) |
|
||||
| `outbound.attachedResults` | Send functions that return result metadata (message IDs) |
|
||||
|
||||
You can also pass raw adapter objects instead of the declarative options
|
||||
if you need full control.
|
||||
</Accordion>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Wire the entry point">
|
||||
Create `index.ts`:
|
||||
|
||||
```typescript index.ts
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { acmeChatPlugin } from "./src/channel.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
id: "acme-chat",
|
||||
name: "Acme Chat",
|
||||
description: "Acme Chat channel plugin",
|
||||
plugin: acmeChatPlugin,
|
||||
registerFull(api) {
|
||||
api.registerCli(
|
||||
({ program }) => {
|
||||
program
|
||||
.command("acme-chat")
|
||||
.description("Acme Chat management");
|
||||
},
|
||||
{ commands: ["acme-chat"] },
|
||||
);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
`defineChannelPluginEntry` handles the setup/full registration split
|
||||
automatically. See
|
||||
[Entry Points](/plugins/sdk-entrypoints#definechannelpluginentry) for all
|
||||
options.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Add a setup entry">
|
||||
Create `setup-entry.ts` for lightweight loading during onboarding:
|
||||
|
||||
```typescript setup-entry.ts
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { acmeChatPlugin } from "./src/channel.js";
|
||||
|
||||
export default defineSetupPluginEntry(acmeChatPlugin);
|
||||
```
|
||||
|
||||
OpenClaw loads this instead of the full entry when the channel is disabled
|
||||
or unconfigured. It avoids pulling in heavy runtime code during setup flows.
|
||||
See [Setup and Config](/plugins/sdk-setup#setup-entry) for details.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Handle inbound messages">
|
||||
Your plugin needs to receive messages from the platform and forward them to
|
||||
OpenClaw. The typical pattern is a webhook that verifies the request and
|
||||
dispatches it through your channel's inbound handler:
|
||||
|
||||
```typescript
|
||||
registerFull(api) {
|
||||
api.registerHttpRoute({
|
||||
path: "/acme-chat/webhook",
|
||||
auth: "plugin", // plugin-managed auth (verify signatures yourself)
|
||||
handler: async (req, res) => {
|
||||
const event = parseWebhookPayload(req);
|
||||
|
||||
// Your inbound handler dispatches the message to OpenClaw.
|
||||
// The exact wiring depends on your platform SDK —
|
||||
// see a real example in extensions/msteams or extensions/googlechat.
|
||||
await handleAcmeChatInbound(api, event);
|
||||
|
||||
res.statusCode = 200;
|
||||
res.end("ok");
|
||||
return true;
|
||||
},
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
<Note>
|
||||
Inbound message handling is channel-specific. Each channel plugin owns
|
||||
its own inbound pipeline. Look at bundled channel plugins
|
||||
(e.g. `extensions/msteams`, `extensions/googlechat`) for real patterns.
|
||||
</Note>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Test">
|
||||
Write colocated tests in `src/channel.test.ts`:
|
||||
|
||||
```typescript src/channel.test.ts
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { acmeChatPlugin } from "./channel.js";
|
||||
|
||||
describe("acme-chat plugin", () => {
|
||||
it("resolves account from config", () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
"acme-chat": { token: "test-token", allowFrom: ["user1"] },
|
||||
},
|
||||
} as any;
|
||||
const account = acmeChatPlugin.setup!.resolveAccount(cfg, undefined);
|
||||
expect(account.token).toBe("test-token");
|
||||
});
|
||||
|
||||
it("inspects account without materializing secrets", () => {
|
||||
const cfg = {
|
||||
channels: { "acme-chat": { token: "test-token" } },
|
||||
} as any;
|
||||
const result = acmeChatPlugin.setup!.inspectAccount!(cfg, undefined);
|
||||
expect(result.configured).toBe(true);
|
||||
expect(result.tokenStatus).toBe("available");
|
||||
});
|
||||
|
||||
it("reports missing config", () => {
|
||||
const cfg = { channels: {} } as any;
|
||||
const result = acmeChatPlugin.setup!.inspectAccount!(cfg, undefined);
|
||||
expect(result.configured).toBe(false);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
```bash
|
||||
pnpm test -- extensions/acme-chat/
|
||||
```
|
||||
|
||||
For shared test helpers, see [Testing](/plugins/sdk-testing).
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## File structure
|
||||
|
||||
```
|
||||
extensions/acme-chat/
|
||||
├── package.json # openclaw.channel metadata
|
||||
├── openclaw.plugin.json # Manifest with config schema
|
||||
├── index.ts # defineChannelPluginEntry
|
||||
├── setup-entry.ts # defineSetupPluginEntry
|
||||
├── api.ts # Public exports (optional)
|
||||
├── runtime-api.ts # Internal runtime exports (optional)
|
||||
└── src/
|
||||
├── channel.ts # ChannelPlugin via createChatChannelPlugin
|
||||
├── channel.test.ts # Tests
|
||||
├── client.ts # Platform API client
|
||||
└── runtime.ts # Runtime store (if needed)
|
||||
```
|
||||
|
||||
## Pairing helpers
|
||||
## Advanced topics
|
||||
|
||||
Use `plugin-sdk/channel-pairing` for DM approval flows:
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Threading options" icon="git-branch" href="/plugins/sdk-entrypoints#registration-mode">
|
||||
Fixed, account-scoped, or custom reply modes
|
||||
</Card>
|
||||
<Card title="Message tool integration" icon="puzzle" href="/plugins/architecture#channel-plugins-and-the-shared-message-tool">
|
||||
describeMessageTool and action discovery
|
||||
</Card>
|
||||
<Card title="Target resolution" icon="crosshair" href="/plugins/architecture#channel-target-resolution">
|
||||
inferTargetChatType, looksLikeId, resolveTarget
|
||||
</Card>
|
||||
<Card title="Runtime helpers" icon="settings" href="/plugins/sdk-runtime">
|
||||
TTS, STT, media, subagent via api.runtime
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
```ts
|
||||
import { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
|
||||
## Next steps
|
||||
|
||||
const pairing = createChannelPairingController({
|
||||
core: runtime,
|
||||
channel: "example-channel",
|
||||
accountId: "default",
|
||||
});
|
||||
|
||||
const result = pairing.issueChallenge({
|
||||
agentId: "assistant",
|
||||
requesterId: "user-123",
|
||||
});
|
||||
```
|
||||
|
||||
That surface also gives you scoped access to pairing storage helpers such as
|
||||
allowlist reads and request upserts.
|
||||
|
||||
## Channel setup helpers
|
||||
|
||||
Use:
|
||||
|
||||
- `plugin-sdk/channel-setup` for optional or installable channels
|
||||
- `plugin-sdk/setup` for setup adapters, DM policy, and allowlist prompts
|
||||
- `plugin-sdk/webhook-ingress` for plugin-owned webhook routes
|
||||
|
||||
## Channel plugin guidance
|
||||
|
||||
- Keep transport-specific execution inside the channel package.
|
||||
- Use `channel-contract` types in tests and local helpers.
|
||||
- Keep `describeMessageTool(...)` and `handleAction(...)` aligned.
|
||||
- Keep session routing in `messaging`, not in ad-hoc command handlers.
|
||||
- Prefer focused subpaths over broad runtime coupling.
|
||||
|
||||
## Related
|
||||
|
||||
- [Plugin SDK Overview](/plugins/sdk-overview)
|
||||
- [Plugin Entry Points](/plugins/sdk-entrypoints)
|
||||
- [Plugin Setup](/plugins/sdk-setup)
|
||||
- [Plugin Internals](/plugins/architecture)
|
||||
- [Provider Plugins](/plugins/sdk-provider-plugins) — if your plugin also provides models
|
||||
- [SDK Overview](/plugins/sdk-overview) — full subpath import reference
|
||||
- [SDK Testing](/plugins/sdk-testing) — test utilities and contract tests
|
||||
- [Plugin Manifest](/plugins/manifest) — full manifest schema
|
||||
|
||||
@@ -1,159 +1,157 @@
|
||||
---
|
||||
title: "Plugin Entry Points"
|
||||
sidebarTitle: "Entry Points"
|
||||
summary: "How to define plugin entry files for provider, tool, channel, and setup plugins"
|
||||
summary: "Reference for definePluginEntry, defineChannelPluginEntry, and defineSetupPluginEntry"
|
||||
read_when:
|
||||
- You are writing a plugin `index.ts`
|
||||
- You need to choose between `definePluginEntry` and `defineChannelPluginEntry`
|
||||
- You are adding a separate `setup-entry.ts`
|
||||
- You need the exact type signature of definePluginEntry or defineChannelPluginEntry
|
||||
- You want to understand registration mode (full vs setup)
|
||||
- You are looking up entry point options
|
||||
---
|
||||
|
||||
# Plugin Entry Points
|
||||
|
||||
OpenClaw has two main entry helpers:
|
||||
Every plugin exports a default entry object. The SDK provides three helpers for
|
||||
creating them.
|
||||
|
||||
- `definePluginEntry(...)` for general plugins
|
||||
- `defineChannelPluginEntry(...)` for native messaging channels
|
||||
<Tip>
|
||||
**Looking for a walkthrough?** See [Channel Plugins](/plugins/sdk-channel-plugins)
|
||||
or [Provider Plugins](/plugins/sdk-provider-plugins) for step-by-step guides.
|
||||
</Tip>
|
||||
|
||||
There is also `defineSetupPluginEntry(...)` for a separate setup-only module.
|
||||
## `definePluginEntry`
|
||||
|
||||
## `definePluginEntry(...)`
|
||||
**Import:** `openclaw/plugin-sdk/plugin-entry`
|
||||
|
||||
Use this for providers, tools, commands, services, memory plugins, and context
|
||||
engines.
|
||||
For provider plugins, tool plugins, hook plugins, and anything that is **not**
|
||||
a messaging channel.
|
||||
|
||||
```ts
|
||||
import { definePluginEntry, type OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
||||
```typescript
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "example-tools",
|
||||
name: "Example Tools",
|
||||
description: "Adds a command and a tool",
|
||||
register(api: OpenClawPluginApi) {
|
||||
api.registerCommand({
|
||||
name: "example",
|
||||
description: "Show plugin status",
|
||||
handler: async () => ({ text: "example ok" }),
|
||||
id: "my-plugin",
|
||||
name: "My Plugin",
|
||||
description: "Short summary",
|
||||
register(api) {
|
||||
api.registerProvider({
|
||||
/* ... */
|
||||
});
|
||||
|
||||
api.registerTool({
|
||||
name: "example_lookup",
|
||||
description: "Look up Example data",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
query: { type: "string" },
|
||||
},
|
||||
required: ["query"],
|
||||
},
|
||||
async execute(_callId, params) {
|
||||
return {
|
||||
content: [{ type: "text", text: `lookup: ${String(params.query)}` }],
|
||||
};
|
||||
},
|
||||
/* ... */
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## `defineChannelPluginEntry(...)`
|
||||
| Field | Type | Required | Default |
|
||||
| -------------- | ---------------------------------------------------------------- | -------- | ------------------- |
|
||||
| `id` | `string` | Yes | — |
|
||||
| `name` | `string` | Yes | — |
|
||||
| `description` | `string` | Yes | — |
|
||||
| `kind` | `string` | No | — |
|
||||
| `configSchema` | `OpenClawPluginConfigSchema \| () => OpenClawPluginConfigSchema` | No | Empty object schema |
|
||||
| `register` | `(api: OpenClawPluginApi) => void` | Yes | — |
|
||||
|
||||
Use this for a plugin that registers a `ChannelPlugin`.
|
||||
- `id` must match your `openclaw.plugin.json` manifest.
|
||||
- `kind` is for exclusive slots: `"memory"` or `"context-engine"`.
|
||||
- `configSchema` can be a function for lazy evaluation.
|
||||
|
||||
```ts
|
||||
## `defineChannelPluginEntry`
|
||||
|
||||
**Import:** `openclaw/plugin-sdk/core`
|
||||
|
||||
Wraps `definePluginEntry` with channel-specific wiring. Automatically calls
|
||||
`api.registerChannel({ plugin })` and gates `registerFull` on registration mode.
|
||||
|
||||
```typescript
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { channelPlugin } from "./src/channel.js";
|
||||
import { setRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
id: "example-channel",
|
||||
name: "Example Channel",
|
||||
description: "Example messaging plugin",
|
||||
plugin: channelPlugin,
|
||||
setRuntime,
|
||||
id: "my-channel",
|
||||
name: "My Channel",
|
||||
description: "Short summary",
|
||||
plugin: myChannelPlugin,
|
||||
setRuntime: setMyRuntime,
|
||||
registerFull(api) {
|
||||
api.registerTool({
|
||||
name: "example_channel_status",
|
||||
description: "Inspect Example Channel state",
|
||||
parameters: { type: "object", properties: {} },
|
||||
async execute() {
|
||||
return { content: [{ type: "text", text: "ok" }] };
|
||||
},
|
||||
});
|
||||
api.registerCli(/* ... */);
|
||||
api.registerGatewayMethod(/* ... */);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Why `registerFull(...)` exists
|
||||
| Field | Type | Required | Default |
|
||||
| -------------- | ---------------------------------------------------------------- | -------- | ------------------- |
|
||||
| `id` | `string` | Yes | — |
|
||||
| `name` | `string` | Yes | — |
|
||||
| `description` | `string` | Yes | — |
|
||||
| `plugin` | `ChannelPlugin` | Yes | — |
|
||||
| `configSchema` | `OpenClawPluginConfigSchema \| () => OpenClawPluginConfigSchema` | No | Empty object schema |
|
||||
| `setRuntime` | `(runtime: PluginRuntime) => void` | No | — |
|
||||
| `registerFull` | `(api: OpenClawPluginApi) => void` | No | — |
|
||||
|
||||
OpenClaw can load plugins in setup-focused registration modes. `registerFull`
|
||||
lets a channel plugin skip extra runtime-only registrations such as tools while
|
||||
still registering the channel capability itself.
|
||||
- `setRuntime` is called during registration so you can store the runtime reference
|
||||
(typically via `createPluginRuntimeStore`).
|
||||
- `registerFull` only runs when `api.registrationMode === "full"`. It is skipped
|
||||
during setup-only loading.
|
||||
|
||||
Use it for:
|
||||
## `defineSetupPluginEntry`
|
||||
|
||||
- agent tools
|
||||
- gateway-only routes
|
||||
- runtime-only commands
|
||||
**Import:** `openclaw/plugin-sdk/core`
|
||||
|
||||
Do not use it for the actual `ChannelPlugin`; that belongs in `plugin: ...`.
|
||||
For the lightweight `setup-entry.ts` file. Returns just `{ plugin }` with no
|
||||
runtime or CLI wiring.
|
||||
|
||||
## `defineSetupPluginEntry(...)`
|
||||
|
||||
Use this when a channel ships a second module for setup flows.
|
||||
|
||||
```ts
|
||||
```typescript
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { exampleSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default defineSetupPluginEntry(exampleSetupPlugin);
|
||||
export default defineSetupPluginEntry(myChannelPlugin);
|
||||
```
|
||||
|
||||
This keeps the setup entry shape explicit and matches the bundled channel
|
||||
pattern used in OpenClaw.
|
||||
OpenClaw loads this instead of the full entry when a channel is disabled,
|
||||
unconfigured, or when deferred loading is enabled. See
|
||||
[Setup and Config](/plugins/sdk-setup#setup-entry) for when this matters.
|
||||
|
||||
## One plugin, many capabilities
|
||||
## Registration mode
|
||||
|
||||
A single entry file can register multiple capabilities:
|
||||
`api.registrationMode` tells your plugin how it was loaded:
|
||||
|
||||
```ts
|
||||
import { definePluginEntry, type OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
||||
| Mode | When | What to register |
|
||||
| ----------------- | --------------------------------- | ----------------------------- |
|
||||
| `"full"` | Normal gateway startup | Everything |
|
||||
| `"setup-only"` | Disabled/unconfigured channel | Channel registration only |
|
||||
| `"setup-runtime"` | Setup flow with runtime available | Channel + lightweight runtime |
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "example-hybrid",
|
||||
name: "Example Hybrid",
|
||||
description: "Provider plus tools",
|
||||
register(api: OpenClawPluginApi) {
|
||||
api.registerProvider({
|
||||
id: "example",
|
||||
label: "Example",
|
||||
auth: [],
|
||||
});
|
||||
`defineChannelPluginEntry` handles this split automatically. If you use
|
||||
`definePluginEntry` directly for a channel, check mode yourself:
|
||||
|
||||
api.registerTool({
|
||||
name: "example_ping",
|
||||
description: "Simple health check",
|
||||
parameters: { type: "object", properties: {} },
|
||||
async execute() {
|
||||
return { content: [{ type: "text", text: "pong" }] };
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
```typescript
|
||||
register(api) {
|
||||
api.registerChannel({ plugin: myPlugin });
|
||||
if (api.registrationMode !== "full") return;
|
||||
|
||||
// Heavy runtime-only registrations
|
||||
api.registerCli(/* ... */);
|
||||
api.registerService(/* ... */);
|
||||
}
|
||||
```
|
||||
|
||||
## Entry-file checklist
|
||||
## Plugin shapes
|
||||
|
||||
- Give the plugin a stable `id`.
|
||||
- Keep `name` and `description` human-readable.
|
||||
- Put schema at the entry level when the plugin has config.
|
||||
- Register only public capabilities inside `register(api)`.
|
||||
- Keep channel plugins on `plugin-sdk/core`.
|
||||
- Keep non-channel plugins on `plugin-sdk/plugin-entry`.
|
||||
OpenClaw classifies loaded plugins by their registration behavior:
|
||||
|
||||
| Shape | Description |
|
||||
| --------------------- | -------------------------------------------------- |
|
||||
| **plain-capability** | One capability type (e.g. provider-only) |
|
||||
| **hybrid-capability** | Multiple capability types (e.g. provider + speech) |
|
||||
| **hook-only** | Only hooks, no capabilities |
|
||||
| **non-capability** | Tools/commands/services but no capabilities |
|
||||
|
||||
Use `openclaw plugins inspect <id>` to see a plugin's shape.
|
||||
|
||||
## Related
|
||||
|
||||
- [Plugin SDK Overview](/plugins/sdk-overview)
|
||||
- [Plugin Runtime](/plugins/sdk-runtime)
|
||||
- [Channel Plugin SDK](/plugins/sdk-channel-plugins)
|
||||
- [Provider Plugin SDK](/plugins/sdk-provider-plugins)
|
||||
- [SDK Overview](/plugins/sdk-overview) — registration API and subpath reference
|
||||
- [Runtime Helpers](/plugins/sdk-runtime) — `api.runtime` and `createPluginRuntimeStore`
|
||||
- [Setup and Config](/plugins/sdk-setup) — manifest, setup entry, deferred loading
|
||||
- [Channel Plugins](/plugins/sdk-channel-plugins) — building the `ChannelPlugin` object
|
||||
- [Provider Plugins](/plugins/sdk-provider-plugins) — provider registration and hooks
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "Plugin SDK Migration"
|
||||
sidebarTitle: "SDK Migration"
|
||||
sidebarTitle: "Migrate to SDK"
|
||||
summary: "Migrate from the legacy backwards-compatibility layer to the modern plugin SDK"
|
||||
read_when:
|
||||
- You see the OPENCLAW_PLUGIN_SDK_COMPAT_DEPRECATED warning
|
||||
@@ -164,7 +164,9 @@ This is a temporary escape hatch, not a permanent solution.
|
||||
|
||||
## Related
|
||||
|
||||
- [Building Plugins](/plugins/building-plugins)
|
||||
- [Plugin SDK Overview](/plugins/sdk-overview)
|
||||
- [Plugin Internals](/plugins/architecture)
|
||||
- [Plugin Manifest](/plugins/manifest)
|
||||
- [Getting Started](/plugins/building-plugins) — build your first plugin
|
||||
- [SDK Overview](/plugins/sdk-overview) — full subpath import reference
|
||||
- [Channel Plugins](/plugins/sdk-channel-plugins) — building channel plugins
|
||||
- [Provider Plugins](/plugins/sdk-provider-plugins) — building provider plugins
|
||||
- [Plugin Internals](/plugins/architecture) — architecture deep dive
|
||||
- [Plugin Manifest](/plugins/manifest) — manifest schema reference
|
||||
|
||||
@@ -1,175 +1,200 @@
|
||||
---
|
||||
title: "Plugin SDK Overview"
|
||||
sidebarTitle: "SDK Overview"
|
||||
summary: "How the OpenClaw plugin SDK is organized, which subpaths are stable, and how to choose the right import"
|
||||
summary: "Import map, registration API reference, and SDK architecture"
|
||||
read_when:
|
||||
- You are starting a new OpenClaw plugin
|
||||
- You need to choose the right plugin-sdk subpath
|
||||
- You are replacing deprecated compat imports
|
||||
- You need to know which SDK subpath to import from
|
||||
- You want a reference for all registration methods on OpenClawPluginApi
|
||||
- You are looking up a specific SDK export
|
||||
---
|
||||
|
||||
# Plugin SDK Overview
|
||||
|
||||
The OpenClaw plugin SDK is split into **small public subpaths** under
|
||||
`openclaw/plugin-sdk/<subpath>`.
|
||||
The plugin SDK is the typed contract between plugins and core. This page is the
|
||||
reference for **what to import** and **what you can register**.
|
||||
|
||||
Use the narrowest import that matches the job. That keeps plugin dependencies
|
||||
small, avoids circular imports, and makes it clear which contract you depend on.
|
||||
<Tip>
|
||||
**Looking for a how-to guide?**
|
||||
- First plugin? Start with [Getting Started](/plugins/building-plugins)
|
||||
- Channel plugin? See [Channel Plugins](/plugins/sdk-channel-plugins)
|
||||
- Provider plugin? See [Provider Plugins](/plugins/sdk-provider-plugins)
|
||||
</Tip>
|
||||
|
||||
## Rules first
|
||||
## Import convention
|
||||
|
||||
- Use focused imports such as `openclaw/plugin-sdk/plugin-entry`.
|
||||
- Do not import the root `openclaw/plugin-sdk` barrel in new code.
|
||||
- Do not import `openclaw/extension-api` in new code.
|
||||
- Do not import `src/**` from plugin packages.
|
||||
- Inside a plugin package, route internal imports through local files such as
|
||||
`./api.ts` or `./runtime-api.ts`, not through the published SDK path for that
|
||||
same plugin.
|
||||
Always import from a specific subpath:
|
||||
|
||||
## SDK map
|
||||
```typescript
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
|
||||
| Job | Subpath | Next page |
|
||||
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
|
||||
| Define plugin entry modules | `plugin-sdk/plugin-entry`, `plugin-sdk/core` | [Plugin Entry Points](/plugins/sdk-entrypoints) |
|
||||
| Use injected runtime helpers | `plugin-sdk/runtime`, `plugin-sdk/runtime-store` | [Plugin Runtime](/plugins/sdk-runtime) |
|
||||
| Build setup/configure flows | `plugin-sdk/setup`, `plugin-sdk/channel-setup`, `plugin-sdk/secret-input` | [Plugin Setup](/plugins/sdk-setup) |
|
||||
| Build channel plugins | `plugin-sdk/core`, `plugin-sdk/channel-contract`, `plugin-sdk/channel-actions`, `plugin-sdk/channel-pairing` | [Channel Plugin SDK](/plugins/sdk-channel-plugins) |
|
||||
| Build provider plugins | `plugin-sdk/plugin-entry`, `plugin-sdk/provider-auth`, `plugin-sdk/provider-onboard`, `plugin-sdk/provider-models`, `plugin-sdk/provider-usage` | [Provider Plugin SDK](/plugins/sdk-provider-plugins) |
|
||||
| Test plugin code | `plugin-sdk/testing` | [Plugin SDK Testing](/plugins/sdk-testing) |
|
||||
// Deprecated — will be removed in the next major release
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk";
|
||||
```
|
||||
|
||||
## Typical plugin layout
|
||||
Each subpath is a small, self-contained module. This keeps startup fast and
|
||||
prevents circular dependency issues.
|
||||
|
||||
```text
|
||||
## Subpath reference
|
||||
|
||||
The most commonly used subpaths, grouped by purpose. The full list of 100+
|
||||
subpaths is in `scripts/lib/plugin-sdk-entrypoints.json`.
|
||||
|
||||
### Plugin entry
|
||||
|
||||
| Subpath | Key exports |
|
||||
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `plugin-sdk/plugin-entry` | `definePluginEntry` |
|
||||
| `plugin-sdk/core` | `defineChannelPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase`, `defineSetupPluginEntry`, `buildChannelConfigSchema` |
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Channel subpaths">
|
||||
| Subpath | Key exports |
|
||||
| --- | --- |
|
||||
| `plugin-sdk/channel-setup` | `createOptionalChannelSetupSurface` |
|
||||
| `plugin-sdk/channel-pairing` | `createChannelPairingController` |
|
||||
| `plugin-sdk/channel-reply-pipeline` | `createChannelReplyPipeline` |
|
||||
| `plugin-sdk/channel-config-helpers` | `createHybridChannelConfigAdapter` |
|
||||
| `plugin-sdk/channel-config-schema` | Channel config schema types |
|
||||
| `plugin-sdk/channel-policy` | `resolveChannelGroupRequireMention` |
|
||||
| `plugin-sdk/channel-lifecycle` | `createAccountStatusSink` |
|
||||
| `plugin-sdk/channel-inbound` | Debounce, mention matching, envelope helpers |
|
||||
| `plugin-sdk/channel-send-result` | Reply result types |
|
||||
| `plugin-sdk/channel-actions` | `createMessageToolButtonsSchema`, `createMessageToolCardSchema` |
|
||||
| `plugin-sdk/channel-targets` | Target parsing/matching helpers |
|
||||
| `plugin-sdk/channel-contract` | Channel contract types |
|
||||
| `plugin-sdk/channel-feedback` | Feedback/reaction wiring |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Provider subpaths">
|
||||
| Subpath | Key exports |
|
||||
| --- | --- |
|
||||
| `plugin-sdk/provider-auth` | `createProviderApiKeyAuthMethod`, `ensureApiKeyFromOptionEnvOrPrompt`, `upsertAuthProfile` |
|
||||
| `plugin-sdk/provider-models` | `normalizeModelCompat` |
|
||||
| `plugin-sdk/provider-catalog` | Catalog type re-exports |
|
||||
| `plugin-sdk/provider-usage` | `fetchClaudeUsage` and similar |
|
||||
| `plugin-sdk/provider-stream` | Stream wrapper types |
|
||||
| `plugin-sdk/provider-onboard` | Onboarding config patch helpers |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Auth and security subpaths">
|
||||
| Subpath | Key exports |
|
||||
| --- | --- |
|
||||
| `plugin-sdk/command-auth` | `resolveControlCommandGate` |
|
||||
| `plugin-sdk/allow-from` | `formatAllowFromLowercase` |
|
||||
| `plugin-sdk/secret-input` | Secret input parsing helpers |
|
||||
| `plugin-sdk/webhook-ingress` | Webhook request/target helpers |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Runtime and storage subpaths">
|
||||
| Subpath | Key exports |
|
||||
| --- | --- |
|
||||
| `plugin-sdk/runtime-store` | `createPluginRuntimeStore` |
|
||||
| `plugin-sdk/config-runtime` | Config load/write helpers |
|
||||
| `plugin-sdk/infra-runtime` | System event/heartbeat helpers |
|
||||
| `plugin-sdk/agent-runtime` | Agent dir/identity/workspace helpers |
|
||||
| `plugin-sdk/directory-runtime` | Config-backed directory query/dedup |
|
||||
| `plugin-sdk/keyed-async-queue` | `KeyedAsyncQueue` |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Capability and testing subpaths">
|
||||
| Subpath | Key exports |
|
||||
| --- | --- |
|
||||
| `plugin-sdk/image-generation` | Image generation provider types |
|
||||
| `plugin-sdk/media-understanding` | Media understanding provider types |
|
||||
| `plugin-sdk/speech` | Speech provider types |
|
||||
| `plugin-sdk/testing` | `installCommonResolveTargetErrorCases`, `shouldAckReaction` |
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Registration API
|
||||
|
||||
The `register(api)` callback receives an `OpenClawPluginApi` object with these
|
||||
methods:
|
||||
|
||||
### Capability registration
|
||||
|
||||
| Method | What it registers |
|
||||
| --------------------------------------------- | ------------------------------ |
|
||||
| `api.registerProvider(...)` | Text inference (LLM) |
|
||||
| `api.registerChannel(...)` | Messaging channel |
|
||||
| `api.registerSpeechProvider(...)` | Text-to-speech / STT synthesis |
|
||||
| `api.registerMediaUnderstandingProvider(...)` | Image/audio/video analysis |
|
||||
| `api.registerImageGenerationProvider(...)` | Image generation |
|
||||
| `api.registerWebSearchProvider(...)` | Web search |
|
||||
|
||||
### Tools and commands
|
||||
|
||||
| Method | What it registers |
|
||||
| ------------------------------- | --------------------------------------------- |
|
||||
| `api.registerTool(tool, opts?)` | Agent tool (required or `{ optional: true }`) |
|
||||
| `api.registerCommand(def)` | Custom command (bypasses the LLM) |
|
||||
|
||||
### Infrastructure
|
||||
|
||||
| Method | What it registers |
|
||||
| ---------------------------------------------- | --------------------- |
|
||||
| `api.registerHook(events, handler, opts?)` | Event hook |
|
||||
| `api.registerHttpRoute(params)` | Gateway HTTP endpoint |
|
||||
| `api.registerGatewayMethod(name, handler)` | Gateway RPC method |
|
||||
| `api.registerCli(registrar, opts?)` | CLI subcommand |
|
||||
| `api.registerService(service)` | Background service |
|
||||
| `api.registerInteractiveHandler(registration)` | Interactive handler |
|
||||
|
||||
### Exclusive slots
|
||||
|
||||
| Method | What it registers |
|
||||
| ------------------------------------------ | ------------------------------------- |
|
||||
| `api.registerContextEngine(id, factory)` | Context engine (one active at a time) |
|
||||
| `api.registerMemoryPromptSection(builder)` | Memory prompt section builder |
|
||||
|
||||
### Events and lifecycle
|
||||
|
||||
| Method | What it does |
|
||||
| -------------------------------------------- | ----------------------------- |
|
||||
| `api.on(hookName, handler, opts?)` | Typed lifecycle hook |
|
||||
| `api.onConversationBindingResolved(handler)` | Conversation binding callback |
|
||||
|
||||
### API object fields
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------------ | ------------------------- | --------------------------------------------------------- |
|
||||
| `api.id` | `string` | Plugin id |
|
||||
| `api.name` | `string` | Display name |
|
||||
| `api.version` | `string?` | Plugin version (optional) |
|
||||
| `api.description` | `string?` | Plugin description (optional) |
|
||||
| `api.source` | `string` | Plugin source path |
|
||||
| `api.rootDir` | `string?` | Plugin root directory (optional) |
|
||||
| `api.config` | `OpenClawConfig` | Current config snapshot |
|
||||
| `api.pluginConfig` | `Record<string, unknown>` | Plugin-specific config from `plugins.entries.<id>.config` |
|
||||
| `api.runtime` | `PluginRuntime` | [Runtime helpers](/plugins/sdk-runtime) |
|
||||
| `api.logger` | `PluginLogger` | Scoped logger (`debug`, `info`, `warn`, `error`) |
|
||||
| `api.registrationMode` | `PluginRegistrationMode` | `"full"`, `"setup-only"`, or `"setup-runtime"` |
|
||||
| `api.resolvePath(input)` | `(string) => string` | Resolve path relative to plugin root |
|
||||
|
||||
## Internal module convention
|
||||
|
||||
Within your plugin, use local barrel files for internal imports:
|
||||
|
||||
```
|
||||
my-plugin/
|
||||
├── package.json
|
||||
├── openclaw.plugin.json
|
||||
├── index.ts
|
||||
├── setup-entry.ts
|
||||
├── api.ts
|
||||
├── runtime-api.ts
|
||||
└── src/
|
||||
├── provider.ts
|
||||
├── setup.ts
|
||||
└── provider.test.ts
|
||||
api.ts # Public exports for external consumers
|
||||
runtime-api.ts # Internal-only runtime exports
|
||||
index.ts # Plugin entry point
|
||||
setup-entry.ts # Lightweight setup-only entry (optional)
|
||||
```
|
||||
|
||||
```ts
|
||||
// api.ts
|
||||
export {
|
||||
definePluginEntry,
|
||||
type OpenClawPluginApi,
|
||||
type ProviderAuthContext,
|
||||
type ProviderAuthResult,
|
||||
} from "openclaw/plugin-sdk/plugin-entry";
|
||||
```
|
||||
|
||||
## What belongs where
|
||||
|
||||
### Entry helpers
|
||||
|
||||
- `plugin-sdk/plugin-entry` is the default entry surface for providers, tools,
|
||||
commands, services, memory plugins, and context engines.
|
||||
- `plugin-sdk/core` adds channel-focused helpers such as
|
||||
`defineChannelPluginEntry(...)`.
|
||||
|
||||
### Runtime helpers
|
||||
|
||||
- Use `api.runtime.*` for trusted in-process helpers that OpenClaw injects at
|
||||
registration time.
|
||||
- Use `plugin-sdk/runtime-store` when plugin modules need a mutable runtime slot
|
||||
that is initialized later.
|
||||
|
||||
### Setup helpers
|
||||
|
||||
- `plugin-sdk/setup` contains shared setup-wizard helpers and config patch
|
||||
helpers.
|
||||
- `plugin-sdk/channel-setup` contains channel-specific setup adapters.
|
||||
- `plugin-sdk/secret-input` exposes the shared secret-input schema helpers.
|
||||
|
||||
### Channel helpers
|
||||
|
||||
- `plugin-sdk/channel-contract` exports pure channel types.
|
||||
- `plugin-sdk/channel-actions` covers shared `message` tool schema helpers.
|
||||
- `plugin-sdk/channel-pairing` covers pairing approval flows.
|
||||
- `plugin-sdk/webhook-ingress` covers plugin-owned webhook routes.
|
||||
|
||||
### Provider helpers
|
||||
|
||||
- `plugin-sdk/provider-auth` covers auth flows and credential helpers.
|
||||
- `plugin-sdk/provider-onboard` covers config patches after auth/setup.
|
||||
- `plugin-sdk/provider-models` covers catalog and model-definition helpers.
|
||||
- `plugin-sdk/provider-usage` covers usage snapshot helpers.
|
||||
- `plugin-sdk/provider-setup` and `plugin-sdk/self-hosted-provider-setup`
|
||||
cover self-hosted and local-model onboarding.
|
||||
|
||||
## Example: mixing subpaths in one plugin
|
||||
|
||||
```ts
|
||||
import { definePluginEntry, type OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { createProviderApiKeyAuthMethod } from "openclaw/plugin-sdk/provider-auth";
|
||||
import { applyProviderConfigWithDefaultModel } from "openclaw/plugin-sdk/provider-onboard";
|
||||
import { buildSecretInputSchema } from "openclaw/plugin-sdk/secret-input";
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "example-provider",
|
||||
name: "Example Provider",
|
||||
description: "Small provider plugin example",
|
||||
configSchema: {
|
||||
jsonSchema: {
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
apiKey: { type: "string" },
|
||||
},
|
||||
},
|
||||
safeParse(value) {
|
||||
return buildSecretInputSchema().safeParse((value as { apiKey?: unknown })?.apiKey);
|
||||
},
|
||||
},
|
||||
register(api: OpenClawPluginApi) {
|
||||
api.registerProvider({
|
||||
id: "example",
|
||||
label: "Example",
|
||||
auth: [
|
||||
createProviderApiKeyAuthMethod({
|
||||
providerId: "example",
|
||||
methodId: "api-key",
|
||||
label: "Example API key",
|
||||
optionKey: "exampleApiKey",
|
||||
flagName: "--example-api-key",
|
||||
envVar: "EXAMPLE_API_KEY",
|
||||
promptMessage: "Enter Example API key",
|
||||
profileId: "example:default",
|
||||
defaultModel: "example/default",
|
||||
applyConfig: (cfg) =>
|
||||
applyProviderConfigWithDefaultModel(cfg, "example", {
|
||||
id: "default",
|
||||
name: "Default",
|
||||
}),
|
||||
}),
|
||||
],
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Choose the smallest public seam
|
||||
|
||||
If a helper exists on a focused subpath, prefer that over a broader runtime
|
||||
surface.
|
||||
|
||||
- Prefer `plugin-sdk/provider-auth` over reaching into unrelated provider files.
|
||||
- Prefer `plugin-sdk/channel-contract` for types in tests and helper modules.
|
||||
- Prefer `plugin-sdk/runtime-store` over custom mutable globals.
|
||||
- Prefer `plugin-sdk/testing` for shared test fixtures.
|
||||
<Warning>
|
||||
Never import your own plugin through `openclaw/plugin-sdk/<your-plugin>`
|
||||
from production code. Route internal imports through `./api.ts` or
|
||||
`./runtime-api.ts`. The SDK path is the external contract only.
|
||||
</Warning>
|
||||
|
||||
## Related
|
||||
|
||||
- [Building Plugins](/plugins/building-plugins)
|
||||
- [Plugin Entry Points](/plugins/sdk-entrypoints)
|
||||
- [Plugin Runtime](/plugins/sdk-runtime)
|
||||
- [Plugin Setup](/plugins/sdk-setup)
|
||||
- [Channel Plugin SDK](/plugins/sdk-channel-plugins)
|
||||
- [Provider Plugin SDK](/plugins/sdk-provider-plugins)
|
||||
- [Plugin SDK Testing](/plugins/sdk-testing)
|
||||
- [Plugin SDK Migration](/plugins/sdk-migration)
|
||||
- [Entry Points](/plugins/sdk-entrypoints) — `definePluginEntry` and `defineChannelPluginEntry` options
|
||||
- [Runtime Helpers](/plugins/sdk-runtime) — full `api.runtime` namespace reference
|
||||
- [Setup and Config](/plugins/sdk-setup) — packaging, manifests, config schemas
|
||||
- [Testing](/plugins/sdk-testing) — test utilities and lint rules
|
||||
- [SDK Migration](/plugins/sdk-migration) — migrating from deprecated surfaces
|
||||
- [Plugin Internals](/plugins/architecture) — deep architecture and capability model
|
||||
|
||||
@@ -1,184 +1,415 @@
|
||||
---
|
||||
title: "Provider Plugin SDK"
|
||||
title: "Building Provider Plugins"
|
||||
sidebarTitle: "Provider Plugins"
|
||||
summary: "Contracts and helper subpaths for model-provider plugins, including auth, onboarding, catalogs, and usage"
|
||||
summary: "Step-by-step guide to building a model provider plugin for OpenClaw"
|
||||
read_when:
|
||||
- You are building a model provider plugin
|
||||
- You need auth helpers for API keys or OAuth
|
||||
- You need onboarding config patches or catalog helpers
|
||||
- You are building a new model provider plugin
|
||||
- You want to add an OpenAI-compatible proxy or custom LLM to OpenClaw
|
||||
- You need to understand provider auth, catalogs, and runtime hooks
|
||||
---
|
||||
|
||||
# Provider Plugin SDK
|
||||
# Building Provider Plugins
|
||||
|
||||
Provider plugins use `definePluginEntry(...)` and call `api.registerProvider(...)`
|
||||
with a `ProviderPlugin` definition.
|
||||
This guide walks through building a provider plugin that adds a model provider
|
||||
(LLM) to OpenClaw. By the end you will have a provider with a model catalog,
|
||||
API key auth, and dynamic model resolution.
|
||||
|
||||
## Minimal provider entry
|
||||
<Info>
|
||||
If you have not built any OpenClaw plugin before, read
|
||||
[Getting Started](/plugins/building-plugins) first for the basic package
|
||||
structure and manifest setup.
|
||||
</Info>
|
||||
|
||||
```ts
|
||||
import { definePluginEntry, type OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
||||
## Walkthrough
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "example-provider",
|
||||
name: "Example Provider",
|
||||
description: "Example text-inference provider plugin",
|
||||
register(api: OpenClawPluginApi) {
|
||||
api.registerProvider({
|
||||
id: "example",
|
||||
label: "Example",
|
||||
auth: [],
|
||||
<Steps>
|
||||
<Step title="Package and manifest">
|
||||
<CodeGroup>
|
||||
```json package.json
|
||||
{
|
||||
"name": "@myorg/openclaw-acme-ai",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"openclaw": {
|
||||
"extensions": ["./index.ts"],
|
||||
"providers": ["acme-ai"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json openclaw.plugin.json
|
||||
{
|
||||
"id": "acme-ai",
|
||||
"name": "Acme AI",
|
||||
"description": "Acme AI model provider",
|
||||
"providers": ["acme-ai"],
|
||||
"providerAuthEnvVars": {
|
||||
"acme-ai": ["ACME_AI_API_KEY"]
|
||||
},
|
||||
"providerAuthChoices": [
|
||||
{
|
||||
"provider": "acme-ai",
|
||||
"method": "api-key",
|
||||
"choiceId": "acme-ai-api-key",
|
||||
"choiceLabel": "Acme AI API key",
|
||||
"groupId": "acme-ai",
|
||||
"groupLabel": "Acme AI",
|
||||
"cliFlag": "--acme-ai-api-key",
|
||||
"cliOption": "--acme-ai-api-key <key>",
|
||||
"cliDescription": "Acme AI API key"
|
||||
}
|
||||
],
|
||||
"configSchema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
The manifest declares `providerAuthEnvVars` so OpenClaw can detect
|
||||
credentials without loading your plugin runtime.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Register the provider">
|
||||
A minimal provider needs an `id`, `label`, `auth`, and `catalog`:
|
||||
|
||||
```typescript index.ts
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { createProviderApiKeyAuthMethod } from "openclaw/plugin-sdk/provider-auth";
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "acme-ai",
|
||||
name: "Acme AI",
|
||||
description: "Acme AI model provider",
|
||||
register(api) {
|
||||
api.registerProvider({
|
||||
id: "acme-ai",
|
||||
label: "Acme AI",
|
||||
docsPath: "/providers/acme-ai",
|
||||
envVars: ["ACME_AI_API_KEY"],
|
||||
|
||||
auth: [
|
||||
createProviderApiKeyAuthMethod({
|
||||
providerId: "acme-ai",
|
||||
methodId: "api-key",
|
||||
label: "Acme AI API key",
|
||||
hint: "API key from your Acme AI dashboard",
|
||||
optionKey: "acmeAiApiKey",
|
||||
flagName: "--acme-ai-api-key",
|
||||
envVar: "ACME_AI_API_KEY",
|
||||
promptMessage: "Enter your Acme AI API key",
|
||||
defaultModel: "acme-ai/acme-large",
|
||||
}),
|
||||
],
|
||||
|
||||
catalog: {
|
||||
order: "simple",
|
||||
run: async (ctx) => {
|
||||
const apiKey =
|
||||
ctx.resolveProviderApiKey("acme-ai").apiKey;
|
||||
if (!apiKey) return null;
|
||||
return {
|
||||
provider: {
|
||||
baseUrl: "https://api.acme-ai.com/v1",
|
||||
apiKey,
|
||||
api: "openai-completions",
|
||||
models: [
|
||||
{
|
||||
id: "acme-large",
|
||||
name: "Acme Large",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
||||
contextWindow: 200000,
|
||||
maxTokens: 32768,
|
||||
},
|
||||
{
|
||||
id: "acme-small",
|
||||
name: "Acme Small",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 },
|
||||
contextWindow: 128000,
|
||||
maxTokens: 8192,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
That is a working provider. Users can now
|
||||
`openclaw onboard --acme-ai-api-key <key>` and select
|
||||
`acme-ai/acme-large` as their model.
|
||||
|
||||
For bundled providers that only register one text provider with API-key
|
||||
auth plus a single catalog-backed runtime, prefer the narrower
|
||||
`defineSingleProviderPluginEntry(...)` helper:
|
||||
|
||||
```typescript
|
||||
import { defineSingleProviderPluginEntry } from "openclaw/plugin-sdk/provider-entry";
|
||||
|
||||
export default defineSingleProviderPluginEntry({
|
||||
id: "acme-ai",
|
||||
name: "Acme AI",
|
||||
description: "Acme AI model provider",
|
||||
provider: {
|
||||
label: "Acme AI",
|
||||
docsPath: "/providers/acme-ai",
|
||||
auth: [
|
||||
{
|
||||
methodId: "api-key",
|
||||
label: "Acme AI API key",
|
||||
hint: "API key from your Acme AI dashboard",
|
||||
optionKey: "acmeAiApiKey",
|
||||
flagName: "--acme-ai-api-key",
|
||||
envVar: "ACME_AI_API_KEY",
|
||||
promptMessage: "Enter your Acme AI API key",
|
||||
defaultModel: "acme-ai/acme-large",
|
||||
},
|
||||
],
|
||||
catalog: {
|
||||
buildProvider: () => ({
|
||||
api: "openai-completions",
|
||||
baseUrl: "https://api.acme-ai.com/v1",
|
||||
models: [{ id: "acme-large", name: "Acme Large" }],
|
||||
}),
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
If your auth flow also needs to patch `models.providers.*`, aliases, and
|
||||
the agent default model during onboarding, use the preset helpers from
|
||||
`openclaw/plugin-sdk/provider-onboard`. The narrowest helpers are
|
||||
`createDefaultModelPresetAppliers(...)`,
|
||||
`createDefaultModelsPresetAppliers(...)`, and
|
||||
`createModelCatalogPresetAppliers(...)`.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Add dynamic model resolution">
|
||||
If your provider accepts arbitrary model IDs (like a proxy or router),
|
||||
add `resolveDynamicModel`:
|
||||
|
||||
```typescript
|
||||
api.registerProvider({
|
||||
// ... id, label, auth, catalog from above
|
||||
|
||||
resolveDynamicModel: (ctx) => ({
|
||||
id: ctx.modelId,
|
||||
name: ctx.modelId,
|
||||
provider: "acme-ai",
|
||||
api: "openai-completions",
|
||||
baseUrl: "https://api.acme-ai.com/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 128000,
|
||||
maxTokens: 8192,
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
If resolving requires a network call, use `prepareDynamicModel` for async
|
||||
warm-up — `resolveDynamicModel` runs again after it completes.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Add runtime hooks (as needed)">
|
||||
Most providers only need `catalog` + `resolveDynamicModel`. Add hooks
|
||||
incrementally as your provider requires them.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Token exchange">
|
||||
For providers that need a token exchange before each inference call:
|
||||
|
||||
```typescript
|
||||
prepareRuntimeAuth: async (ctx) => {
|
||||
const exchanged = await exchangeToken(ctx.apiKey);
|
||||
return {
|
||||
apiKey: exchanged.token,
|
||||
baseUrl: exchanged.baseUrl,
|
||||
expiresAt: exchanged.expiresAt,
|
||||
};
|
||||
},
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Custom headers">
|
||||
For providers that need custom request headers or body modifications:
|
||||
|
||||
```typescript
|
||||
// wrapStreamFn returns a StreamFn derived from ctx.streamFn
|
||||
wrapStreamFn: (ctx) => {
|
||||
if (!ctx.streamFn) return undefined;
|
||||
const inner = ctx.streamFn;
|
||||
return async (params) => {
|
||||
params.headers = {
|
||||
...params.headers,
|
||||
"X-Acme-Version": "2",
|
||||
};
|
||||
return inner(params);
|
||||
};
|
||||
},
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Usage and billing">
|
||||
For providers that expose usage/billing data:
|
||||
|
||||
```typescript
|
||||
resolveUsageAuth: async (ctx) => {
|
||||
const auth = await ctx.resolveOAuthToken();
|
||||
return auth ? { token: auth.token } : null;
|
||||
},
|
||||
fetchUsageSnapshot: async (ctx) => {
|
||||
return await fetchAcmeUsage(ctx.token, ctx.timeoutMs);
|
||||
},
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Accordion title="All available provider hooks">
|
||||
OpenClaw calls hooks in this order. Most providers only use 2-3:
|
||||
|
||||
| # | Hook | When to use |
|
||||
| --- | --- | --- |
|
||||
| 1 | `catalog` | Model catalog or base URL defaults |
|
||||
| 2 | `resolveDynamicModel` | Accept arbitrary upstream model IDs |
|
||||
| 3 | `prepareDynamicModel` | Async metadata fetch before resolving |
|
||||
| 4 | `normalizeResolvedModel` | Transport rewrites before the runner |
|
||||
| 5 | `capabilities` | Transcript/tooling metadata (data, not callable) |
|
||||
| 6 | `prepareExtraParams` | Default request params |
|
||||
| 7 | `wrapStreamFn` | Custom headers/body wrappers |
|
||||
| 8 | `formatApiKey` | Custom runtime token shape |
|
||||
| 9 | `refreshOAuth` | Custom OAuth refresh |
|
||||
| 10 | `buildAuthDoctorHint` | Auth repair guidance |
|
||||
| 11 | `isCacheTtlEligible` | Prompt cache TTL gating |
|
||||
| 12 | `buildMissingAuthMessage` | Custom missing-auth hint |
|
||||
| 13 | `suppressBuiltInModel` | Hide stale upstream rows |
|
||||
| 14 | `augmentModelCatalog` | Synthetic forward-compat rows |
|
||||
| 15 | `isBinaryThinking` | Binary thinking on/off |
|
||||
| 16 | `supportsXHighThinking` | `xhigh` reasoning support |
|
||||
| 17 | `resolveDefaultThinkingLevel` | Default `/think` policy |
|
||||
| 18 | `isModernModelRef` | Live/smoke model matching |
|
||||
| 19 | `prepareRuntimeAuth` | Token exchange before inference |
|
||||
| 20 | `resolveUsageAuth` | Custom usage credential parsing |
|
||||
| 21 | `fetchUsageSnapshot` | Custom usage endpoint |
|
||||
| 22 | `onModelSelected` | Post-selection callback (e.g. telemetry) |
|
||||
|
||||
For detailed descriptions and real-world examples, see
|
||||
[Internals: Provider Runtime Hooks](/plugins/architecture#provider-runtime-hooks).
|
||||
</Accordion>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Add extra capabilities (optional)">
|
||||
A provider plugin can register speech, media understanding, image
|
||||
generation, and web search alongside text inference:
|
||||
|
||||
```typescript
|
||||
register(api) {
|
||||
api.registerProvider({ id: "acme-ai", /* ... */ });
|
||||
|
||||
api.registerSpeechProvider({
|
||||
id: "acme-ai",
|
||||
label: "Acme Speech",
|
||||
isConfigured: ({ config }) => Boolean(config.messages?.tts),
|
||||
synthesize: async (req) => ({
|
||||
audioBuffer: Buffer.from(/* PCM data */),
|
||||
outputFormat: "mp3",
|
||||
fileExtension: ".mp3",
|
||||
voiceCompatible: false,
|
||||
}),
|
||||
});
|
||||
|
||||
api.registerMediaUnderstandingProvider({
|
||||
id: "acme-ai",
|
||||
capabilities: ["image", "audio"],
|
||||
describeImage: async (req) => ({ text: "A photo of..." }),
|
||||
transcribeAudio: async (req) => ({ text: "Transcript..." }),
|
||||
});
|
||||
|
||||
api.registerImageGenerationProvider({
|
||||
id: "acme-ai",
|
||||
label: "Acme Images",
|
||||
generate: async (req) => ({ /* image result */ }),
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
OpenClaw classifies this as a **hybrid-capability** plugin. This is the
|
||||
recommended pattern for company plugins (one plugin per vendor). See
|
||||
[Internals: Capability Ownership](/plugins/architecture#capability-ownership-model).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Test">
|
||||
```typescript src/provider.test.ts
|
||||
import { describe, it, expect } from "vitest";
|
||||
// Export your provider config object from index.ts or a dedicated file
|
||||
import { acmeProvider } from "./provider.js";
|
||||
|
||||
describe("acme-ai provider", () => {
|
||||
it("resolves dynamic models", () => {
|
||||
const model = acmeProvider.resolveDynamicModel!({
|
||||
modelId: "acme-beta-v3",
|
||||
} as any);
|
||||
expect(model.id).toBe("acme-beta-v3");
|
||||
expect(model.provider).toBe("acme-ai");
|
||||
});
|
||||
|
||||
it("returns catalog when key is available", async () => {
|
||||
const result = await acmeProvider.catalog!.run({
|
||||
resolveProviderApiKey: () => ({ apiKey: "test-key" }),
|
||||
} as any);
|
||||
expect(result?.provider?.models).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("returns null catalog when no key", async () => {
|
||||
const result = await acmeProvider.catalog!.run({
|
||||
resolveProviderApiKey: () => ({ apiKey: undefined }),
|
||||
} as any);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## File structure
|
||||
|
||||
```
|
||||
extensions/acme-ai/
|
||||
├── package.json # openclaw.providers metadata
|
||||
├── openclaw.plugin.json # Manifest with providerAuthEnvVars
|
||||
├── index.ts # definePluginEntry + registerProvider
|
||||
└── src/
|
||||
├── provider.test.ts # Tests
|
||||
└── usage.ts # Usage endpoint (optional)
|
||||
```
|
||||
|
||||
## Provider subpaths
|
||||
## Catalog order reference
|
||||
|
||||
| Subpath | Use it for |
|
||||
| --------------------------------------- | ---------------------------------------------- |
|
||||
| `plugin-sdk/provider-auth` | API key, OAuth, auth-profile, and PKCE helpers |
|
||||
| `plugin-sdk/provider-onboard` | Config patches after setup/auth |
|
||||
| `plugin-sdk/provider-models` | Model-definition and catalog helpers |
|
||||
| `plugin-sdk/provider-setup` | Shared local/self-hosted setup flows |
|
||||
| `plugin-sdk/self-hosted-provider-setup` | OpenAI-compatible self-hosted providers |
|
||||
| `plugin-sdk/provider-usage` | Usage snapshot fetch helpers |
|
||||
|
||||
## API key auth
|
||||
|
||||
`createProviderApiKeyAuthMethod(...)` is the standard helper for API-key
|
||||
`catalog.order` controls when your catalog merges relative to built-in
|
||||
providers:
|
||||
|
||||
```ts
|
||||
import { createProviderApiKeyAuthMethod } from "openclaw/plugin-sdk/provider-auth";
|
||||
import { applyProviderConfigWithDefaultModel } from "openclaw/plugin-sdk/provider-onboard";
|
||||
| Order | When | Use case |
|
||||
| --------- | ------------- | ----------------------------------------------- |
|
||||
| `simple` | First pass | Plain API-key providers |
|
||||
| `profile` | After simple | Providers gated on auth profiles |
|
||||
| `paired` | After profile | Synthesize multiple related entries |
|
||||
| `late` | Last pass | Override existing providers (wins on collision) |
|
||||
|
||||
const auth = [
|
||||
createProviderApiKeyAuthMethod({
|
||||
providerId: "example",
|
||||
methodId: "api-key",
|
||||
label: "Example API key",
|
||||
optionKey: "exampleApiKey",
|
||||
flagName: "--example-api-key",
|
||||
envVar: "EXAMPLE_API_KEY",
|
||||
promptMessage: "Enter Example API key",
|
||||
profileId: "example:default",
|
||||
defaultModel: "example/default",
|
||||
applyConfig: (cfg) =>
|
||||
applyProviderConfigWithDefaultModel(cfg, "example", {
|
||||
id: "default",
|
||||
name: "Default",
|
||||
}),
|
||||
}),
|
||||
];
|
||||
```
|
||||
## Next steps
|
||||
|
||||
## OAuth auth
|
||||
|
||||
`buildOauthProviderAuthResult(...)` builds the standard auth result payload for
|
||||
OAuth-style providers:
|
||||
|
||||
```ts
|
||||
import { buildOauthProviderAuthResult } from "openclaw/plugin-sdk/provider-auth";
|
||||
|
||||
async function runOAuthLogin() {
|
||||
return buildOauthProviderAuthResult({
|
||||
providerId: "example-portal",
|
||||
defaultModel: "example-portal/default",
|
||||
access: "access-token",
|
||||
refresh: "refresh-token",
|
||||
email: "user@example.com",
|
||||
notes: ["Tokens auto-refresh when the provider supports refresh tokens."],
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Catalog and discovery hooks
|
||||
|
||||
Provider plugins usually implement either `catalog` or the legacy `discovery`
|
||||
alias. `catalog` is preferred.
|
||||
|
||||
```ts
|
||||
api.registerProvider({
|
||||
id: "example",
|
||||
label: "Example",
|
||||
auth,
|
||||
catalog: {
|
||||
order: "simple",
|
||||
async run(ctx) {
|
||||
const apiKey = ctx.resolveProviderApiKey("example").apiKey;
|
||||
if (!apiKey) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
provider: {
|
||||
api: "openai",
|
||||
baseUrl: "https://api.example.com/v1",
|
||||
apiKey,
|
||||
models: [
|
||||
{
|
||||
id: "default",
|
||||
name: "Default",
|
||||
input: ["text"],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Onboarding config patches
|
||||
|
||||
`plugin-sdk/provider-onboard` keeps post-auth config writes consistent.
|
||||
|
||||
Common helpers:
|
||||
|
||||
- `applyProviderConfigWithDefaultModel(...)`
|
||||
- `applyProviderConfigWithDefaultModels(...)`
|
||||
- `applyProviderConfigWithModelCatalog(...)`
|
||||
- `applyAgentDefaultModelPrimary(...)`
|
||||
- `ensureModelAllowlistEntry(...)`
|
||||
|
||||
## Self-hosted and local model setup
|
||||
|
||||
Use `plugin-sdk/provider-setup` or
|
||||
`plugin-sdk/self-hosted-provider-setup` when the provider is an OpenAI-style
|
||||
backend, Ollama, SGLang, or vLLM.
|
||||
|
||||
Examples from the shared setup surfaces:
|
||||
|
||||
- `promptAndConfigureOllama(...)`
|
||||
- `configureOllamaNonInteractive(...)`
|
||||
- `promptAndConfigureOpenAICompatibleSelfHostedProvider(...)`
|
||||
- `discoverOpenAICompatibleSelfHostedProvider(...)`
|
||||
|
||||
These helpers keep setup behavior aligned with built-in provider flows.
|
||||
|
||||
## Usage snapshots
|
||||
|
||||
If the provider owns quota or usage endpoints, use `resolveUsageAuth(...)` and
|
||||
`fetchUsageSnapshot(...)`.
|
||||
|
||||
`plugin-sdk/provider-usage` includes shared fetch helpers such as:
|
||||
|
||||
- `fetchClaudeUsage(...)`
|
||||
- `fetchCodexUsage(...)`
|
||||
- `fetchGeminiUsage(...)`
|
||||
- `fetchMinimaxUsage(...)`
|
||||
- `fetchZaiUsage(...)`
|
||||
|
||||
## Provider guidance
|
||||
|
||||
- Keep auth logic in `provider-auth`.
|
||||
- Keep config mutation in `provider-onboard`.
|
||||
- Keep catalog/model helpers in `provider-models`.
|
||||
- Keep usage logic in `provider-usage`.
|
||||
- Use `catalog`, not `discovery`, in new plugins.
|
||||
|
||||
## Related
|
||||
|
||||
- [Plugin SDK Overview](/plugins/sdk-overview)
|
||||
- [Plugin Entry Points](/plugins/sdk-entrypoints)
|
||||
- [Plugin Setup](/plugins/sdk-setup)
|
||||
- [Plugin Internals](/plugins/architecture#provider-runtime-hooks)
|
||||
- [Channel Plugins](/plugins/sdk-channel-plugins) — if your plugin also provides a channel
|
||||
- [SDK Runtime](/plugins/sdk-runtime) — `api.runtime` helpers (TTS, search, subagent)
|
||||
- [SDK Overview](/plugins/sdk-overview) — full subpath import reference
|
||||
- [Plugin Internals](/plugins/architecture#provider-runtime-hooks) — hook details and bundled examples
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user