@capybara-hq/kernel 0.1.0-rc.6 → 0.1.0-rc.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (331) hide show
  1. package/bootstrap.json +27 -3
  2. package/dist/admin/admin.controller.d.ts +8 -72
  3. package/dist/admin/admin.controller.js +21 -46
  4. package/dist/admin/admin.schemas.d.ts +57 -0
  5. package/dist/admin/admin.schemas.js +50 -0
  6. package/dist/admin/extensions.controller.d.ts +10 -0
  7. package/dist/admin/extensions.controller.js +18 -0
  8. package/dist/admin/extensions.schemas.d.ts +7 -0
  9. package/dist/admin/extensions.schemas.js +10 -0
  10. package/dist/admin/limit-defaults.d.ts +20 -0
  11. package/dist/admin/limit-defaults.js +10 -0
  12. package/dist/agents/agent-profile.service.d.ts +7 -5
  13. package/dist/agents/agent-profile.service.js +14 -9
  14. package/dist/agents/agents.controller.d.ts +7 -287
  15. package/dist/agents/agents.controller.js +7 -67
  16. package/dist/agents/agents.schemas.d.ts +389 -0
  17. package/dist/agents/agents.schemas.js +126 -0
  18. package/dist/agents/agents.service.d.ts +13 -5
  19. package/dist/agents/agents.service.js +67 -13
  20. package/dist/agents/definition.d.ts +47 -19
  21. package/dist/agents/definition.js +119 -38
  22. package/dist/agents/from-template.d.ts +2 -2
  23. package/dist/agents/from-template.js +76 -45
  24. package/dist/agents/from-template.service.d.ts +12 -0
  25. package/dist/agents/from-template.service.js +20 -3
  26. package/dist/agents/models.controller.d.ts +1 -2
  27. package/dist/agents/models.controller.js +1 -1
  28. package/dist/agents/org-templates.d.ts +13 -3
  29. package/dist/agents/org-templates.js +69 -28
  30. package/dist/agents/pending-connector-requests.d.ts +2 -0
  31. package/dist/agents/pending-connector-requests.js +1 -1
  32. package/dist/agents/pending-connectors.controller.d.ts +1 -1
  33. package/dist/agents/pending-connectors.controller.js +2 -2
  34. package/dist/agents/pending-connectors.service.d.ts +2 -2
  35. package/dist/agents/pending-connectors.service.js +19 -19
  36. package/dist/agents/profile.d.ts +18 -0
  37. package/dist/agents/profile.js +5 -1
  38. package/dist/agents/templates.controller.d.ts +8 -17
  39. package/dist/agents/templates.controller.js +13 -31
  40. package/dist/agents/templates.schemas.d.ts +20 -0
  41. package/dist/agents/templates.schemas.js +45 -0
  42. package/dist/background/background.controller.js +3 -2
  43. package/dist/background/background.schemas.d.ts +10 -0
  44. package/dist/background/background.schemas.js +16 -0
  45. package/dist/background/tasks.service.d.ts +1 -1
  46. package/dist/background/tasks.service.js +7 -2
  47. package/dist/catalog/admin-catalog.controller.d.ts +4 -57
  48. package/dist/catalog/admin-catalog.controller.js +8 -45
  49. package/dist/catalog/admin-catalog.schemas.d.ts +72 -0
  50. package/dist/catalog/admin-catalog.schemas.js +92 -0
  51. package/dist/catalog/catalog-content.d.ts +12 -2
  52. package/dist/catalog/catalog-scope.service.js +8 -2
  53. package/dist/catalog/catalog.service.d.ts +2 -0
  54. package/dist/catalog/catalog.service.js +3 -0
  55. package/dist/catalog/component-scope.controller.d.ts +3 -65
  56. package/dist/catalog/component-scope.controller.js +3 -56
  57. package/dist/catalog/component-scope.schemas.d.ts +114 -0
  58. package/dist/catalog/component-scope.schemas.js +97 -0
  59. package/dist/catalog/component-scope.service.d.ts +28 -4
  60. package/dist/catalog/component-scope.service.js +55 -3
  61. package/dist/catalog/component-state.d.ts +9 -2
  62. package/dist/catalog/component-state.js +22 -13
  63. package/dist/catalog/marketplaces.controller.d.ts +5 -35
  64. package/dist/catalog/marketplaces.controller.js +6 -34
  65. package/dist/catalog/marketplaces.schemas.d.ts +48 -0
  66. package/dist/catalog/marketplaces.schemas.js +53 -0
  67. package/dist/catalog/marketplaces.service.d.ts +15 -1
  68. package/dist/catalog/marketplaces.service.js +22 -1
  69. package/dist/catalog/org-catalog.controller.d.ts +6 -62
  70. package/dist/catalog/org-catalog.controller.js +12 -66
  71. package/dist/catalog/org-catalog.schemas.d.ts +79 -0
  72. package/dist/catalog/org-catalog.schemas.js +82 -0
  73. package/dist/catalog/org-catalog.service.d.ts +9 -2
  74. package/dist/catalog/org-catalog.service.js +38 -5
  75. package/dist/catalog/org-extension.controller.d.ts +1 -12
  76. package/dist/catalog/org-extension.controller.js +1 -10
  77. package/dist/catalog/org-extension.schemas.d.ts +15 -0
  78. package/dist/catalog/org-extension.schemas.js +22 -0
  79. package/dist/catalog/org-plugin-uploads.controller.d.ts +2 -19
  80. package/dist/catalog/org-plugin-uploads.controller.js +15 -28
  81. package/dist/catalog/org-plugin-uploads.schemas.d.ts +20 -0
  82. package/dist/catalog/org-plugin-uploads.schemas.js +32 -0
  83. package/dist/catalog/owned-items.d.ts +6 -2
  84. package/dist/catalog/owned-items.js +16 -4
  85. package/dist/catalog/platform-components.d.ts +2 -0
  86. package/dist/catalog/platform-components.js +2 -0
  87. package/dist/catalog/plugin-import.js +1 -0
  88. package/dist/catalog/plugin-install.js +1 -1
  89. package/dist/catalog/requests.service.d.ts +2 -1
  90. package/dist/catalog/requests.service.js +6 -2
  91. package/dist/channels/channels.schemas.d.ts +33 -0
  92. package/dist/channels/channels.schemas.js +34 -0
  93. package/dist/channels/connections.controller.d.ts +2 -29
  94. package/dist/channels/connections.controller.js +1 -23
  95. package/dist/channels/connections.service.d.ts +8 -2
  96. package/dist/channels/connections.service.js +23 -5
  97. package/dist/channels/inbound.js +4 -0
  98. package/dist/conversations/conversations.controller.d.ts +16 -37
  99. package/dist/conversations/conversations.controller.js +16 -56
  100. package/dist/conversations/conversations.schemas.d.ts +52 -0
  101. package/dist/conversations/conversations.schemas.js +79 -0
  102. package/dist/conversations/conversations.service.d.ts +9 -1
  103. package/dist/conversations/conversations.service.js +23 -18
  104. package/dist/conversations/events.d.ts +80 -6
  105. package/dist/conversations/events.js +60 -5
  106. package/dist/conversations/message-context.d.ts +28 -0
  107. package/dist/conversations/message-context.js +56 -0
  108. package/dist/conversations/queue.d.ts +2 -1
  109. package/dist/conversations/queue.js +11 -2
  110. package/dist/db/kernel-schema.d.ts +20 -0
  111. package/dist/environments/environments.schemas.d.ts +3 -0
  112. package/dist/environments/environments.schemas.js +14 -0
  113. package/dist/environments/environments.service.d.ts +16 -4
  114. package/dist/environments/environments.service.js +58 -13
  115. package/dist/errors.d.ts +3 -0
  116. package/dist/errors.js +3 -0
  117. package/dist/evals/evals.schemas.d.ts +110 -0
  118. package/dist/evals/evals.schemas.js +107 -0
  119. package/dist/evals/reconstruct.js +18 -11
  120. package/dist/evals/recorded-tools.d.ts +2 -1
  121. package/dist/evals/recorded-tools.js +11 -3
  122. package/dist/evals/run-replay.d.ts +8 -1
  123. package/dist/evals/run-replay.js +13 -0
  124. package/dist/evals/runs.controller.d.ts +2 -57
  125. package/dist/evals/runs.controller.js +1 -42
  126. package/dist/evals/runs.service.d.ts +6 -6
  127. package/dist/evals/runs.service.js +32 -18
  128. package/dist/evals/sets.controller.d.ts +2 -28
  129. package/dist/evals/sets.controller.js +1 -31
  130. package/dist/evals/sets.service.d.ts +7 -7
  131. package/dist/evals/sets.service.js +23 -17
  132. package/dist/evals/snapshot.d.ts +3 -2
  133. package/dist/evals/snapshot.js +17 -4
  134. package/dist/extensions/admin-ops.d.ts +5 -3
  135. package/dist/extensions/admin-ops.js +17 -12
  136. package/dist/extensions/deployment-config.d.ts +16 -1
  137. package/dist/extensions/deployment-config.js +83 -0
  138. package/dist/extensions/extensions.module.js +3 -0
  139. package/dist/extensions/host.d.ts +33 -2
  140. package/dist/extensions/host.js +107 -1
  141. package/dist/extensions/installs.d.ts +5 -0
  142. package/dist/extensions/installs.js +12 -0
  143. package/dist/extensions/org-config.d.ts +17 -2
  144. package/dist/extensions/org-config.js +23 -4
  145. package/dist/extensions/point-defaults.controller.d.ts +2 -8
  146. package/dist/extensions/point-defaults.controller.js +1 -3
  147. package/dist/extensions/point-defaults.d.ts +3 -1
  148. package/dist/extensions/point-defaults.js +4 -2
  149. package/dist/extensions/point-defaults.schemas.d.ts +9 -0
  150. package/dist/extensions/point-defaults.schemas.js +14 -0
  151. package/dist/extensions/unavailable.d.ts +49 -0
  152. package/dist/extensions/unavailable.js +113 -0
  153. package/dist/files/previewers.controller.js +2 -3
  154. package/dist/files/previewers.d.ts +1 -1
  155. package/dist/files/previewers.js +4 -4
  156. package/dist/files/previewers.schemas.d.ts +10 -0
  157. package/dist/files/previewers.schemas.js +9 -0
  158. package/dist/http/api.module.js +2 -0
  159. package/dist/identity/accounts.d.ts +43 -4
  160. package/dist/identity/accounts.js +74 -6
  161. package/dist/identity/auth.guard.js +10 -1
  162. package/dist/identity/cookies.d.ts +6 -0
  163. package/dist/identity/cookies.js +14 -0
  164. package/dist/identity/identity.module.js +3 -0
  165. package/dist/identity/initial-passwords.controller.d.ts +22 -0
  166. package/dist/identity/initial-passwords.controller.js +49 -0
  167. package/dist/identity/initial-passwords.d.ts +61 -0
  168. package/dist/identity/initial-passwords.job.d.ts +16 -0
  169. package/dist/identity/initial-passwords.job.js +46 -0
  170. package/dist/identity/initial-passwords.js +159 -0
  171. package/dist/identity/me.controller.d.ts +14 -0
  172. package/dist/identity/me.controller.js +39 -1
  173. package/dist/identity/principal.d.ts +8 -0
  174. package/dist/identity/principal.js +8 -0
  175. package/dist/identity/settings.d.ts +3 -1
  176. package/dist/identity/settings.js +6 -4
  177. package/dist/inbox/inbox.schemas.d.ts +8 -0
  178. package/dist/inbox/inbox.schemas.js +11 -0
  179. package/dist/inbox/platform-inbox.controller.d.ts +1 -1
  180. package/dist/inbox/platform-inbox.controller.js +2 -2
  181. package/dist/index.d.ts +4 -0
  182. package/dist/index.js +6 -0
  183. package/dist/lifecycle/kernel-lifecycle.js +4 -0
  184. package/dist/models/enablement.d.ts +2 -0
  185. package/dist/models/enablement.js +1 -0
  186. package/dist/models/org-models.schemas.d.ts +8 -0
  187. package/dist/models/org-models.schemas.js +22 -0
  188. package/dist/models/prices.d.ts +3 -1
  189. package/dist/models/prices.js +7 -5
  190. package/dist/models/purposes.d.ts +12 -2
  191. package/dist/models/purposes.js +22 -8
  192. package/dist/orgs/orgs.controller.d.ts +2 -5
  193. package/dist/orgs/orgs.controller.js +3 -6
  194. package/dist/orgs/orgs.schemas.d.ts +8 -0
  195. package/dist/orgs/orgs.schemas.js +16 -0
  196. package/dist/orgs/orgs.service.d.ts +3 -1
  197. package/dist/orgs/orgs.service.js +6 -4
  198. package/dist/orgs/settings.service.d.ts +9 -1
  199. package/dist/orgs/settings.service.js +20 -5
  200. package/dist/overrides.d.ts +4 -0
  201. package/dist/overrides.js +2 -0
  202. package/dist/platform/errors.d.ts +21 -4
  203. package/dist/platform/errors.js +45 -6
  204. package/dist/platform/exclusions.d.ts +2 -3
  205. package/dist/platform/exclusions.js +68 -849
  206. package/dist/platform/method.js +1 -1
  207. package/dist/platform/operation.d.ts +82 -5
  208. package/dist/platform/operation.js +62 -7
  209. package/dist/platform/ops/accounts.ops.d.ts +32 -0
  210. package/dist/platform/ops/accounts.ops.js +291 -0
  211. package/dist/platform/ops/admin.ops.d.ts +36 -0
  212. package/dist/platform/ops/admin.ops.js +389 -0
  213. package/dist/platform/ops/agent-skills.ops.d.ts +24 -0
  214. package/dist/platform/ops/agent-skills.ops.js +226 -0
  215. package/dist/platform/ops/agent-templates.ops.d.ts +4 -1
  216. package/dist/platform/ops/agent-templates.ops.js +194 -14
  217. package/dist/platform/ops/agents.ops.d.ts +19 -1
  218. package/dist/platform/ops/agents.ops.js +481 -58
  219. package/dist/platform/ops/approvals.ops.d.ts +30 -0
  220. package/dist/platform/ops/approvals.ops.js +116 -0
  221. package/dist/platform/ops/background.ops.d.ts +14 -0
  222. package/dist/platform/ops/background.ops.js +134 -0
  223. package/dist/platform/ops/catalog-admin.ops.d.ts +74 -0
  224. package/dist/platform/ops/catalog-admin.ops.js +587 -0
  225. package/dist/platform/ops/channels.ops.d.ts +16 -0
  226. package/dist/platform/ops/channels.ops.js +195 -0
  227. package/dist/platform/ops/components.ops.d.ts +46 -0
  228. package/dist/platform/ops/components.ops.js +853 -0
  229. package/dist/platform/ops/connectors.ops.d.ts +4 -2
  230. package/dist/platform/ops/connectors.ops.js +68 -6
  231. package/dist/platform/ops/conversations.ops.d.ts +30 -0
  232. package/dist/platform/ops/conversations.ops.js +470 -0
  233. package/dist/platform/ops/environments.ops.d.ts +26 -0
  234. package/dist/platform/ops/environments.ops.js +289 -0
  235. package/dist/platform/ops/errors.d.ts +10 -5
  236. package/dist/platform/ops/errors.js +19 -11
  237. package/dist/platform/ops/evals.ops.d.ts +28 -0
  238. package/dist/platform/ops/evals.ops.js +783 -0
  239. package/dist/platform/ops/extensions-admin.ops.d.ts +25 -0
  240. package/dist/platform/ops/extensions-admin.ops.js +344 -0
  241. package/dist/platform/ops/extensions.ops.d.ts +7 -1
  242. package/dist/platform/ops/extensions.ops.js +248 -17
  243. package/dist/platform/ops/inbox.ops.d.ts +25 -0
  244. package/dist/platform/ops/inbox.ops.js +378 -0
  245. package/dist/platform/ops/marketplaces.ops.d.ts +7 -1
  246. package/dist/platform/ops/marketplaces.ops.js +326 -17
  247. package/dist/platform/ops/models.ops.d.ts +25 -0
  248. package/dist/platform/ops/models.ops.js +232 -0
  249. package/dist/platform/ops/org-plugins.ops.d.ts +29 -0
  250. package/dist/platform/ops/org-plugins.ops.js +329 -0
  251. package/dist/platform/ops/org-settings.ops.d.ts +16 -0
  252. package/dist/platform/ops/org-settings.ops.js +102 -0
  253. package/dist/platform/ops/orgs.ops.d.ts +28 -0
  254. package/dist/platform/ops/orgs.ops.js +295 -0
  255. package/dist/platform/ops/other-orgs.d.ts +20 -0
  256. package/dist/platform/ops/other-orgs.js +72 -0
  257. package/dist/platform/ops/platform.ops.d.ts +4 -4
  258. package/dist/platform/ops/platform.ops.js +23 -24
  259. package/dist/platform/ops/plugins.ops.d.ts +10 -8
  260. package/dist/platform/ops/plugins.ops.js +176 -77
  261. package/dist/platform/ops/previewers.ops.d.ts +14 -0
  262. package/dist/platform/ops/previewers.ops.js +109 -0
  263. package/dist/platform/ops/requests.ops.js +57 -19
  264. package/dist/platform/ops/skills.ops.d.ts +5 -1
  265. package/dist/platform/ops/skills.ops.js +129 -11
  266. package/dist/platform/ops/unavailable.d.ts +23 -0
  267. package/dist/platform/ops/unavailable.js +111 -0
  268. package/dist/platform/parity.d.ts +33 -0
  269. package/dist/platform/parity.js +272 -0
  270. package/dist/platform/platform-ops.module.d.ts +32 -0
  271. package/dist/platform/platform-ops.module.js +78 -11
  272. package/dist/platform/route-schemas.d.ts +18 -0
  273. package/dist/platform/route-schemas.js +60 -0
  274. package/dist/roles/worker.module.js +2 -0
  275. package/dist/runtime/context/build.d.ts +2 -0
  276. package/dist/runtime/context/build.js +28 -2
  277. package/dist/runtime/context/compaction.js +10 -1
  278. package/dist/runtime/context/run-context.d.ts +65 -0
  279. package/dist/runtime/context/run-context.js +215 -0
  280. package/dist/runtime/model-call.js +2 -1
  281. package/dist/runtime/providers.js +8 -1
  282. package/dist/runtime/run-context.service.d.ts +65 -0
  283. package/dist/runtime/run-context.service.js +220 -0
  284. package/dist/runtime/run-worker.d.ts +5 -0
  285. package/dist/runtime/run-worker.js +31 -6
  286. package/dist/runtime/runtime.module.js +2 -0
  287. package/dist/runtime/subagents/definition.d.ts +15 -15
  288. package/dist/runtime/subagents/definition.js +46 -115
  289. package/dist/skills/changes.controller.js +2 -1
  290. package/dist/skills/changes.service.d.ts +1 -1
  291. package/dist/skills/changes.service.js +4 -4
  292. package/dist/skills/invocable.controller.d.ts +1 -1
  293. package/dist/skills/invocable.controller.js +2 -2
  294. package/dist/skills/invoke.d.ts +2 -2
  295. package/dist/skills/invoke.js +8 -1
  296. package/dist/skills/skills.controller.d.ts +4 -13
  297. package/dist/skills/skills.controller.js +8 -24
  298. package/dist/skills/skills.schemas.d.ts +48 -0
  299. package/dist/skills/skills.schemas.js +61 -0
  300. package/dist/skills/skills.service.d.ts +11 -1
  301. package/dist/skills/skills.service.js +37 -14
  302. package/dist/time-zone.d.ts +5 -0
  303. package/dist/time-zone.js +19 -0
  304. package/dist/tools/approvals.controller.js +2 -3
  305. package/dist/tools/approvals.schemas.d.ts +21 -0
  306. package/dist/tools/approvals.schemas.js +15 -0
  307. package/dist/tools/builtin-names.d.ts +10 -8
  308. package/dist/tools/builtin-names.js +16 -11
  309. package/dist/tools/builtins/builtin-tools.d.ts +3 -1
  310. package/dist/tools/builtins/builtin-tools.js +15 -3
  311. package/dist/tools/builtins/current-time.d.ts +26 -0
  312. package/dist/tools/builtins/current-time.js +99 -0
  313. package/dist/tools/builtins/platform.d.ts +19 -2
  314. package/dist/tools/builtins/platform.js +105 -16
  315. package/dist/tools/connectors.controller.d.ts +1 -2
  316. package/dist/tools/connectors.controller.js +1 -4
  317. package/dist/tools/connectors.schemas.d.ts +12 -0
  318. package/dist/tools/connectors.schemas.js +19 -0
  319. package/dist/tools/connectors.service.d.ts +5 -2
  320. package/dist/tools/connectors.service.js +7 -5
  321. package/dist/tools/org-tool-switches.d.ts +16 -2
  322. package/dist/tools/org-tool-switches.js +26 -9
  323. package/dist/tools/pipeline.js +3 -1
  324. package/dist/tools/registry.d.ts +48 -51
  325. package/dist/tools/registry.js +222 -233
  326. package/package.json +3 -3
  327. package/src/migrations/0090_initial_passwords.sql +27 -0
  328. package/src/migrations/0091_account_time_zone.sql +4 -0
  329. package/src/migrations/0092_tools_default_on.sql +27 -0
  330. package/dist/platform/redact-orgs.d.ts +0 -7
  331. package/dist/platform/redact-orgs.js +0 -52
@@ -8,42 +8,12 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
8
  return function (target, key) { decorator(target, key, paramIndex); }
9
9
  };
10
10
  import { Controller, Delete, Get, HttpCode, Inject, Param, Patch, Post } from "@nestjs/common";
11
- import { z } from "zod";
12
11
  import { CurrentPrincipal, patTokenId, requireUser, } from "../identity/principal.js";
13
12
  import { createZodDto } from "../infra/validation/create-zod-dto.js";
14
13
  import { ZBody } from "../infra/validation/zod-params.js";
15
14
  import { CurrentOrg, OrgAction } from "../orgs/org.guard.js";
15
+ import { EvalAddCaseBody as AddCaseBody, EvalSetCreateBody as CreateBody, EvalSetPatchBody as PatchBody, EvalSampleBody as SampleBody, } from "./evals.schemas.js";
16
16
  import { EvalSetsService, } from "./sets.service.js";
17
- const NAME = z.string().trim().min(1).max(200);
18
- const DESCRIPTION = z.string().max(2000);
19
- const RUBRIC = z.string().min(1).max(20_000);
20
- const CreateBody = z
21
- .object({
22
- agentId: z.string().min(1).max(100),
23
- name: NAME,
24
- description: DESCRIPTION.optional(),
25
- rubric: RUBRIC.optional(),
26
- })
27
- .strict();
28
- const PatchBody = z
29
- .object({
30
- name: NAME.optional(),
31
- description: DESCRIPTION.optional(),
32
- rubric: RUBRIC.nullable().optional(),
33
- })
34
- .strict();
35
- const AddCaseBody = z
36
- .object({ conversationId: z.string().min(1).max(100), runId: z.string().min(1).max(100) })
37
- .strict();
38
- const SampleBody = z
39
- .object({
40
- from: z.iso.datetime({ offset: true }).optional(),
41
- to: z.iso.datetime({ offset: true }).optional(),
42
- count: z.number().int().min(1).max(50),
43
- status: z.enum(["completed", "failed", "any"]).optional(),
44
- minToolCalls: z.number().int().min(0).max(1000).optional(),
45
- })
46
- .strict();
47
17
  class CreateBodyDto extends createZodDto(CreateBody, "EvalSetCreateBody") {
48
18
  }
49
19
  class PatchBodyDto extends createZodDto(PatchBody, "EvalSetPatchBody") {
@@ -91,19 +91,19 @@ export declare class EvalSetsService {
91
91
  name: string;
92
92
  description?: string;
93
93
  rubric?: string;
94
- }, actorTokenId?: string): Promise<EvalSetView>;
94
+ }, actorTokenId?: string, auditDetail?: Record<string, unknown>): Promise<EvalSetView>;
95
95
  list(orgId: string): Promise<EvalSetView[]>;
96
96
  get(orgId: string, setId: string): Promise<EvalSetDetail>;
97
97
  update(orgId: string, actor: string, setId: string, patch: {
98
98
  name?: string;
99
99
  description?: string;
100
100
  rubric?: string | null;
101
- }, actorTokenId?: string): Promise<EvalSetView>;
101
+ }, actorTokenId?: string, auditDetail?: Record<string, unknown>): Promise<EvalSetView>;
102
102
  /**
103
103
  * 删除评测集(Ruling S1-a):集合行软删除,留作审计存根;用例(含快照)硬删,结果随之级联删除,不留复制来的对话内容;
104
104
  * 在执行的运行取消,运行行保留(无入口)。
105
105
  */
106
- remove(orgId: string, actor: string, setId: string, actorTokenId?: string): Promise<void>;
106
+ remove(orgId: string, actor: string, setId: string, actorTokenId?: string, auditDetail?: Record<string, unknown>): Promise<void>;
107
107
  private createIn;
108
108
  private updateIn;
109
109
  private removeIn;
@@ -125,20 +125,20 @@ export declare class EvalSetsService {
125
125
  addCase(orgId: string, actor: string, setId: string, input: {
126
126
  conversationId: string;
127
127
  runId: string;
128
- }, actorTokenId?: string): Promise<EvalCaseView>;
128
+ }, actorTokenId?: string, auditDetail?: Record<string, unknown>): Promise<EvalCaseView>;
129
129
  /**
130
130
  * 抽样:从该 agent 的 chat 对话里随机取(`ORDER BY random()`)已终态、尚不在集合里的运行,至多
131
131
  * `min(count, 剩余容量)` 个,逐个取快照写入。快照超大(或其间被删除 / 写入时已满 / 并发加入)的计入 `skipped`。
132
132
  * 集合已满 → `eval.too_many_cases`。逐个写入,内存里一次只有一份快照。
133
133
  */
134
- sample(orgId: string, actor: string, setId: string, input: SampleInput, actorTokenId?: string): Promise<{
134
+ sample(orgId: string, actor: string, setId: string, input: SampleInput, actorTokenId?: string, auditDetail?: Record<string, unknown>): Promise<{
135
135
  added: number;
136
136
  skipped: number;
137
137
  }>;
138
- removeCase(orgId: string, actor: string, setId: string, caseId: string, actorTokenId?: string): Promise<void>;
138
+ removeCase(orgId: string, actor: string, setId: string, caseId: string, actorTokenId?: string, auditDetail?: Record<string, unknown>): Promise<void>;
139
139
  /**
140
140
  * 用例详情:由快照还原轨迹(原对话删除后照常可读)。快照即对话内容,每次查看写审计 `trajectory.viewed`
141
141
  * (target = 原对话 id,detail 带 `caseId` / `setId`)。
142
142
  */
143
- getCase(orgId: string, actor: string, setId: string, caseId: string, actorTokenId?: string): Promise<EvalCaseDetail>;
143
+ getCase(orgId: string, actor: string, setId: string, caseId: string, actorTokenId?: string, auditDetail?: Record<string, unknown>): Promise<EvalCaseDetail>;
144
144
  }
@@ -152,8 +152,8 @@ let EvalSetsService = EvalSetsService_1 = class EvalSetsService {
152
152
  throw setNotFound();
153
153
  return EvalSetsService_1.toView(r);
154
154
  }
155
- async create(orgId, actor, input, actorTokenId) {
156
- const id = await this.createIn(orgId, actor, input, actorTokenId);
155
+ async create(orgId, actor, input, actorTokenId, auditDetail) {
156
+ const id = await this.createIn(orgId, actor, input, actorTokenId, auditDetail);
157
157
  return this.view(orgId, id);
158
158
  }
159
159
  async list(orgId) {
@@ -175,22 +175,22 @@ let EvalSetsService = EvalSetsService_1 = class EvalSetsService {
175
175
  .execute();
176
176
  return { ...set, cases: cases.map(toCaseView) };
177
177
  }
178
- async update(orgId, actor, setId, patch, actorTokenId) {
178
+ async update(orgId, actor, setId, patch, actorTokenId, auditDetail) {
179
179
  if (!UUID.test(setId))
180
180
  throw setNotFound();
181
- await this.updateIn(orgId, actor, setId, patch, actorTokenId);
181
+ await this.updateIn(orgId, actor, setId, patch, actorTokenId, auditDetail);
182
182
  return this.view(orgId, setId);
183
183
  }
184
184
  /**
185
185
  * 删除评测集(Ruling S1-a):集合行软删除,留作审计存根;用例(含快照)硬删,结果随之级联删除,不留复制来的对话内容;
186
186
  * 在执行的运行取消,运行行保留(无入口)。
187
187
  */
188
- async remove(orgId, actor, setId, actorTokenId) {
188
+ async remove(orgId, actor, setId, actorTokenId, auditDetail) {
189
189
  if (!UUID.test(setId))
190
190
  throw setNotFound();
191
- await this.removeIn(orgId, actor, setId, actorTokenId);
191
+ await this.removeIn(orgId, actor, setId, actorTokenId, auditDetail);
192
192
  }
193
- async createIn(orgId, actor, input, actorTokenId) {
193
+ async createIn(orgId, actor, input, actorTokenId, auditDetail) {
194
194
  await this.orgLock.lockAndAuthorize(orgId, actor, "evals.manage");
195
195
  const agent = await this.db
196
196
  .selectFrom("agents")
@@ -219,11 +219,11 @@ let EvalSetsService = EvalSetsService_1 = class EvalSetsService {
219
219
  orgId,
220
220
  action: "eval.set_created",
221
221
  target: row.id,
222
- detail: { agentId: input.agentId, name: input.name },
222
+ detail: { agentId: input.agentId, name: input.name, ...auditDetail },
223
223
  });
224
224
  return row.id;
225
225
  }
226
- async updateIn(orgId, actor, setId, patch, actorTokenId) {
226
+ async updateIn(orgId, actor, setId, patch, actorTokenId, auditDetail) {
227
227
  await this.orgLock.lockAndAuthorize(orgId, actor, "evals.manage");
228
228
  const r = await this.db
229
229
  .updateTable("eval_sets")
@@ -248,10 +248,11 @@ let EvalSetsService = EvalSetsService_1 = class EvalSetsService {
248
248
  // 只记改了哪些字段(评分标准可能很长,不进审计)
249
249
  detail: {
250
250
  fields: ["name", "description", "rubric"].filter((f) => patch[f] !== undefined),
251
+ ...auditDetail,
251
252
  },
252
253
  });
253
254
  }
254
- async removeIn(orgId, actor, setId, actorTokenId) {
255
+ async removeIn(orgId, actor, setId, actorTokenId, auditDetail) {
255
256
  await this.orgLock.lockAndAuthorize(orgId, actor, "evals.manage");
256
257
  const r = await this.db
257
258
  .updateTable("eval_sets")
@@ -269,6 +270,7 @@ let EvalSetsService = EvalSetsService_1 = class EvalSetsService {
269
270
  orgId,
270
271
  action: "eval.set_deleted",
271
272
  target: setId,
273
+ ...(auditDetail !== undefined && { detail: auditDetail }),
272
274
  });
273
275
  }
274
276
  async insertCaseIn(orgId, actor, setId, snapshot, extra, prepared) {
@@ -319,11 +321,12 @@ let EvalSetsService = EvalSetsService_1 = class EvalSetsService {
319
321
  conversationId: snapshot.conversationId,
320
322
  runId: snapshot.runId,
321
323
  ...(extra.sampled && { sampled: true }),
324
+ ...extra.auditDetail,
322
325
  },
323
326
  });
324
327
  return toCaseView(row);
325
328
  }
326
- async removeCaseIn(orgId, actor, setId, caseId, actorTokenId) {
329
+ async removeCaseIn(orgId, actor, setId, caseId, actorTokenId, auditDetail) {
327
330
  await this.orgLock.lockAndAuthorize(orgId, actor, "evals.manage");
328
331
  const set = await this.db
329
332
  .selectFrom("eval_sets")
@@ -354,6 +357,7 @@ let EvalSetsService = EvalSetsService_1 = class EvalSetsService {
354
357
  caseId,
355
358
  conversationId: r.source_conversation_id,
356
359
  runId: r.source_run_id,
360
+ ...auditDetail,
357
361
  },
358
362
  });
359
363
  }
@@ -402,7 +406,7 @@ let EvalSetsService = EvalSetsService_1 = class EvalSetsService {
402
406
  * `eval.agent_mismatch`;已在集合里 → `eval.case_exists`;集合满了 → `eval.too_many_cases`;
403
407
  * 运行未终态 / 快照超大 → `eval.run_not_finished` / `eval.case_too_large`(`takeSnapshot`)。
404
408
  */
405
- async addCase(orgId, actor, setId, input, actorTokenId) {
409
+ async addCase(orgId, actor, setId, input, actorTokenId, auditDetail) {
406
410
  const set = await this.liveSet(orgId, setId);
407
411
  const conv = await this.db
408
412
  .selectFrom("conversations")
@@ -434,6 +438,7 @@ let EvalSetsService = EvalSetsService_1 = class EvalSetsService {
434
438
  const r = await this.insertCase(orgId, actor, setId, snapshot, {
435
439
  sampled: false,
436
440
  ...(actorTokenId !== undefined && { actorTokenId }),
441
+ ...(auditDetail !== undefined && { auditDetail }),
437
442
  });
438
443
  if (r === "exists")
439
444
  throw caseExists();
@@ -446,7 +451,7 @@ let EvalSetsService = EvalSetsService_1 = class EvalSetsService {
446
451
  * `min(count, 剩余容量)` 个,逐个取快照写入。快照超大(或其间被删除 / 写入时已满 / 并发加入)的计入 `skipped`。
447
452
  * 集合已满 → `eval.too_many_cases`。逐个写入,内存里一次只有一份快照。
448
453
  */
449
- async sample(orgId, actor, setId, input, actorTokenId) {
454
+ async sample(orgId, actor, setId, input, actorTokenId, auditDetail) {
450
455
  const set = await this.liveSet(orgId, setId);
451
456
  const { maxCasesPerSet, maxCaseBytes } = this.config.get().evals;
452
457
  const room = maxCasesPerSet - (await this.caseCount(this.db, setId));
@@ -497,6 +502,7 @@ let EvalSetsService = EvalSetsService_1 = class EvalSetsService {
497
502
  const r = await this.insertCase(orgId, actor, setId, snapshot, {
498
503
  sampled: true,
499
504
  ...(actorTokenId !== undefined && { actorTokenId }),
505
+ ...(auditDetail !== undefined && { auditDetail }),
500
506
  });
501
507
  if (typeof r === "string")
502
508
  skipped++;
@@ -505,18 +511,18 @@ let EvalSetsService = EvalSetsService_1 = class EvalSetsService {
505
511
  }
506
512
  return { added, skipped };
507
513
  }
508
- async removeCase(orgId, actor, setId, caseId, actorTokenId) {
514
+ async removeCase(orgId, actor, setId, caseId, actorTokenId, auditDetail) {
509
515
  if (!UUID.test(setId))
510
516
  throw setNotFound();
511
517
  if (!UUID.test(caseId))
512
518
  throw caseNotFound();
513
- await this.removeCaseIn(orgId, actor, setId, caseId, actorTokenId);
519
+ await this.removeCaseIn(orgId, actor, setId, caseId, actorTokenId, auditDetail);
514
520
  }
515
521
  /**
516
522
  * 用例详情:由快照还原轨迹(原对话删除后照常可读)。快照即对话内容,每次查看写审计 `trajectory.viewed`
517
523
  * (target = 原对话 id,detail 带 `caseId` / `setId`)。
518
524
  */
519
- async getCase(orgId, actor, setId, caseId, actorTokenId) {
525
+ async getCase(orgId, actor, setId, caseId, actorTokenId, auditDetail) {
520
526
  await this.liveSet(orgId, setId);
521
527
  if (!UUID.test(caseId))
522
528
  throw caseNotFound();
@@ -537,7 +543,7 @@ let EvalSetsService = EvalSetsService_1 = class EvalSetsService {
537
543
  orgId,
538
544
  action: "trajectory.viewed",
539
545
  target: row.source_conversation_id,
540
- detail: { agentId: snapshot.agentId, caseId, setId },
546
+ detail: { agentId: snapshot.agentId, caseId, setId, ...auditDetail },
541
547
  });
542
548
  return {
543
549
  case: toCaseView(row),
@@ -59,8 +59,9 @@ export interface CaseSnapshot {
59
59
  */
60
60
  export declare function takeSnapshot(db: KernelSchemaDb, orgId: string, conversationId: string, runId: string, maxBytes: number): Promise<CaseSnapshot>;
61
61
  /**
62
- * 读出库里存的快照(`eval_cases.snapshot`):把各版本定义里改名前(D17)的 `{ kind: "app" }` 工具引用规范化为
63
- * connector 形(C27)。整轮回放会把定义交给实时注册表,不规范化的话连接器工具全部失效。其余字段原样。
62
+ * Reads a stored snapshot (`eval_cases.snapshot`): each version's definition goes through
63
+ * `normalizeStoredDefinition` (rc tool keys, and an enabled tool list read as nothing turned off).
64
+ * Other fields as they are.
64
65
  */
65
66
  export declare function readSnapshot(raw: unknown): CaseSnapshot;
66
67
  /** 快照事件还原为日志事件(`createdAt` 转回 Date)。 */
@@ -97,7 +97,7 @@ export async function takeSnapshot(db, orgId, conversationId, runId, maxBytes) {
97
97
  .orderBy("version")
98
98
  .execute();
99
99
  for (const r of defRows) {
100
- definitions[String(r.version)] = normalizeStoredDefinition(r.definition);
100
+ definitions[String(r.version)] = snapshotDefinition(r.definition);
101
101
  }
102
102
  const toolSpecs = {};
103
103
  if (hashes.size > 0) {
@@ -151,14 +151,27 @@ export async function takeSnapshot(db, orgId, conversationId, runId, maxBytes) {
151
151
  return snapshot;
152
152
  }
153
153
  /**
154
- * 读出库里存的快照(`eval_cases.snapshot`):把各版本定义里改名前(D17)的 `{ kind: "app" }` 工具引用规范化为
155
- * connector 形(C27)。整轮回放会把定义交给实时注册表,不规范化的话连接器工具全部失效。其余字段原样。
154
+ * A definition as a snapshot holds it: normalized (`normalizeStoredDefinition`), and one from
155
+ * before tools were on by default keeps its enabled list next to it: rc tool keys are read by its
156
+ * extension refs (`legacyScopeOf`); the runtime ignores it (tools default-on spec §2).
157
+ */
158
+ function snapshotDefinition(d) {
159
+ const enabled = d?.tools;
160
+ return {
161
+ ...normalizeStoredDefinition(d),
162
+ ...(Array.isArray(enabled) && { tools: enabled }),
163
+ };
164
+ }
165
+ /**
166
+ * Reads a stored snapshot (`eval_cases.snapshot`): each version's definition goes through
167
+ * `normalizeStoredDefinition` (rc tool keys, and an enabled tool list read as nothing turned off).
168
+ * Other fields as they are.
156
169
  */
157
170
  export function readSnapshot(raw) {
158
171
  const s = raw;
159
172
  const definitions = {};
160
173
  for (const [v, d] of Object.entries(s.definitions ?? {})) {
161
- definitions[v] = normalizeStoredDefinition(d);
174
+ definitions[v] = snapshotDefinition(d);
162
175
  }
163
176
  return {
164
177
  ...s,
@@ -120,14 +120,16 @@ export declare class ExtensionAdminOps {
120
120
  }): Promise<AdminExtensionView>;
121
121
  private writeInstall;
122
122
  /** Enable on the deployment (audit `extension.enabled`); no change when already enabled. Org enablement is unchanged. */
123
- enable(name: string, actor: string | null, actorTokenId?: string, owner?: ExtensionOpsOwner): Promise<AdminExtensionView>;
123
+ enable(name: string, actor: string | null, actorTokenId?: string, owner?: ExtensionOpsOwner,
124
+ /** Merged into the audit detail (a write made through the Platform tool). */
125
+ auditDetail?: Record<string, unknown>): Promise<AdminExtensionView>;
124
126
  /**
125
127
  * Disables on the deployment (audit `extension.disabled`); no change when already disabled. Every
126
128
  * replica unloads it (draining in-flight calls), and the extensions that `requires` it unload with
127
129
  * it; the org enablement switch is unchanged and the org page shows it as unavailable. A required
128
130
  * bootstrap plugin -> `extension.required`.
129
131
  */
130
- disable(name: string, actor: string | null, actorTokenId?: string, owner?: ExtensionOpsOwner): Promise<AdminExtensionView>;
132
+ disable(name: string, actor: string | null, actorTokenId?: string, owner?: ExtensionOpsOwner, auditDetail?: Record<string, unknown>): Promise<AdminExtensionView>;
131
133
  /**
132
134
  * Uninstall: a required bootstrap plugin -> `extension.required`; must be disabled first
133
135
  * (otherwise `extension.not_disabled`); deletes the install record
@@ -136,7 +138,7 @@ export declare class ExtensionAdminOps {
136
138
  * permission snapshot and the package in the package store are untouched (a reinstall picks them
137
139
  * up).
138
140
  */
139
- uninstall(name: string, actor: string | null, actorTokenId?: string, owner?: ExtensionOpsOwner): Promise<void>;
141
+ uninstall(name: string, actor: string | null, actorTokenId?: string, owner?: ExtensionOpsOwner, auditDetail?: Record<string, unknown>): Promise<void>;
140
142
  private writeUninstall;
141
143
  private setState;
142
144
  private writeState;
@@ -222,8 +222,10 @@ let ExtensionAdminOps = class ExtensionAdminOps {
222
222
  return { changed: true, state: row?.desired_state ?? "disabled" };
223
223
  }
224
224
  /** Enable on the deployment (audit `extension.enabled`); no change when already enabled. Org enablement is unchanged. */
225
- enable(name, actor, actorTokenId, owner) {
226
- return this.setState(name, "enabled", actor, actorTokenId, owner);
225
+ enable(name, actor, actorTokenId, owner,
226
+ /** Merged into the audit detail (a write made through the Platform tool). */
227
+ auditDetail) {
228
+ return this.setState(name, "enabled", actor, actorTokenId, owner, auditDetail);
227
229
  }
228
230
  /**
229
231
  * Disables on the deployment (audit `extension.disabled`); no change when already disabled. Every
@@ -231,8 +233,8 @@ let ExtensionAdminOps = class ExtensionAdminOps {
231
233
  * it; the org enablement switch is unchanged and the org page shows it as unavailable. A required
232
234
  * bootstrap plugin -> `extension.required`.
233
235
  */
234
- disable(name, actor, actorTokenId, owner) {
235
- return this.setState(name, "disabled", actor, actorTokenId, owner);
236
+ disable(name, actor, actorTokenId, owner, auditDetail) {
237
+ return this.setState(name, "disabled", actor, actorTokenId, owner, auditDetail);
236
238
  }
237
239
  /**
238
240
  * Uninstall: a required bootstrap plugin -> `extension.required`; must be disabled first
@@ -242,11 +244,11 @@ let ExtensionAdminOps = class ExtensionAdminOps {
242
244
  * permission snapshot and the package in the package store are untouched (a reinstall picks them
243
245
  * up).
244
246
  */
245
- async uninstall(name, actor, actorTokenId, owner) {
247
+ async uninstall(name, actor, actorTokenId, owner, auditDetail) {
246
248
  this.assertInstallable(name);
247
- await this.writeUninstall(name, actor, actorTokenId, owner);
249
+ await this.writeUninstall(name, actor, actorTokenId, owner, auditDetail);
248
250
  }
249
- async writeUninstall(name, actor, actorTokenId, owner) {
251
+ async writeUninstall(name, actor, actorTokenId, owner, auditDetail) {
250
252
  const db = this.db;
251
253
  await this.authorize(actor, owner);
252
254
  const row = await this.lockRow(name);
@@ -260,19 +262,22 @@ let ExtensionAdminOps = class ExtensionAdminOps {
260
262
  await db.deleteFrom("extension_installs").where("name", "=", name).execute();
261
263
  // 来源条目随安装记录一起删:之后不经目录重新安装时不再受旧条目的策略约束(T26 裁决)
262
264
  await db.deleteFrom("extension_catalog_sources").where("plugin", "=", name).execute();
263
- await this.audit(actor, actorTokenId, "extension.uninstalled", name, row.version, row.sha256, ownerDetail(owner));
265
+ await this.audit(actor, actorTokenId, "extension.uninstalled", name, row.version, row.sha256, {
266
+ ...ownerDetail(owner),
267
+ ...auditDetail,
268
+ });
264
269
  afterCommit(() => this.notify(name));
265
270
  }
266
- async setState(name, state, actor, actorTokenId, owner) {
271
+ async setState(name, state, actor, actorTokenId, owner, auditDetail) {
267
272
  this.assertInstallable(name);
268
- const result = await this.writeState(name, state, actor, actorTokenId, owner);
273
+ const result = await this.writeState(name, state, actor, actorTokenId, owner, auditDetail);
269
274
  return this.viewAfterCommit(name, {
270
275
  version: result.row.version,
271
276
  sha256: result.row.sha256,
272
277
  state,
273
278
  });
274
279
  }
275
- async writeState(name, state, actor, actorTokenId, owner) {
280
+ async writeState(name, state, actor, actorTokenId, owner, auditDetail) {
276
281
  const db = this.db;
277
282
  await this.authorize(actor, owner);
278
283
  const row = await this.lockRow(name);
@@ -291,7 +296,7 @@ let ExtensionAdminOps = class ExtensionAdminOps {
291
296
  })
292
297
  .where("name", "=", name)
293
298
  .execute();
294
- await this.audit(actor, actorTokenId, state === "enabled" ? "extension.enabled" : "extension.disabled", name, row.version, row.sha256, ownerDetail(owner));
299
+ await this.audit(actor, actorTokenId, state === "enabled" ? "extension.enabled" : "extension.disabled", name, row.version, row.sha256, { ...ownerDetail(owner), ...auditDetail });
295
300
  afterCommit(() => this.notify(name));
296
301
  return { row, changed: true };
297
302
  }
@@ -59,7 +59,7 @@ export interface SecretEntry {
59
59
  value?: string | null | undefined;
60
60
  renameFrom?: string | undefined;
61
61
  }
62
- /** The response of `GET / PUT /api/v1/admin/extensions/:name/config`. */
62
+ /** The response of `GET / PUT / DELETE /api/v1/admin/extensions/:name/config`. */
63
63
  export interface DeploymentConfigView {
64
64
  plugin: string;
65
65
  /** The plugin's display name (`ExtensionDisplayNames`); null when it has none. */
@@ -159,6 +159,21 @@ export declare class ExtensionDeploymentConfigService {
159
159
  * applies it on this replica right away.
160
160
  */
161
161
  put(plugin: string, values: Record<string, unknown>, actor: string, actorTokenId?: string, secretEntries?: readonly SecretEntry[]): Promise<DeploymentConfigView>;
162
+ /**
163
+ * Clears the deployment config stored in PG: the `extension_deployment_configs` row and every
164
+ * secret stored for the extension (any path, also ones an older version declared). Fields from
165
+ * the startup config (file / Nacos / env) are untouched and stay in effect (they stay
166
+ * `readonly` in the view; only the startup config changes them). Unknown to the deployment ->
167
+ * `extension.not_found`.
168
+ * In a transaction: `lockAndAuthorize` (re-checks the super admin under the lock), the advisory
169
+ * lock per extension, audit `extension.config_cleared` (detail `clearedPaths`: the stored field
170
+ * paths, never values; nothing stored -> no audit, no publish). After the commit publishes
171
+ * {@link PLUGIN_DEPLOYMENT_CONFIG_TOPIC} and applies it on this replica: every replica re-reads,
172
+ * and the extension loads from what remains, or is unloaded and becomes pending configuration
173
+ * when that is missing or invalid (`ExtensionHost.applyDeploymentConfig`), without a restart.
174
+ */
175
+ clear(plugin: string, actor: string, actorTokenId?: string): Promise<DeploymentConfigView>;
176
+ private clearStored;
162
177
  /**
163
178
  * Secret entries name a secret record field some hint names (else 400 `validation_failed`, also
164
179
  * for a path given in `values` too, an entry with neither `value` nor `renameFrom`, or a key
@@ -16,6 +16,7 @@ import { ApiError } from "../errors.js";
16
16
  import { audit } from "../identity/audit.js";
17
17
  import { SuperAdminLock } from "../identity/super-admin.js";
18
18
  import { KernelConfigService } from "../infra/config/kernel-config.service.js";
19
+ import { afterCommit } from "../infra/database/after-commit.js";
19
20
  import { KernelDb } from "../infra/database/kernel-db.js";
20
21
  import { TransactionHost } from "../infra/database/transaction-host.js";
21
22
  import { Transactional } from "../infra/database/transactional.decorator.js";
@@ -193,6 +194,85 @@ let ExtensionDeploymentConfigService = class ExtensionDeploymentConfigService {
193
194
  }
194
195
  return this.render(plugin, info, stored, await this.displayNames.get(plugin));
195
196
  }
197
+ /**
198
+ * Clears the deployment config stored in PG: the `extension_deployment_configs` row and every
199
+ * secret stored for the extension (any path, also ones an older version declared). Fields from
200
+ * the startup config (file / Nacos / env) are untouched and stay in effect (they stay
201
+ * `readonly` in the view; only the startup config changes them). Unknown to the deployment ->
202
+ * `extension.not_found`.
203
+ * In a transaction: `lockAndAuthorize` (re-checks the super admin under the lock), the advisory
204
+ * lock per extension, audit `extension.config_cleared` (detail `clearedPaths`: the stored field
205
+ * paths, never values; nothing stored -> no audit, no publish). After the commit publishes
206
+ * {@link PLUGIN_DEPLOYMENT_CONFIG_TOPIC} and applies it on this replica: every replica re-reads,
207
+ * and the extension loads from what remains, or is unloaded and becomes pending configuration
208
+ * when that is missing or invalid (`ExtensionHost.applyDeploymentConfig`), without a restart.
209
+ */
210
+ async clear(plugin, actor, actorTokenId) {
211
+ const info = await this.info(plugin);
212
+ await this.clearStored(plugin, info.fields.map((f) => f.path), actor, actorTokenId);
213
+ return this.render(plugin, info, {}, await this.displayNames.get(plugin));
214
+ }
215
+ async clearStored(plugin, fieldPaths, actor, actorTokenId) {
216
+ const t = this.db;
217
+ await this.adminLock.lockAndAuthorize(actor);
218
+ await this.configLock.lock(plugin);
219
+ const row = await t
220
+ .selectFrom("extension_deployment_configs")
221
+ .select("config")
222
+ .where("plugin", "=", plugin)
223
+ .forUpdate()
224
+ .executeTakeFirst();
225
+ const prefix = secretKey(plugin, "");
226
+ const secretKeys = (await t
227
+ .selectFrom("secrets")
228
+ .select("key")
229
+ .where("namespace", "=", SECRETS_NAMESPACE)
230
+ .where("org_id", "=", DEPLOYMENT_SECRETS_ORG)
231
+ .execute())
232
+ .map((r) => r.key)
233
+ .filter((k) => k.startsWith(prefix));
234
+ if (row === undefined && secretKeys.length === 0)
235
+ return;
236
+ if (secretKeys.length > 0) {
237
+ await t
238
+ .deleteFrom("secrets")
239
+ .where("namespace", "=", SECRETS_NAMESPACE)
240
+ .where("org_id", "=", DEPLOYMENT_SECRETS_ORG)
241
+ .where("key", "in", secretKeys)
242
+ .execute();
243
+ }
244
+ await t.deleteFrom("extension_deployment_configs").where("plugin", "=", plugin).execute();
245
+ const clearedPaths = [
246
+ ...new Set([
247
+ ...fieldPaths.filter((p) => getPath(row?.config ?? {}, p) !== undefined),
248
+ ...secretKeys.map((k) => k.slice(prefix.length)),
249
+ ]),
250
+ ].sort();
251
+ await audit(t, {
252
+ actorAccountId: actor,
253
+ ...(actorTokenId !== undefined && { actorTokenId }),
254
+ action: "extension.config_cleared",
255
+ target: plugin,
256
+ detail: { clearedPaths },
257
+ });
258
+ afterCommit(async () => {
259
+ try {
260
+ await this.bus.publish(PLUGIN_DEPLOYMENT_CONFIG_TOPIC, { plugin });
261
+ }
262
+ catch (err) {
263
+ this.log.warn("cannot publish plugin-deployment-config after clearing", { plugin, err });
264
+ }
265
+ try {
266
+ await this.lifecycle.applyConfig(plugin);
267
+ }
268
+ catch (err) {
269
+ this.log.error("applying the cleared plugin deployment config on this replica failed", {
270
+ plugin,
271
+ err,
272
+ });
273
+ }
274
+ });
275
+ }
196
276
  /**
197
277
  * Secret entries name a secret record field some hint names (else 400 `validation_failed`, also
198
278
  * for a path given in `values` too, an entry with neither `value` nor `renameFrom`, or a key
@@ -405,6 +485,9 @@ __decorate([
405
485
  accessMode: "read only",
406
486
  })
407
487
  ], ExtensionDeploymentConfigService.prototype, "readStored", null);
488
+ __decorate([
489
+ Transactional()
490
+ ], ExtensionDeploymentConfigService.prototype, "clearStored", null);
408
491
  __decorate([
409
492
  Transactional()
410
493
  ], ExtensionDeploymentConfigService.prototype, "write", null);
@@ -24,6 +24,7 @@ import { ExtensionPointDefaults } from "./point-defaults.js";
24
24
  import { ExtensionRegistryModule } from "./registry.js";
25
25
  import { ReplicaStatusStore } from "./sources.js";
26
26
  import { ExtensionStateModule } from "./state.module.js";
27
+ import { ExtensionAvailability } from "./unavailable.js";
27
28
  /**
28
29
  * The extensions domain: the extension host (it builds each `ctx` from the injected kernel
29
30
  * services), the package store and install records (the desired state the host converges to, one
@@ -60,6 +61,7 @@ ExtensionsModule = __decorate([
60
61
  OrgOverrides,
61
62
  ExtensionPointDefaults,
62
63
  BootstrapService,
64
+ ExtensionAvailability,
63
65
  ],
64
66
  exports: [
65
67
  ExtensionRegistryModule,
@@ -77,6 +79,7 @@ ExtensionsModule = __decorate([
77
79
  OrgOverrides,
78
80
  ExtensionPointDefaults,
79
81
  BootstrapService,
82
+ ExtensionAvailability,
80
83
  ],
81
84
  })
82
85
  ], ExtensionsModule);
@@ -179,6 +179,11 @@ export declare class ExtensionHost {
179
179
  * 安装记录不在这里:每次 converge 都按 PG 期望状态重新判定。
180
180
  */
181
181
  private readonly pendingActivations;
182
+ /**
183
+ * The load parameters of each config-declared extension that loaded: when its deployment config
184
+ * is cleared and the rest is invalid it goes back to {@link pendingActivations} (pending config).
185
+ */
186
+ private readonly declaredActivations;
182
187
  /** 安装记录准备好的候选(按插件名;sha 变了就作废)。 */
183
188
  private readonly prepared;
184
189
  /** 闸门放行后导入过的安装记录真实清单(按插件名;部署配置 schema 用,含待配置而未加载的)。 */
@@ -516,12 +521,38 @@ export declare class ExtensionHost {
516
521
  /**
517
522
  * 部署配置保存后(`kernel.plugin-deployment-config`)本副本重读并校验(C10;与 unload / reload 串行):
518
523
  * - 插件没在本副本生效 → `not_loaded`(配置声明的刷新后台的合法性判定;待配置的由 reconcile 加载);
519
- * - 不合法 → `invalid`:保持当前值,告警;
524
+ * - 不合法 → `invalid`:保持当前值,告警;但 PG 里已没有保存的配置(超级管理员清空了,`DELETE
525
+ * /api/v1/admin/extensions/:name/config`)、剩下的来源(启动配置、默认值)又不够时 → `unloaded`:卸下实例、
526
+ * 记为待配置(pending / config),依赖方连锁;重新配好后由 reconcile 加载;
520
527
  * - 没变 → `unchanged`;只改了 hot 字段 → `hot`:就地替换,插件经 `ctx.config` 读到新值,不重新 setup;
521
528
  * - 改了非 hot 字段 → `reload`:用新配置重新加载实例(先新后旧,排空在途调用),依赖方连锁;
522
529
  * 重新加载失败旧实例保留(`reload_failed`,记 error)。
523
530
  */
524
- applyDeploymentConfig(plugin: string): Promise<"not_loaded" | "invalid" | "unchanged" | "hot" | "reload" | "reload_failed">;
531
+ applyDeploymentConfig(plugin: string): Promise<"not_loaded" | "invalid" | "unloaded" | "unchanged" | "hot" | "reload" | "reload_failed">;
532
+ /** PG holds no deployment config for the plugin (it was cleared); a read error counts as no. */
533
+ private clearedInPg;
534
+ /**
535
+ * Unloads an extension whose deployment config was cleared and is now missing or invalid (in
536
+ * the host's serial queue): drains it, records pending / config (a config-declared one goes back
537
+ * to {@link pendingActivations}; an install record is decided again on every converge) and
538
+ * cascades to its dependents. It loads again without a restart once it is configured.
539
+ */
540
+ private unloadForMissingConfig;
541
+ /**
542
+ * Records an extension that is not loaded as pending configuration: a config-declared one goes
543
+ * back to {@link pendingActivations} (a later save loads it); an install record is decided again
544
+ * on every converge.
545
+ */
546
+ private markPendingConfig;
547
+ /**
548
+ * Before an extension unloaded for a dependency comes back ({@link cascade}): re-reads its
549
+ * deployment config, which may have been saved or cleared while it was down (applyDeploymentConfig
550
+ * only records validity then), and refreshes its load parameters, so it never returns on a stale
551
+ * config or revoked secrets. Returns false when the config is now missing or invalid and PG holds
552
+ * none: the extension is left pending configuration instead. A read error, or an invalid config
553
+ * that is still stored, keeps the previous config (as for a loaded extension).
554
+ */
555
+ private refreshConfigForRestore;
525
556
  /** 本次未加载、等待批准权限的插件(含因 `requires` 只能由它们满足而未加载的插件),按依赖拓扑序。 */
526
557
  pending(): PendingExtension[];
527
558
  /** 已加载插件的清单(按加载顺序,即依赖拓扑序)。 */