@capybara-hq/kernel 0.1.0-rc.22 → 0.1.0-rc.24

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 (234) hide show
  1. package/bootstrap.json +25 -25
  2. package/dist/admin/admin.controller.d.ts +3 -3
  3. package/dist/admin/admin.controller.js +6 -2
  4. package/dist/admin/admin.module.d.ts +2 -1
  5. package/dist/admin/admin.module.js +7 -3
  6. package/dist/admin/admin.schemas.d.ts +13 -0
  7. package/dist/admin/outbox-dead.controller.d.ts +23 -0
  8. package/dist/admin/outbox-dead.controller.js +62 -0
  9. package/dist/admin/outbox-dead.schemas.d.ts +8 -0
  10. package/dist/admin/outbox-dead.schemas.js +18 -0
  11. package/dist/admin/outbox-dead.service.d.ts +66 -0
  12. package/dist/admin/outbox-dead.service.js +179 -0
  13. package/dist/admin/overview.service.d.ts +40 -5
  14. package/dist/admin/overview.service.js +41 -7
  15. package/dist/agents/from-template.js +1 -1
  16. package/dist/background/finish.d.ts +5 -2
  17. package/dist/background/finish.js +14 -3
  18. package/dist/background/launch.d.ts +44 -5
  19. package/dist/background/launch.js +92 -9
  20. package/dist/background/session.d.ts +14 -2
  21. package/dist/background/session.js +26 -4
  22. package/dist/background/status.d.ts +1 -1
  23. package/dist/background/status.js +3 -3
  24. package/dist/background/stop.d.ts +0 -2
  25. package/dist/background/stop.js +1 -21
  26. package/dist/background/store.d.ts +8 -0
  27. package/dist/background/store.js +24 -0
  28. package/dist/catalog/admin-catalog.controller.d.ts +21 -2
  29. package/dist/catalog/admin-catalog.controller.js +45 -6
  30. package/dist/catalog/admin-catalog.schemas.d.ts +5 -0
  31. package/dist/catalog/admin-catalog.schemas.js +8 -0
  32. package/dist/catalog/catalog-content.d.ts +5 -0
  33. package/dist/catalog/catalog-content.js +1 -0
  34. package/dist/catalog/catalog.module.d.ts +2 -1
  35. package/dist/catalog/catalog.module.js +5 -1
  36. package/dist/catalog/marketplaces.service.d.ts +1 -1
  37. package/dist/catalog/platform-import-update.d.ts +50 -0
  38. package/dist/catalog/platform-import-update.js +116 -0
  39. package/dist/catalog/plugin-import.d.ts +36 -1
  40. package/dist/catalog/plugin-import.js +23 -1
  41. package/dist/catalog/plugin-upgrade.d.ts +18 -0
  42. package/dist/catalog/plugin-upgrade.js +19 -0
  43. package/dist/catalog/requests.service.js +2 -2
  44. package/dist/channels/channels.module.d.ts +5 -2
  45. package/dist/channels/channels.module.js +9 -2
  46. package/dist/channels/deliver-job.d.ts +25 -0
  47. package/dist/channels/deliver-job.js +25 -0
  48. package/dist/channels/inbound.d.ts +1 -1
  49. package/dist/channels/inbound.js +2 -15
  50. package/dist/channels/jobs.d.ts +28 -18
  51. package/dist/channels/jobs.js +63 -26
  52. package/dist/config/schema.d.ts +3 -6
  53. package/dist/config/schema.js +20 -27
  54. package/dist/conversations/agent-tree.d.ts +16 -0
  55. package/dist/conversations/agent-tree.js +36 -0
  56. package/dist/conversations/conversations.service.d.ts +44 -14
  57. package/dist/conversations/conversations.service.js +52 -38
  58. package/dist/conversations/event-log.d.ts +7 -10
  59. package/dist/conversations/event-log.js +24 -15
  60. package/dist/conversations/events.js +2 -1
  61. package/dist/conversations/queue.service.d.ts +8 -3
  62. package/dist/conversations/queue.service.js +37 -13
  63. package/dist/conversations/titles.d.ts +21 -8
  64. package/dist/conversations/titles.js +42 -15
  65. package/dist/db/kernel-schema.d.ts +26 -8
  66. package/dist/devices/devices.service.d.ts +12 -3
  67. package/dist/devices/devices.service.js +30 -9
  68. package/dist/errors.d.ts +15 -0
  69. package/dist/errors.js +15 -0
  70. package/dist/evals/run-replay.js +14 -8
  71. package/dist/extensions/extensions.module.js +3 -0
  72. package/dist/extensions/lifecycle.d.ts +6 -1
  73. package/dist/extensions/lifecycle.js +9 -2
  74. package/dist/extensions/usage-subscribers.d.ts +43 -0
  75. package/dist/extensions/usage-subscribers.js +108 -0
  76. package/dist/http/api.module.js +2 -0
  77. package/dist/identity/settings.d.ts +53 -3
  78. package/dist/identity/settings.js +92 -9
  79. package/dist/index.d.ts +1 -0
  80. package/dist/index.js +1 -0
  81. package/dist/infra/cli/kernel-cli.module.js +5 -0
  82. package/dist/infra/config/kernel-config.service.d.ts +7 -0
  83. package/dist/infra/config/kernel-config.service.js +20 -0
  84. package/dist/infra/events/kernel-events.d.ts +9 -35
  85. package/dist/infra/outbox/outbox-relay.module.d.ts +6 -0
  86. package/dist/infra/outbox/outbox-relay.module.js +18 -0
  87. package/dist/infra/outbox/outbox.dispatcher.d.ts +103 -0
  88. package/dist/infra/outbox/outbox.dispatcher.js +310 -0
  89. package/dist/infra/outbox/outbox.module.d.ts +24 -0
  90. package/dist/infra/outbox/outbox.module.js +50 -0
  91. package/dist/infra/outbox/outbox.relay.d.ts +31 -0
  92. package/dist/infra/outbox/outbox.relay.js +76 -0
  93. package/dist/infra/outbox/outbox.service.d.ts +51 -0
  94. package/dist/infra/outbox/outbox.service.js +131 -0
  95. package/dist/infra/outbox/registry.d.ts +120 -0
  96. package/dist/infra/outbox/registry.js +108 -0
  97. package/dist/infra/queue/queue-names.d.ts +8 -0
  98. package/dist/infra/queue/queue-names.js +16 -0
  99. package/dist/kernel.module.js +3 -0
  100. package/dist/local-devices/device-policy.service.d.ts +4 -0
  101. package/dist/local-devices/device-policy.service.js +61 -3
  102. package/dist/local-devices/local-device-gateway.d.ts +4 -2
  103. package/dist/local-devices/local-device-gateway.js +39 -14
  104. package/dist/local-devices/machines.d.ts +25 -1
  105. package/dist/local-devices/machines.js +91 -15
  106. package/dist/local-devices/policy-summary.d.ts +44 -1
  107. package/dist/local-devices/policy-summary.js +69 -0
  108. package/dist/models/embeddings.d.ts +9 -9
  109. package/dist/models/embeddings.js +11 -18
  110. package/dist/models/models.module.js +3 -0
  111. package/dist/orgs/orgs.service.js +7 -0
  112. package/dist/orgs/settings.controller.js +2 -2
  113. package/dist/orgs/settings.service.d.ts +11 -5
  114. package/dist/orgs/settings.service.js +28 -14
  115. package/dist/overrides.d.ts +20 -3
  116. package/dist/overrides.js +10 -2
  117. package/dist/platform/exclusions.js +5 -0
  118. package/dist/platform/ops/admin.ops.js +50 -9
  119. package/dist/platform/ops/catalog-admin.ops.d.ts +3 -1
  120. package/dist/platform/ops/catalog-admin.ops.js +32 -4
  121. package/dist/platform/ops/org-settings.ops.js +3 -3
  122. package/dist/platform/ops/orgs.ops.js +1 -0
  123. package/dist/platform/ops/outbox.ops.d.ts +21 -0
  124. package/dist/platform/ops/outbox.ops.js +125 -0
  125. package/dist/platform/ops/platform.ops.js +1 -1
  126. package/dist/platform/ops/schedules.ops.js +40 -1
  127. package/dist/platform/platform-ops.module.d.ts +2 -1
  128. package/dist/platform/platform-ops.module.js +3 -0
  129. package/dist/platform/route-schemas.js +3 -0
  130. package/dist/roles/worker.module.js +9 -4
  131. package/dist/runtime/langgraph-loop.js +13 -5
  132. package/dist/runtime/limits.d.ts +15 -0
  133. package/dist/runtime/limits.js +25 -0
  134. package/dist/runtime/loop.d.ts +8 -3
  135. package/dist/runtime/loop.js +2 -1
  136. package/dist/runtime/maintenance.d.ts +4 -2
  137. package/dist/runtime/maintenance.js +17 -2
  138. package/dist/runtime/model-call.d.ts +14 -16
  139. package/dist/runtime/model-call.js +14 -24
  140. package/dist/runtime/queue-lost-jobs.d.ts +24 -0
  141. package/dist/runtime/queue-lost-jobs.js +51 -0
  142. package/dist/runtime/run-control.d.ts +42 -5
  143. package/dist/runtime/run-control.js +66 -12
  144. package/dist/runtime/run-finish.d.ts +39 -12
  145. package/dist/runtime/run-finish.js +97 -14
  146. package/dist/runtime/run-jobs.d.ts +95 -13
  147. package/dist/runtime/run-jobs.js +199 -28
  148. package/dist/runtime/run-orphan-check.job.d.ts +142 -0
  149. package/dist/runtime/run-orphan-check.job.js +339 -0
  150. package/dist/runtime/run-processors.d.ts +16 -9
  151. package/dist/runtime/run-processors.js +1 -1
  152. package/dist/runtime/run-queue.d.ts +64 -55
  153. package/dist/runtime/run-queue.js +147 -284
  154. package/dist/runtime/run-steps.d.ts +1 -2
  155. package/dist/runtime/run-steps.js +8 -11
  156. package/dist/runtime/run-worker.d.ts +6 -17
  157. package/dist/runtime/run-worker.js +32 -34
  158. package/dist/runtime/runtime.module.d.ts +2 -3
  159. package/dist/runtime/runtime.module.js +5 -6
  160. package/dist/runtime/step-log.d.ts +16 -4
  161. package/dist/runtime/step-log.js +26 -6
  162. package/dist/runtime/stream.controller.d.ts +2 -4
  163. package/dist/runtime/stream.controller.js +5 -11
  164. package/dist/runtime/subagents/child.js +1 -1
  165. package/dist/runtime/subagents/definition.d.ts +2 -1
  166. package/dist/runtime/subagents/definition.js +4 -2
  167. package/dist/runtime/subagents/deliveries.d.ts +6 -3
  168. package/dist/runtime/subagents/deliveries.js +16 -7
  169. package/dist/runtime/subagents/dispatch.d.ts +12 -12
  170. package/dist/runtime/subagents/dispatch.js +13 -38
  171. package/dist/runtime/subagents/messages.d.ts +5 -1
  172. package/dist/runtime/subagents/messages.js +11 -3
  173. package/dist/runtime/subagents/skill-fork.d.ts +3 -3
  174. package/dist/runtime/subagents/skill-fork.js +5 -5
  175. package/dist/runtime/subagents/subagents.service.js +1 -1
  176. package/dist/runtime/subagents/tree-jobs.d.ts +61 -0
  177. package/dist/runtime/subagents/tree-jobs.js +86 -0
  178. package/dist/runtime/usage-report-jobs.d.ts +23 -48
  179. package/dist/runtime/usage-report-jobs.js +67 -119
  180. package/dist/runtime/usage-report.d.ts +28 -77
  181. package/dist/runtime/usage-report.js +35 -213
  182. package/dist/runtime/waits.d.ts +48 -198
  183. package/dist/runtime/waits.js +103 -805
  184. package/dist/sandbox/platform-tiers.d.ts +86 -0
  185. package/dist/sandbox/platform-tiers.js +97 -0
  186. package/dist/sandbox/sandbox.service.d.ts +18 -5
  187. package/dist/sandbox/sandbox.service.js +75 -20
  188. package/dist/sandbox/tiers.d.ts +14 -2
  189. package/dist/sandbox/tiers.js +8 -0
  190. package/dist/schedules/calendar.d.ts +134 -0
  191. package/dist/schedules/calendar.js +410 -0
  192. package/dist/schedules/fire.d.ts +1 -3
  193. package/dist/schedules/fire.js +5 -10
  194. package/dist/schedules/run-tracker.d.ts +0 -5
  195. package/dist/schedules/run-tracker.js +0 -13
  196. package/dist/schedules/scan.job.js +15 -20
  197. package/dist/schedules/schedule-math.d.ts +42 -0
  198. package/dist/schedules/schedule-math.js +52 -0
  199. package/dist/schedules/scheduled-tasks.service.d.ts +16 -0
  200. package/dist/schedules/scheduled-tasks.service.js +53 -0
  201. package/dist/schedules/schedules.controller.d.ts +5 -1
  202. package/dist/schedules/schedules.controller.js +15 -1
  203. package/dist/schedules/schedules.schemas.d.ts +35 -0
  204. package/dist/schedules/schedules.schemas.js +27 -0
  205. package/dist/schedules/store.d.ts +5 -0
  206. package/dist/schedules/store.js +20 -0
  207. package/dist/tools/approvals.service.d.ts +26 -7
  208. package/dist/tools/approvals.service.js +88 -10
  209. package/dist/tools/builtin-names.d.ts +5 -3
  210. package/dist/tools/builtin-names.js +12 -4
  211. package/dist/tools/builtins/builtin-tools.d.ts +1 -2
  212. package/dist/tools/builtins/builtin-tools.js +21 -17
  213. package/dist/tools/builtins/sandbox/bash.js +9 -3
  214. package/dist/tools/builtins/sandbox/common.d.ts +18 -1
  215. package/dist/tools/builtins/sandbox/common.js +14 -1
  216. package/dist/tools/builtins/sandbox/index.d.ts +2 -1
  217. package/dist/tools/builtins/sandbox/index.js +4 -1
  218. package/dist/tools/builtins/sandbox/task-list.d.ts +12 -0
  219. package/dist/tools/builtins/sandbox/task-list.js +130 -0
  220. package/dist/tools/builtins/sandbox/task-output.d.ts +8 -1
  221. package/dist/tools/builtins/sandbox/task-output.js +21 -3
  222. package/dist/tools/builtins/web/extract.d.ts +2 -4
  223. package/dist/tools/builtins/web/extract.js +2 -5
  224. package/dist/tools/pipeline.d.ts +1 -1
  225. package/dist/tools/pipeline.js +1 -1
  226. package/dist/tools/questions.service.d.ts +15 -6
  227. package/dist/tools/questions.service.js +20 -8
  228. package/dist/tools/registry.d.ts +4 -2
  229. package/dist/tools/registry.js +4 -3
  230. package/dist/tools/tools.module.js +4 -3
  231. package/package.json +3 -3
  232. package/src/migrations/0118_device_policy_ops.sql +6 -0
  233. package/src/migrations/0119_outbox.sql +22 -0
  234. package/src/migrations/0120_drop_usage_report_sweep.sql +7 -0
@@ -5,14 +5,19 @@ import { CHANNEL_WEBHOOK_TIMINGS, type ChannelWebhookTimings } from "./channels/
5
5
  import type { EvalReplayHooks } from "./evals/run-replay.js";
6
6
  import { EVAL_REPLAY_HOOKS } from "./evals/worker.js";
7
7
  import { BOOTSTRAP_LOCK_TTL } from "./extensions/bootstrap.js";
8
+ import { USAGE_SUBSCRIBERS_CLOCK } from "./extensions/usage-subscribers.js";
8
9
  import { FILE_PREVIEW_TIMEOUT } from "./files/previewers.js";
10
+ import { OUTBOX_DISPATCH_FAILS } from "./infra/outbox/outbox.dispatcher.js";
11
+ import { OUTBOX_FAST_PATH_SETTLED } from "./infra/outbox/outbox.module.js";
12
+ import { OUTBOX_STRICT_CONFLICTS } from "./infra/outbox/outbox.service.js";
9
13
  import { PRESENCE_INTERVAL_MS } from "./infra/presence/replica-presence.js";
14
+ import type { KernelQueueName } from "./infra/queue/queue-names.js";
10
15
  import { LIST_MODELS_TIMEOUT } from "./runtime/providers.js";
11
16
  import { RUN_CONTEXT_CLOCK } from "./runtime/run-context.service.js";
17
+ import { ENSURE_RUN_FAILS } from "./runtime/run-queue.js";
12
18
  import { AGENT_LOOP_FACTORY, type AgentLoopFactory } from "./runtime/run-steps.js";
13
19
  import { RUN_HOOKS, type RunHooks } from "./runtime/run-worker.js";
14
20
  import { SUBAGENT_MESSAGES_HOOKS, type SubagentMessagesHooks } from "./runtime/subagents/messages.js";
15
- import { USAGE_REPORT_RETRY, type UsageReportRetry } from "./runtime/usage-report.js";
16
21
  import { SANDBOX_LEASE_TIMINGS, type SandboxLeaseTimings } from "./sandbox/leases.js";
17
22
  import { SETUP_CHECK_TIMEOUT } from "./setup/setup-checks.service.js";
18
23
  import { TOOL_PIPELINE_HOOKS, type ToolPipelineHooks } from "./tools/pipeline.js";
@@ -26,13 +31,21 @@ import { EMBED_TOKEN_CLOCK } from "./ui/embed-token.js";
26
31
  * - `EVAL_REPLAY_HOOKS`: the hooks of the eval full-run replay and the judge;
27
32
  * - `TOOL_PIPELINE_HOOKS`: the tool pipeline's hooks and policy decision;
28
33
  * - `SUBAGENT_MESSAGES_HOOKS`: the sub-agent message tools' hooks (a send raced by a run's end);
29
- * - `BOOTSTRAP_LOCK_TTL`, `FILE_PREVIEW_TIMEOUT`, `LIST_MODELS_TIMEOUT`, `USAGE_REPORT_RETRY`,
34
+ * - `BOOTSTRAP_LOCK_TTL`, `FILE_PREVIEW_TIMEOUT`, `LIST_MODELS_TIMEOUT`,
30
35
  * `SANDBOX_LEASE_TIMINGS`, `CHANNEL_WEBHOOK_TIMINGS`, `SETUP_CHECK_TIMEOUT`,
31
36
  * `PRESENCE_INTERVAL_MS`: shorter timings;
32
37
  * - `ADMIN_USAGE_TIMINGS`: the usage aggregate's statement timeout and clock;
33
38
  * - `EMBED_TOKEN_CLOCK`: the clock embed tokens are issued and checked with;
34
39
  * - `RUN_CONTEXT_CLOCK`: the clock run start reads the run context's date from, and the
35
40
  * `CurrentTime` builtin the time;
41
+ * - `OUTBOX_STRICT_CONFLICTS`: a reused outbox job id with different data throws (tests) instead
42
+ * of logging an error;
43
+ * - `OUTBOX_DISPATCH_FAILS`: returns true to make the outbox dispatcher's adds to the given queue
44
+ * fail (a Redis outage);
45
+ * - `USAGE_SUBSCRIBERS_CLOCK`: the clock the `usage.report` subscriber cache ages with;
46
+ * - `OUTBOX_FAST_PATH_SETTLED`: receives each detached outbox fast-path pass (a test awaits them);
47
+ * - `ENSURE_RUN_FAILS`: returns true to make `RunQueue.ensureRun` throw (Redis unreachable, or the
48
+ * direct call after a commit skipped by a crash);
36
49
  * - `APP_INTERCEPTOR`: one more global interceptor (a probe of the matched routes).
37
50
  */
38
51
  interface KernelSeams {
@@ -44,7 +57,6 @@ interface KernelSeams {
44
57
  [BOOTSTRAP_LOCK_TTL]: number;
45
58
  [FILE_PREVIEW_TIMEOUT]: number;
46
59
  [LIST_MODELS_TIMEOUT]: number;
47
- [USAGE_REPORT_RETRY]: UsageReportRetry;
48
60
  [SANDBOX_LEASE_TIMINGS]: Partial<SandboxLeaseTimings>;
49
61
  [CHANNEL_WEBHOOK_TIMINGS]: Partial<ChannelWebhookTimings>;
50
62
  [SETUP_CHECK_TIMEOUT]: number;
@@ -52,6 +64,11 @@ interface KernelSeams {
52
64
  [ADMIN_USAGE_TIMINGS]: Partial<AdminUsageTimings>;
53
65
  [EMBED_TOKEN_CLOCK]: () => number;
54
66
  [RUN_CONTEXT_CLOCK]: () => number;
67
+ [OUTBOX_STRICT_CONFLICTS]: boolean;
68
+ [OUTBOX_DISPATCH_FAILS]: (queue: KernelQueueName) => boolean;
69
+ [USAGE_SUBSCRIBERS_CLOCK]: () => number;
70
+ [OUTBOX_FAST_PATH_SETTLED]: (pass: Promise<void>) => void;
71
+ [ENSURE_RUN_FAILS]: () => boolean;
55
72
  [APP_INTERCEPTOR]: NestInterceptor;
56
73
  }
57
74
  /**
package/dist/overrides.js CHANGED
@@ -3,14 +3,18 @@ import { ADMIN_USAGE_TIMINGS } from "./admin/usage.service.js";
3
3
  import { CHANNEL_WEBHOOK_TIMINGS } from "./channels/webhook.js";
4
4
  import { EVAL_REPLAY_HOOKS } from "./evals/worker.js";
5
5
  import { BOOTSTRAP_LOCK_TTL } from "./extensions/bootstrap.js";
6
+ import { USAGE_SUBSCRIBERS_CLOCK } from "./extensions/usage-subscribers.js";
6
7
  import { FILE_PREVIEW_TIMEOUT } from "./files/previewers.js";
8
+ import { OUTBOX_DISPATCH_FAILS } from "./infra/outbox/outbox.dispatcher.js";
9
+ import { OUTBOX_FAST_PATH_SETTLED } from "./infra/outbox/outbox.module.js";
10
+ import { OUTBOX_STRICT_CONFLICTS } from "./infra/outbox/outbox.service.js";
7
11
  import { PRESENCE_INTERVAL_MS } from "./infra/presence/replica-presence.js";
8
12
  import { LIST_MODELS_TIMEOUT } from "./runtime/providers.js";
9
13
  import { RUN_CONTEXT_CLOCK } from "./runtime/run-context.service.js";
14
+ import { ENSURE_RUN_FAILS } from "./runtime/run-queue.js";
10
15
  import { AGENT_LOOP_FACTORY } from "./runtime/run-steps.js";
11
16
  import { RUN_HOOKS } from "./runtime/run-worker.js";
12
17
  import { SUBAGENT_MESSAGES_HOOKS, } from "./runtime/subagents/messages.js";
13
- import { USAGE_REPORT_RETRY } from "./runtime/usage-report.js";
14
18
  import { SANDBOX_LEASE_TIMINGS } from "./sandbox/leases.js";
15
19
  import { SETUP_CHECK_TIMEOUT } from "./setup/setup-checks.service.js";
16
20
  import { TOOL_PIPELINE_HOOKS } from "./tools/pipeline.js";
@@ -24,7 +28,7 @@ const SEAM_TOKENS = [
24
28
  BOOTSTRAP_LOCK_TTL,
25
29
  FILE_PREVIEW_TIMEOUT,
26
30
  LIST_MODELS_TIMEOUT,
27
- USAGE_REPORT_RETRY,
31
+ USAGE_SUBSCRIBERS_CLOCK,
28
32
  SANDBOX_LEASE_TIMINGS,
29
33
  CHANNEL_WEBHOOK_TIMINGS,
30
34
  SETUP_CHECK_TIMEOUT,
@@ -32,6 +36,10 @@ const SEAM_TOKENS = [
32
36
  ADMIN_USAGE_TIMINGS,
33
37
  EMBED_TOKEN_CLOCK,
34
38
  RUN_CONTEXT_CLOCK,
39
+ OUTBOX_STRICT_CONFLICTS,
40
+ OUTBOX_DISPATCH_FAILS,
41
+ OUTBOX_FAST_PATH_SETTLED,
42
+ ENSURE_RUN_FAILS,
35
43
  APP_INTERCEPTOR,
36
44
  ];
37
45
  const allSeamsListed = true;
@@ -95,6 +95,11 @@ export const PLATFORM_EXCLUSIONS = [
95
95
  category: "human-only",
96
96
  reason: "Confirms an import review, an approval decision by the super admin",
97
97
  },
98
+ {
99
+ route: "POST /api/v1/admin/catalog/imports/:stagingId/update",
100
+ category: "human-only",
101
+ reason: "Confirms an import review together with the platform update it applies, an approval decision by the super admin",
102
+ },
98
103
  {
99
104
  route: "GET /api/v1/admin/catalog/items/:id/icon",
100
105
  category: "transport",
@@ -43,6 +43,7 @@ const SettingsInput = DEPLOYMENT_SETTINGS_PATCH.pick({
43
43
  uiTheme: true,
44
44
  uiArrangement: true,
45
45
  clientExtensions: true,
46
+ sandboxTiers: true,
46
47
  }).strict();
47
48
  const ProviderId = ModelProviderParams.shape.provider.describe("The model provider (models.platform-list), e.g. the plugin name of its extension.");
48
49
  /** `provider/model` of a purpose target, or null. */
@@ -77,6 +78,22 @@ function attentionRows(a) {
77
78
  ? `Check the provider's deployment config and connection on its extension page (/admin/extensions/${p.plugin}); the models page (/admin/models) shows the list.`
78
79
  : "The provider lists no chat model that is switched on: switch one on in the admin console (/admin/models) or check the provider's config.",
79
80
  })),
81
+ ...a.outbox.map((o) => ({
82
+ kind: "outbox",
83
+ id: o.kind,
84
+ name: "Background work that could not be queued",
85
+ state: "dead",
86
+ reason: `${o.count} dead outbox row(s), the oldest dead since ${o.oldestAt}`,
87
+ next: "List them with admin.outbox-list-dead, then retry each with admin.outbox-retry or drop it with admin.outbox-discard.",
88
+ })),
89
+ ...a.queue.map((q) => ({
90
+ kind: "queue",
91
+ id: q.kind,
92
+ name: "The queue lost background jobs",
93
+ state: "lost_jobs",
94
+ reason: `${q.count} queued run job(s) were missing from the queue, the last at ${q.lastAt}; they were queued again`,
95
+ next: "Redis lost data: check its persistence (AOF or snapshots) and whether it restarted or evicted keys. Nothing to do per run; the item clears a week after the last loss.",
96
+ })),
80
97
  ],
81
98
  more: a.more,
82
99
  unavailable: a.unavailable,
@@ -126,7 +143,7 @@ let AdminOperations = class AdminOperations {
126
143
  this.registry.register([
127
144
  defineOperation({
128
145
  id: "admin.overview",
129
- description: "The admin console's dashboard numbers (super admin): orgs, accounts and attentionTotal, everything waiting for a super admin (the platform inbox total plus the extensions, plugin updates and model providers admin.attention lists); partial is true when one of those lists could not be read right now (attentionTotal then leaves it out).",
146
+ description: "The admin console's dashboard numbers (super admin): orgs, accounts and attentionTotal, everything waiting for a super admin (the platform inbox total plus the extensions, plugin updates and model providers admin.attention lists, every dead outbox row and the lost-jobs item of the run queue); partial is true when one of those lists could not be read right now (attentionTotal then leaves it out).",
130
147
  input: z.object({}).strict(),
131
148
  example: {},
132
149
  authz: { superAdmin: true },
@@ -136,7 +153,7 @@ let AdminOperations = class AdminOperations {
136
153
  }),
137
154
  defineOperation({
138
155
  id: "admin.attention",
139
- description: "What needs the super admin besides the platform inbox (super admin), one compact row each (kind, id, name, state, reason, next step): extensions (reason config, load_failed, approval, dependency, conflict, converging or legacy_format), platform plugins with a newer marketplace version (reason names both versions) and model providers (reason list_failed or no_chat_model). Each kind lists at most 20 rows; more counts the rest per kind. unavailable names a kind that could not be read right now (try again later). The platform inbox itself is inbox.platform-list.",
156
+ description: "What needs the super admin besides the platform inbox (super admin), one compact row each (kind, id, name, state, reason, next step): extensions (reason config, load_failed, approval, dependency, conflict, converging or legacy_format), platform plugins with a newer marketplace version (reason names both versions) model providers (reason list_failed or no_chat_model) background work the kernel could not queue (kind outbox: how many outbox rows are dead and since when) and run jobs the queue lost (kind queue: Redis lost data; the runs were queued again). Each kind lists at most 20 rows; more counts the rest per kind. unavailable names a kind that could not be read right now (try again later). The platform inbox itself is inbox.platform-list.",
140
157
  input: z.object({}).strict(),
141
158
  example: {},
142
159
  authz: { superAdmin: true },
@@ -182,17 +199,17 @@ let AdminOperations = class AdminOperations {
182
199
  }),
183
200
  defineOperation({
184
201
  id: "admin.settings",
185
- description: "Read the deployment settings (super admin): who may create orgs (orgCreation), the price currency, whether orgs may create their own connectors and skills, whether org admins may browse the marketplaces, and the per-org limit overrides keyed by org id (orgs.get reads one org's).",
202
+ description: "Read the deployment settings (super admin): who may create orgs (orgCreation), the price currency, whether orgs may create their own connectors and skills, whether org admins may browse the marketplaces, the per-org limit overrides keyed by org id (orgs.get reads one org's), and the platform's sandbox levels in effect (sandboxTiers: max, default, allowUnsandboxed, with sources: env, file or nacos are set in the startup config and read-only, db chosen in the admin console, default).",
186
203
  input: z.object({}).strict(),
187
204
  example: {},
188
205
  authz: { superAdmin: true },
189
206
  mirrors: ["GET /api/v1/admin/settings"],
190
207
  confirm: "read",
191
- run: () => this.settings.get(),
208
+ run: () => this.settings.view(),
192
209
  }),
193
210
  defineOperation({
194
211
  id: "admin.update-settings",
195
- description: "Change deployment settings (super admin); give only the keys to change: orgCreation (anyone or super_admin), priceCurrency (ISO 4217 code), customConnectors / customSkills (allow or deny: whether orgs may create their own instead of installing from the catalog), orgMarketplaceBrowse (true or false), uiTheme ({ id }: the platform default theme, a platform theme whose scope is all, or null for the built-in theme; it is what every org falls back to and what the sign-in pages show), uiArrangement ({ <slot>: { hidden, order } } for a list slot, { <slot>: { use } } for a single slot: the platform default arrangement of UI slots, with contribution keys <extension>/<contribution>; hidden ones are not listed but still open by URL; use names the contribution that replaces the built-in, null for the built-in; null for a slot removes its entry), clientExtensions ({ enabled?, disabled? }: the kill switch of plugin client code; enabled false stops every plugin's interface code in every browser, disabled is the whole list of plugins whose interface code alone is stopped while their tools keep working; read the current list from admin.settings first). Per-org limits are orgs.set-limits.",
212
+ description: "Change deployment settings (super admin); give only the keys to change: orgCreation (anyone or super_admin), priceCurrency (ISO 4217 code), customConnectors / customSkills (allow or deny: whether orgs may create their own instead of installing from the catalog), orgMarketplaceBrowse (true or false), uiTheme ({ id }: the platform default theme, a platform theme whose scope is all, or null for the built-in theme; it is what every org falls back to and what the sign-in pages show), uiArrangement ({ <slot>: { hidden, order } } for a list slot, { <slot>: { use } } for a single slot: the platform default arrangement of UI slots, with contribution keys <extension>/<contribution>; hidden ones are not listed but still open by URL; use names the contribution that replaces the built-in, null for the built-in; null for a slot removes its entry), clientExtensions ({ enabled?, disabled? }: the kill switch of plugin client code; enabled false stops every plugin's interface code in every browser, disabled is the whole list of plugins whose interface code alone is stopped while their tools keep working; read the current list from admin.settings first), sandboxTiers ({ max?, default?, allowUnsandboxed? }: the platform's sandbox levels strict < dev < open; null clears a field back to its default; through this tool they may only be lowered, never raised, and fields set in the startup config are read-only). Per-org limits are orgs.set-limits.",
196
213
  input: SettingsInput.refine((b) => Object.keys(b).length > 0, {
197
214
  message: "at least one setting is required",
198
215
  }),
@@ -207,6 +224,14 @@ let AdminOperations = class AdminOperations {
207
224
  code: "validation_failed",
208
225
  next: "Fix the values as the message says (admin.settings shows the current ones).",
209
226
  },
227
+ {
228
+ code: "deployment.sandbox_tier_not_allowed",
229
+ next: "Through this tool the platform's sandbox levels may only be lowered; to raise them, ask a super admin to change them in the admin console settings on the web.",
230
+ },
231
+ {
232
+ code: "deployment.setting_readonly",
233
+ next: "That sandbox level is set in the deployment's startup config (environment, file or Nacos; admin.settings shows the source); it can only be changed there, by the operator.",
234
+ },
210
235
  {
211
236
  code: "theme.not_available",
212
237
  next: "The platform default must be a platform theme whose scope is all, not disabled, and on in every organization. When the details list orgs, the theme is off in those organizations: tell the person their names, then choose another theme (plugins.components with kind theme lists them) or have it switched on in those organizations first; { id: null } sets the built-in theme.",
@@ -214,13 +239,27 @@ let AdminOperations = class AdminOperations {
214
239
  ],
215
240
  precheck: async (i) => {
216
241
  const r = DeploymentSettingsBody.safeParse(i);
217
- return r.success
242
+ if (!r.success) {
243
+ return {
244
+ ok: false,
245
+ code: "validation_failed",
246
+ message: r.error.issues[0]?.message ?? "",
247
+ };
248
+ }
249
+ const tiers = i.sandboxTiers;
250
+ return tiers === undefined
218
251
  ? { ok: true }
219
- : { ok: false, code: "validation_failed", message: r.error.issues[0]?.message ?? "" };
252
+ : precheckBy(() => this.settings.checkSandboxTiers(tiers, { onlyNarrows: true }));
220
253
  },
221
254
  summary: async (i) => {
222
- const { uiTheme, uiArrangement, clientExtensions, ...rest } = i;
255
+ const { uiTheme, uiArrangement, clientExtensions, sandboxTiers, ...rest } = i;
223
256
  const parts = Object.entries(rest).map(([k, v]) => `${k}=${String(v)}`);
257
+ if (sandboxTiers !== undefined) {
258
+ parts.push(`sandboxTiers=${Object.entries(sandboxTiers)
259
+ .filter(([, v]) => v !== undefined)
260
+ .map(([k, v]) => `${k}:${String(v)}`)
261
+ .join(" ")}`);
262
+ }
224
263
  const zh = [...parts];
225
264
  const en = [...parts];
226
265
  if (uiTheme !== undefined) {
@@ -253,7 +292,9 @@ let AdminOperations = class AdminOperations {
253
292
  en: `Change the deployment settings: ${en.join(", ")}`,
254
293
  };
255
294
  },
256
- run: (input, ctx) => this.settings.update(input, ctx.actorAccountId, undefined, viaAgent("admin.update-settings", ctx)),
295
+ run: (input, ctx) => this.settings.update(input, ctx.actorAccountId, undefined, viaAgent("admin.update-settings", ctx),
296
+ // a person raises the platform's sandbox levels, never an agent (dev tiers spec §2)
297
+ { onlyNarrows: true }),
257
298
  }),
258
299
  defineOperation({
259
300
  id: "models.platform-list",
@@ -2,6 +2,7 @@ import { type OnModuleInit } from "@nestjs/common";
2
2
  import { type AppearanceResult, AppearanceService } from "../../catalog/appearance.service.js";
3
3
  import { CatalogService } from "../../catalog/catalog.service.js";
4
4
  import { CatalogScopeService } from "../../catalog/catalog-scope.service.js";
5
+ import { PlatformImportUpdate } from "../../catalog/platform-import-update.js";
5
6
  import { PluginImport, type PluginReview } from "../../catalog/plugin-import.js";
6
7
  import { KernelDb } from "../../infra/database/kernel-db.js";
7
8
  import { ThemesService } from "../../themes/themes.service.js";
@@ -70,10 +71,11 @@ export declare class CatalogAdminOperations implements OnModuleInit {
70
71
  private readonly catalog;
71
72
  private readonly scope;
72
73
  private readonly pluginImport;
74
+ private readonly importUpdate;
73
75
  private readonly kdb;
74
76
  private readonly appearance;
75
77
  private readonly themes;
76
- constructor(registry: PlatformOperations, catalog: CatalogService, scope: CatalogScopeService, pluginImport: PluginImport, kdb: KernelDb, appearance: AppearanceService, themes: ThemesService);
78
+ constructor(registry: PlatformOperations, catalog: CatalogService, scope: CatalogScopeService, pluginImport: PluginImport, importUpdate: PlatformImportUpdate, kdb: KernelDb, appearance: AppearanceService, themes: ThemesService);
77
79
  /** The precheck refusal of another org's private plugin (the phase-1 rule), else null. */
78
80
  private otherOrgs;
79
81
  /** Whether an org owns the item (its owner org manages it, not the super admin's agent). */
@@ -14,6 +14,7 @@ import { CatalogDisabledBody, CatalogGitImportBody, CatalogIdPathParams, Catalog
14
14
  import { AppearanceService } from "../../catalog/appearance.service.js";
15
15
  import { CatalogService } from "../../catalog/catalog.service.js";
16
16
  import { CatalogScopeService } from "../../catalog/catalog-scope.service.js";
17
+ import { PlatformImportUpdate } from "../../catalog/platform-import-update.js";
17
18
  import { PluginImport } from "../../catalog/plugin-import.js";
18
19
  import { ApiError } from "../../errors.js";
19
20
  import { KernelDb } from "../../infra/database/kernel-db.js";
@@ -125,14 +126,16 @@ let CatalogAdminOperations = class CatalogAdminOperations {
125
126
  catalog;
126
127
  scope;
127
128
  pluginImport;
129
+ importUpdate;
128
130
  kdb;
129
131
  appearance;
130
132
  themes;
131
- constructor(registry, catalog, scope, pluginImport, kdb, appearance, themes) {
133
+ constructor(registry, catalog, scope, pluginImport, importUpdate, kdb, appearance, themes) {
132
134
  this.registry = registry;
133
135
  this.catalog = catalog;
134
136
  this.scope = scope;
135
137
  this.pluginImport = pluginImport;
138
+ this.importUpdate = importUpdate;
136
139
  this.kdb = kdb;
137
140
  this.appearance = appearance;
138
141
  this.themes = themes;
@@ -313,6 +316,30 @@ let CatalogAdminOperations = class CatalogAdminOperations {
313
316
  };
314
317
  },
315
318
  }),
319
+ defineOperation({
320
+ id: "plugins.import-update-preview",
321
+ description: "Preview what a staged new version of an installed platform plugin does as the platform update (super admin): every component's change, the extension step and the org connectors it touches. Nothing is imported or changed; the person confirms the review and the update together on the web (reviewUrl).",
322
+ input: z.object({ stagingId: StagingId }).strict(),
323
+ example: { stagingId: "3f1c2a9e-5b7d-4e21-9c0a-1d2e3f4a5b6c" },
324
+ authz: { superAdmin: true },
325
+ mirrors: ["GET /api/v1/admin/catalog/imports/:stagingId/update-preview"],
326
+ confirm: "read",
327
+ errors: [
328
+ {
329
+ code: "plugin.staging_not_found",
330
+ next: "The staged import expired (24 hours) or was confirmed already: prepare it again with plugins.import-npm or plugins.import-git.",
331
+ },
332
+ {
333
+ code: "plugin.upgrade_target_invalid",
334
+ next: "The plugin is not installed on the platform yet (reason not_installed: the review installs it), or the platform cannot move to this version (the details say why).",
335
+ },
336
+ ],
337
+ run: async (input) => ({
338
+ preview: await this.importUpdate.preview(input.stagingId),
339
+ reviewUrl: reviewUrl(input.stagingId),
340
+ next: CONFIRM_ON_WEB,
341
+ }),
342
+ }),
316
343
  defineOperation({
317
344
  id: "plugins.scope-preview",
318
345
  description: "Preview changing where a platform plugin is on (super admin): a scope (all: every org; optional: orgs switch it on; named: only the orgs listed, with orgs) or disabled: true (off everywhere). Returns the orgs that lose it (with the agents there), the components it takes back, name conflicts, and the scopeHash plugins.set-scope or plugins.set-disabled needs. Nothing is written; show the preview to the person first.",
@@ -675,8 +702,9 @@ CatalogAdminOperations = __decorate([
675
702
  __param(1, Inject(CatalogService)),
676
703
  __param(2, Inject(CatalogScopeService)),
677
704
  __param(3, Inject(PluginImport)),
678
- __param(4, Inject(KernelDb)),
679
- __param(5, Inject(AppearanceService)),
680
- __param(6, Inject(ThemesService))
705
+ __param(4, Inject(PlatformImportUpdate)),
706
+ __param(5, Inject(KernelDb)),
707
+ __param(6, Inject(AppearanceService)),
708
+ __param(7, Inject(ThemesService))
681
709
  ], CatalogAdminOperations);
682
710
  export { CatalogAdminOperations };
@@ -47,7 +47,7 @@ let OrgSettingsOperations = class OrgSettingsOperations {
47
47
  confirm: "read",
48
48
  run: async (_input, ctx) => ({
49
49
  settings: await this.settings.get(ctx.orgId),
50
- deployment: this.settings.deployment(),
50
+ deployment: await this.settings.deployment(),
51
51
  sandboxLimits: await this.settings.sandboxLimits(ctx.orgId),
52
52
  }),
53
53
  }),
@@ -80,8 +80,8 @@ let OrgSettingsOperations = class OrgSettingsOperations {
80
80
  },
81
81
  ],
82
82
  precheck: (i, ctx) => precheckBy(async () => {
83
- this.settings.check(i);
84
- this.settings.assertOnlyNarrows(await this.settings.get(ctx.orgId), i);
83
+ await this.settings.check(i);
84
+ await this.settings.assertOnlyNarrows(await this.settings.get(ctx.orgId), i);
85
85
  }),
86
86
  summary: async (i, ctx) => {
87
87
  const { theme, ...rest } = i;
@@ -161,6 +161,7 @@ let OrgsOperations = class OrgsOperations {
161
161
  "uiTheme",
162
162
  "uiArrangement",
163
163
  "clientExtensions",
164
+ "sandboxTiers",
164
165
  ],
165
166
  extras: ["orgId", "runConcurrency", "sandbox", "subagents"],
166
167
  confirm: "platform",
@@ -0,0 +1,21 @@
1
+ import { type OnModuleInit } from "@nestjs/common";
2
+ import { OutboxDeadService } from "../../admin/outbox-dead.service.js";
3
+ import { KernelDb } from "../../infra/database/kernel-db.js";
4
+ import { PlatformOperations } from "../registry.js";
5
+ /**
6
+ * The super admin's dead outbox rows through the `Platform` tool (transactional outbox spec
7
+ * §3.4): the list, retry and discard of `/api/v1/admin/outbox/dead*`, run through the same
8
+ * service. Dead rows are the deployment's, not an org's: the operations act on all of them.
9
+ */
10
+ export declare class OutboxOperations implements OnModuleInit {
11
+ private readonly registry;
12
+ private readonly dead;
13
+ private readonly kdb;
14
+ constructor(registry: PlatformOperations, dead: OutboxDeadService, kdb: KernelDb);
15
+ /** The dead row's job (queue and name) for a card, or null when no dead row has the id. */
16
+ private jobOf;
17
+ private precheck;
18
+ /** "job-name on queue" for a card, or the bare id when the row is gone. */
19
+ private label;
20
+ onModuleInit(): void;
21
+ }
@@ -0,0 +1,125 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
+ return function (target, key) { decorator(target, key, paramIndex); }
9
+ };
10
+ import { Inject, Injectable } from "@nestjs/common";
11
+ import { z } from "zod";
12
+ import { OutboxDeadParams } from "../../admin/outbox-dead.schemas.js";
13
+ import { OutboxDeadService } from "../../admin/outbox-dead.service.js";
14
+ import { KernelDb } from "../../infra/database/kernel-db.js";
15
+ import { defineOperation } from "../operation.js";
16
+ import { PlatformOperations } from "../registry.js";
17
+ import { viaAgent } from "./errors.js";
18
+ const DeadIdInput = OutboxDeadParams.strict();
19
+ /**
20
+ * The super admin's dead outbox rows through the `Platform` tool (transactional outbox spec
21
+ * §3.4): the list, retry and discard of `/api/v1/admin/outbox/dead*`, run through the same
22
+ * service. Dead rows are the deployment's, not an org's: the operations act on all of them.
23
+ */
24
+ let OutboxOperations = class OutboxOperations {
25
+ registry;
26
+ dead;
27
+ kdb;
28
+ constructor(registry, dead, kdb) {
29
+ this.registry = registry;
30
+ this.dead = dead;
31
+ this.kdb = kdb;
32
+ }
33
+ /** The dead row's job (queue and name) for a card, or null when no dead row has the id. */
34
+ async jobOf(id) {
35
+ const row = await this.kdb.db
36
+ .selectFrom("outbox")
37
+ .select(["queue", "job_name"])
38
+ .where("id", "=", id)
39
+ .where("dead_at", "is not", null)
40
+ .executeTakeFirst();
41
+ return row ?? null;
42
+ }
43
+ async precheck(id) {
44
+ return (await this.jobOf(id)) === null
45
+ ? { ok: false, code: "outbox.not_found", message: `No dead outbox row ${id}.` }
46
+ : { ok: true };
47
+ }
48
+ /** "job-name on queue" for a card, or the bare id when the row is gone. */
49
+ async label(id) {
50
+ const job = await this.jobOf(id);
51
+ return job === null ? `#${id}` : `${job.job_name} (${job.queue}, #${id})`;
52
+ }
53
+ onModuleInit() {
54
+ this.registry.register([
55
+ defineOperation({
56
+ id: "admin.outbox-list-dead",
57
+ description: "List background work the kernel could not queue (super admin): outbox rows dead after their last delivery attempt, oldest first (at most 200), each with its id, queue, job name, job id, org (null for platform work), attempts, last error and when it died. Retry one with admin.outbox-retry or drop it with admin.outbox-discard.",
58
+ input: z.object({}).strict(),
59
+ example: {},
60
+ authz: { superAdmin: true },
61
+ mirrors: ["GET /api/v1/admin/outbox/dead"],
62
+ confirm: "read",
63
+ run: () => this.dead.list(),
64
+ }),
65
+ defineOperation({
66
+ id: "admin.outbox-retry",
67
+ description: "Queue a dead outbox row again (super admin): it gets fresh attempts and is delivered right away. When the same job is already owed by a pending row, the dead copy is discarded instead; outcome says which (retried or already_owed). A job whose subject is gone since is harmless: it finds nothing to do. The platform audit log records it.",
68
+ input: DeadIdInput,
69
+ example: { id: "42" },
70
+ authz: { superAdmin: true },
71
+ mirrors: ["POST /api/v1/admin/outbox/dead/:id/retry"],
72
+ confirm: "platform",
73
+ errors: [
74
+ {
75
+ code: "outbox.not_found",
76
+ next: "The row is no longer dead (retried, discarded or delivered): list the dead rows again with admin.outbox-list-dead.",
77
+ },
78
+ ],
79
+ precheck: (i) => this.precheck(i.id),
80
+ summary: async (i) => {
81
+ const job = await this.label(i.id);
82
+ return {
83
+ zh: `重新排入无法排入队列的后台任务 ${job}`,
84
+ en: `Queue background work that could not be queued again: ${job}`,
85
+ };
86
+ },
87
+ run: (input, ctx) => this.dead.retry(input.id, { accountId: ctx.actorAccountId }, viaAgent("admin.outbox-retry", ctx)),
88
+ }),
89
+ defineOperation({
90
+ id: "admin.outbox-discard",
91
+ description: "Discard a dead outbox row (super admin): its job is never run. Use it only when the work is no longer wanted; to run it, use admin.outbox-retry. The platform audit log records it.",
92
+ input: DeadIdInput,
93
+ example: { id: "42" },
94
+ authz: { superAdmin: true },
95
+ mirrors: ["DELETE /api/v1/admin/outbox/dead/:id"],
96
+ confirm: "platform",
97
+ errors: [
98
+ {
99
+ code: "outbox.not_found",
100
+ next: "The row is no longer dead (retried, discarded or delivered): list the dead rows again with admin.outbox-list-dead.",
101
+ },
102
+ ],
103
+ precheck: (i) => this.precheck(i.id),
104
+ summary: async (i) => {
105
+ const job = await this.label(i.id);
106
+ return {
107
+ zh: `丢弃无法排入队列的后台任务 ${job},它不会再运行`,
108
+ en: `Discard background work that could not be queued: ${job}; it will never run`,
109
+ };
110
+ },
111
+ run: async (input, ctx) => {
112
+ await this.dead.discard(input.id, { accountId: ctx.actorAccountId }, viaAgent("admin.outbox-discard", ctx));
113
+ return { id: input.id, discarded: true };
114
+ },
115
+ }),
116
+ ]);
117
+ }
118
+ };
119
+ OutboxOperations = __decorate([
120
+ Injectable(),
121
+ __param(0, Inject(PlatformOperations)),
122
+ __param(1, Inject(OutboxDeadService)),
123
+ __param(2, Inject(KernelDb))
124
+ ], OutboxOperations);
125
+ export { OutboxOperations };
@@ -148,7 +148,7 @@ let PlatformOperationsProvider = class PlatformOperationsProvider {
148
148
  const sandbox = toolKeys.some((k) => SANDBOX_TOOL_NAMES.includes(k));
149
149
  const org = await this.settings.get(ctx.orgId);
150
150
  // a new device's level: the org's default tier and its network
151
- const policy = this.settings.sandboxPolicy(org, null);
151
+ const policy = await this.settings.sandboxPolicy(org, null);
152
152
  return {
153
153
  id: agent.id,
154
154
  name: d.name,
@@ -10,7 +10,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
10
10
  import { Inject, Injectable } from "@nestjs/common";
11
11
  import { z } from "zod";
12
12
  import { ScheduledTasksService, } from "../../schedules/scheduled-tasks.service.js";
13
- import { createInputOf, grantsOf, ScheduleChatTargetsQuery, ScheduleCreateBody, ScheduleGrantableQuery, ScheduleGrantParams, ScheduleGrantsBody, ScheduleListQuery, ScheduleParams, ScheduleRunBody, ScheduleRunsQuery, ScheduleUpdateBody, updateInputOf, } from "../../schedules/schedules.schemas.js";
13
+ import { calendarInputOf, createInputOf, grantsOf, ScheduleCalendarQuery, ScheduleChatTargetsQuery, ScheduleCreateBody, ScheduleGrantableQuery, ScheduleGrantParams, ScheduleGrantsBody, ScheduleListQuery, ScheduleParams, ScheduleRunBody, ScheduleRunsQuery, ScheduleUpdateBody, updateInputOf, } from "../../schedules/schedules.schemas.js";
14
14
  import { defineOperation } from "../operation.js";
15
15
  import { PlatformOperations } from "../registry.js";
16
16
  import { named, orElse } from "./summary.js";
@@ -98,6 +98,45 @@ let SchedulesOperations = class SchedulesOperations {
98
98
  return { items: items.map(row) };
99
99
  },
100
100
  }),
101
+ defineOperation({
102
+ id: "schedules.calendar",
103
+ description: "Your scheduled task runs and planned occurrences between two instants (at most 43 days): recorded runs with their status, planned runs computed from each active task's schedule up to 42 days ahead, and dense tasks summarized per day. Org admins see every task with all=true. from and to are ISO instants with an offset; timeZone (IANA) sets the local days used to summarize dense tasks; taskId lists one task's items, never summarized (then at most 2 days). truncated means a limit cut the range at horizon.",
104
+ input: ScheduleCalendarQuery,
105
+ example: {
106
+ from: "2026-11-09T00:00:00+08:00",
107
+ to: "2026-11-16T00:00:00+08:00",
108
+ timeZone: "Asia/Shanghai",
109
+ },
110
+ authz: { orgAction: "org.read" },
111
+ mirrors: ["GET /api/v1/orgs/:orgId/schedules/calendar"],
112
+ confirm: "read",
113
+ errors: [
114
+ {
115
+ code: "validation_failed",
116
+ next: "Narrow the range to 43 days or less (2 days with taskId), with from before to.",
117
+ },
118
+ {
119
+ code: "forbidden",
120
+ next: "Reading every task needs the org admin role: call without all, or ask an org admin.",
121
+ },
122
+ {
123
+ code: "schedule.not_found",
124
+ next: "Check taskId with schedules.list: members see only their own tasks; an org admin finds another member's task id with schedules.list all=true, then reads it here by taskId (all is not needed).",
125
+ },
126
+ ],
127
+ run: async (input, ctx) => {
128
+ const answer = await this.tasks.calendar(ctx.orgId, this.actor(ctx), calendarInputOf(input));
129
+ return {
130
+ ...answer,
131
+ tasks: answer.tasks.map((t) => ({
132
+ id: t.id,
133
+ name: t.name,
134
+ agentId: t.agentId,
135
+ status: t.status,
136
+ })),
137
+ };
138
+ },
139
+ }),
101
140
  defineOperation({
102
141
  id: "schedules.chat-targets",
103
142
  description: "The IM chats you can point a chat-mode scheduled task at: your direct chats with each active channel connection's bot (one you have messaged before), and the groups you have talked in when the channel has threads. Each gives { connectionId, chatId, chatType } for schedules.create, and the connection's agentId, which the task must use.",
@@ -21,6 +21,7 @@ import { ModelsOperations } from "./ops/models.ops.js";
21
21
  import { OrgPluginsOperations } from "./ops/org-plugins.ops.js";
22
22
  import { OrgSettingsOperations } from "./ops/org-settings.ops.js";
23
23
  import { OrgsOperations } from "./ops/orgs.ops.js";
24
+ import { OutboxOperations } from "./ops/outbox.ops.js";
24
25
  import { PlatformOperationsProvider } from "./ops/platform.ops.js";
25
26
  import { PluginsOperations } from "./ops/plugins.ops.js";
26
27
  import { PreviewersOperations } from "./ops/previewers.ops.js";
@@ -34,7 +35,7 @@ import { UiOperations } from "./ops/ui.ops.js";
34
35
  * One provider per domain, each taking `PlatformOperations` as its first constructor argument:
35
36
  * the parity test in `tools/checks` builds the operations from it without a Nest app.
36
37
  */
37
- export declare const PLATFORM_OPERATION_PROVIDERS: readonly [typeof PlatformOperationsProvider, typeof SkillsOperations, typeof AgentsOperations, typeof AgentTemplatesOperations, typeof PluginsOperations, typeof MarketplacesOperations, typeof RequestsOperations, typeof ConnectorsOperations, typeof ExtensionsOperations, typeof ConversationsOperations, typeof ComponentsOperations, typeof AccountsOperations, typeof OrgsOperations, typeof AdminOperations, typeof CatalogAdminOperations, typeof OrgPluginsOperations, typeof ExtensionsAdminOperations, typeof ModelsOperations, typeof InboxOperations, typeof ApprovalsOperations, typeof ChannelsOperations, typeof OrgSettingsOperations, typeof EvalsOperations, typeof BackgroundOperations, typeof PreviewersOperations, typeof DevicesOperations, typeof AgentSkillsOperations, typeof ThemesOperations, typeof SetupOperations, typeof UiOperations, typeof AdminItemsOperations, typeof SchedulesOperations];
38
+ export declare const PLATFORM_OPERATION_PROVIDERS: readonly [typeof PlatformOperationsProvider, typeof SkillsOperations, typeof AgentsOperations, typeof AgentTemplatesOperations, typeof PluginsOperations, typeof MarketplacesOperations, typeof RequestsOperations, typeof ConnectorsOperations, typeof ExtensionsOperations, typeof ConversationsOperations, typeof ComponentsOperations, typeof AccountsOperations, typeof OrgsOperations, typeof AdminOperations, typeof CatalogAdminOperations, typeof OrgPluginsOperations, typeof ExtensionsAdminOperations, typeof ModelsOperations, typeof InboxOperations, typeof ApprovalsOperations, typeof ChannelsOperations, typeof OrgSettingsOperations, typeof EvalsOperations, typeof BackgroundOperations, typeof PreviewersOperations, typeof DevicesOperations, typeof AgentSkillsOperations, typeof ThemesOperations, typeof SetupOperations, typeof UiOperations, typeof AdminItemsOperations, typeof SchedulesOperations, typeof OutboxOperations];
38
39
  /**
39
40
  * The `Platform` tool's operations (ruling P2): one provider per domain, each registering its
40
41
  * operations into `PlatformOperations` from `onModuleInit`. It imports the domain modules, which
@@ -49,6 +49,7 @@ import { ModelsOperations } from "./ops/models.ops.js";
49
49
  import { OrgPluginsOperations } from "./ops/org-plugins.ops.js";
50
50
  import { OrgSettingsOperations } from "./ops/org-settings.ops.js";
51
51
  import { OrgsOperations } from "./ops/orgs.ops.js";
52
+ import { OutboxOperations } from "./ops/outbox.ops.js";
52
53
  import { PlatformOperationsProvider } from "./ops/platform.ops.js";
53
54
  import { PluginsOperations } from "./ops/plugins.ops.js";
54
55
  import { PreviewersOperations } from "./ops/previewers.ops.js";
@@ -107,6 +108,8 @@ export const PLATFORM_OPERATION_PROVIDERS = [
107
108
  AdminItemsOperations,
108
109
  // scheduled tasks (scheduled tasks spec §10)
109
110
  SchedulesOperations,
111
+ // dead outbox rows (transactional outbox spec §3.4)
112
+ OutboxOperations,
110
113
  ];
111
114
  /**
112
115
  * The `Platform` tool's operations (ruling P2): one provider per domain, each registering its