@capybara-hq/kernel 0.1.0-rc.2 → 0.1.0-rc.4
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.
- package/dist/admin/admin.controller.d.ts +9 -4
- package/dist/admin/admin.controller.js +13 -4
- package/dist/admin/extensions.controller.d.ts +8 -1
- package/dist/admin/extensions.controller.js +22 -2
- package/dist/agents/agent-lookup.d.ts +3 -0
- package/dist/agents/agent-lookup.js +20 -2
- package/dist/agents/agent-profile.service.d.ts +29 -0
- package/dist/agents/agent-profile.service.js +117 -0
- package/dist/agents/agents.controller.d.ts +93 -3
- package/dist/agents/agents.controller.js +114 -4
- package/dist/agents/agents.module.js +6 -2
- package/dist/agents/agents.service.d.ts +13 -5
- package/dist/agents/agents.service.js +49 -13
- package/dist/agents/definition.d.ts +35 -8
- package/dist/agents/definition.js +203 -17
- package/dist/agents/instruction-files.d.ts +60 -0
- package/dist/agents/instruction-files.js +111 -0
- package/dist/agents/models.controller.d.ts +9 -3
- package/dist/agents/models.controller.js +19 -4
- package/dist/agents/profile.d.ts +96 -0
- package/dist/agents/profile.js +51 -0
- package/dist/agents/readiness.controller.d.ts +26 -0
- package/dist/agents/readiness.controller.js +56 -0
- package/dist/agents/templates.js +20 -5
- package/dist/background/background.controller.d.ts +38 -0
- package/dist/background/background.controller.js +87 -0
- package/dist/background/background.module.d.ts +10 -0
- package/dist/background/background.module.js +32 -0
- package/dist/background/finish.d.ts +43 -0
- package/dist/background/finish.js +94 -0
- package/dist/background/launch-lock.d.ts +14 -0
- package/dist/background/launch-lock.js +39 -0
- package/dist/background/launch.d.ts +36 -0
- package/dist/background/launch.js +70 -0
- package/dist/background/poll.job.d.ts +53 -0
- package/dist/background/poll.job.js +182 -0
- package/dist/background/render.d.ts +23 -0
- package/dist/background/render.js +48 -0
- package/dist/background/session.d.ts +37 -0
- package/dist/background/session.js +66 -0
- package/dist/background/status.d.ts +35 -0
- package/dist/background/status.js +57 -0
- package/dist/background/stop.d.ts +62 -0
- package/dist/background/stop.js +225 -0
- package/dist/background/store.d.ts +150 -0
- package/dist/background/store.js +351 -0
- package/dist/background/store.module.d.ts +6 -0
- package/dist/background/store.module.js +22 -0
- package/dist/background/tasks.service.d.ts +67 -0
- package/dist/background/tasks.service.js +186 -0
- package/dist/background/wake-rules.d.ts +57 -0
- package/dist/background/wake-rules.js +83 -0
- package/dist/background/wake.d.ts +28 -0
- package/dist/background/wake.js +57 -0
- package/dist/catalog/catalog-content.js +4 -1
- package/dist/catalog/claude/agents.js +15 -10
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/plugin-import.js +1 -1
- package/dist/catalog/plugin-upgrade.js +1 -1
- package/dist/channels/cards.d.ts +8 -2
- package/dist/channels/cards.js +17 -9
- package/dist/channels/connections.service.d.ts +16 -1
- package/dist/channels/connections.service.js +38 -4
- package/dist/channels/threads.d.ts +5 -0
- package/dist/channels/threads.js +8 -0
- package/dist/config/schema.d.ts +18 -0
- package/dist/config/schema.js +104 -2
- package/dist/conversations/access.js +2 -0
- package/dist/conversations/artifacts.d.ts +1 -1
- package/dist/conversations/artifacts.js +1 -1
- package/dist/conversations/attachments.service.d.ts +30 -0
- package/dist/conversations/attachments.service.js +130 -5
- package/dist/conversations/conversations.controller.d.ts +36 -5
- package/dist/conversations/conversations.controller.js +62 -12
- package/dist/conversations/conversations.module.js +3 -0
- package/dist/conversations/conversations.service.d.ts +44 -2
- package/dist/conversations/conversations.service.js +140 -12
- package/dist/conversations/event-log.d.ts +12 -1
- package/dist/conversations/event-log.js +29 -1
- package/dist/conversations/events.d.ts +81 -3
- package/dist/conversations/events.js +83 -16
- package/dist/conversations/queue.d.ts +3 -1
- package/dist/conversations/queue.js +13 -2
- package/dist/conversations/queue.service.js +3 -1
- package/dist/conversations/titles.d.ts +7 -0
- package/dist/conversations/titles.js +15 -0
- package/dist/db/kernel-schema.d.ts +60 -4
- package/dist/db/pool.d.ts +5 -0
- package/dist/db/pool.js +3 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +8 -0
- package/dist/evals/recorded-tools.d.ts +27 -1
- package/dist/evals/recorded-tools.js +85 -10
- package/dist/evals/run-replay.d.ts +10 -2
- package/dist/evals/run-replay.js +49 -12
- package/dist/evals/step-replay.js +12 -6
- package/dist/evals/trajectory.d.ts +2 -2
- package/dist/evals/trajectory.js +1 -1
- package/dist/extensions/admin-ops.js +2 -0
- package/dist/extensions/admin-view.d.ts +3 -1
- package/dist/extensions/admin-view.js +10 -2
- package/dist/extensions/blobs.js +1 -0
- package/dist/extensions/config-issues.d.ts +13 -1
- package/dist/extensions/config-issues.js +22 -5
- package/dist/extensions/config-json-schema.d.ts +43 -7
- package/dist/extensions/config-json-schema.js +124 -58
- package/dist/extensions/deployment-config-store.d.ts +6 -0
- package/dist/extensions/deployment-config.d.ts +50 -3
- package/dist/extensions/deployment-config.js +125 -28
- package/dist/extensions/display-name.d.ts +22 -0
- package/dist/extensions/display-name.js +77 -0
- package/dist/extensions/extensions.module.js +6 -0
- package/dist/extensions/host.d.ts +26 -1
- package/dist/extensions/host.js +82 -9
- package/dist/extensions/org-config.controller.d.ts +11 -3
- package/dist/extensions/org-config.controller.js +14 -6
- package/dist/extensions/org-config.d.ts +6 -0
- package/dist/extensions/org-config.js +12 -13
- package/dist/extensions/package.d.ts +14 -1
- package/dist/extensions/package.js +51 -2
- package/dist/extensions/permission-view.d.ts +3 -0
- package/dist/extensions/point-defaults.controller.d.ts +34 -0
- package/dist/extensions/point-defaults.controller.js +71 -0
- package/dist/extensions/point-defaults.d.ts +64 -0
- package/dist/extensions/point-defaults.js +206 -0
- package/dist/extensions/registry.d.ts +1 -1
- package/dist/extensions/registry.js +2 -0
- package/dist/http/api.module.js +8 -0
- package/dist/http/nest-logger.d.ts +6 -5
- package/dist/http/nest-logger.js +24 -10
- package/dist/identity/auth.controller.js +9 -5
- package/dist/identity/cookies.d.ts +20 -5
- package/dist/identity/cookies.js +44 -6
- package/dist/identity/me.controller.d.ts +5 -1
- package/dist/identity/me.controller.js +12 -3
- package/dist/identity/sessions.d.ts +12 -0
- package/dist/identity/sessions.js +45 -0
- package/dist/identity/settings.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/infra/config/kernel-config.service.js +6 -0
- package/dist/infra/database/database.module.js +1 -0
- package/dist/infra/events/kernel-events.d.ts +8 -0
- package/dist/infra/lifecycle/process-guards.js +4 -0
- package/dist/infra/logging/logging.module.d.ts +4 -2
- package/dist/infra/logging/logging.module.js +24 -6
- package/dist/infra/queue/redis-connection.d.ts +6 -0
- package/dist/infra/queue/redis-connection.js +7 -0
- package/dist/infra/redis/redis.module.js +6 -2
- package/dist/infra/tokens.d.ts +6 -1
- package/dist/infra/tokens.js +6 -1
- package/dist/lifecycle/kernel-lifecycle.js +5 -0
- package/dist/log.d.ts +13 -1
- package/dist/log.js +93 -17
- package/dist/models/purposes.d.ts +23 -0
- package/dist/models/purposes.js +31 -10
- package/dist/orgs/offboarding.d.ts +3 -1
- package/dist/orgs/offboarding.js +26 -16
- package/dist/orgs/settings.service.d.ts +7 -2
- package/dist/orgs/settings.service.js +15 -4
- package/dist/roles/worker.module.js +6 -0
- package/dist/runtime/context/build.d.ts +15 -13
- package/dist/runtime/context/build.js +45 -27
- package/dist/runtime/context/claude-tools.d.ts +3 -1
- package/dist/runtime/context/claude-tools.js +12 -12
- package/dist/runtime/context/compaction.js +4 -0
- package/dist/runtime/context/legacy-text.d.ts +22 -0
- package/dist/runtime/context/legacy-text.js +37 -0
- package/dist/runtime/context/skills.d.ts +29 -11
- package/dist/runtime/context/skills.js +37 -30
- package/dist/runtime/langgraph-loop.js +3 -2
- package/dist/runtime/loop.d.ts +5 -4
- package/dist/runtime/maintenance.d.ts +4 -2
- package/dist/runtime/maintenance.js +17 -5
- package/dist/runtime/model-call.d.ts +17 -1
- package/dist/runtime/model-call.js +4 -3
- package/dist/runtime/providers.d.ts +6 -0
- package/dist/runtime/providers.js +8 -0
- package/dist/runtime/run-finish.d.ts +1 -1
- package/dist/runtime/run-queue.d.ts +28 -5
- package/dist/runtime/run-queue.js +131 -35
- package/dist/runtime/run-worker.d.ts +2 -2
- package/dist/runtime/run-worker.js +20 -7
- package/dist/runtime/runtime.module.js +8 -3
- package/dist/runtime/step-log.d.ts +6 -0
- package/dist/runtime/step-log.js +16 -2
- package/dist/runtime/subagents/definition.d.ts +1 -6
- package/dist/runtime/subagents/definition.js +14 -13
- package/dist/runtime/subagents/dispatch.d.ts +2 -2
- package/dist/runtime/subagents/dispatch.js +2 -2
- package/dist/runtime/subagents/org-agents.js +2 -1
- package/dist/runtime/subagents/roster.d.ts +1 -1
- package/dist/runtime/subagents/roster.js +1 -1
- package/dist/runtime/subagents/skill-fork.d.ts +2 -2
- package/dist/runtime/subagents/skill-fork.js +2 -2
- package/dist/runtime/subagents/subagents.service.d.ts +3 -3
- package/dist/runtime/subagents/subagents.service.js +3 -3
- package/dist/runtime/usage-report.d.ts +2 -1
- package/dist/runtime/usage-report.js +2 -1
- package/dist/runtime/waits.d.ts +13 -7
- package/dist/runtime/waits.js +42 -16
- package/dist/sandbox/sandbox.module.js +6 -1
- package/dist/sandbox/sandbox.service.d.ts +61 -3
- package/dist/sandbox/sandbox.service.js +141 -7
- package/dist/skills/catalog.d.ts +4 -4
- package/dist/skills/catalog.js +4 -4
- package/dist/skills/changes.service.d.ts +2 -2
- package/dist/skills/changes.service.js +5 -4
- package/dist/skills/invocation-keys.d.ts +1 -1
- package/dist/skills/invocation-keys.js +1 -1
- package/dist/skills/invoke.d.ts +1 -1
- package/dist/skills/invoke.js +5 -4
- package/dist/tools/approvals.service.d.ts +6 -0
- package/dist/tools/approvals.service.js +21 -1
- package/dist/tools/builtin-names.d.ts +91 -0
- package/dist/tools/builtin-names.js +143 -0
- package/dist/tools/builtins/agent.d.ts +7 -7
- package/dist/tools/builtins/agent.js +7 -11
- package/dist/tools/builtins/ask-user.d.ts +1 -1
- package/dist/tools/builtins/ask-user.js +2 -2
- package/dist/tools/builtins/builtin-tools.d.ts +17 -3
- package/dist/tools/builtins/builtin-tools.js +36 -4
- package/dist/tools/builtins/read-tool-output.d.ts +1 -1
- package/dist/tools/builtins/read-tool-output.js +2 -2
- package/dist/tools/builtins/sandbox/bash.d.ts +4 -4
- package/dist/tools/builtins/sandbox/bash.js +259 -29
- package/dist/tools/builtins/sandbox/common.d.ts +30 -7
- package/dist/tools/builtins/sandbox/common.js +9 -5
- package/dist/tools/builtins/sandbox/deliver.d.ts +1 -1
- package/dist/tools/builtins/sandbox/deliver.js +12 -12
- package/dist/tools/builtins/sandbox/edit.d.ts +1 -1
- package/dist/tools/builtins/sandbox/edit.js +41 -30
- package/dist/tools/builtins/sandbox/file-state.d.ts +34 -0
- package/dist/tools/builtins/sandbox/file-state.js +34 -0
- package/dist/tools/builtins/sandbox/glob-match.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob-match.js +1 -1
- package/dist/tools/builtins/sandbox/glob.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob.js +4 -4
- package/dist/tools/builtins/sandbox/grep.d.ts +7 -4
- package/dist/tools/builtins/sandbox/grep.js +147 -30
- package/dist/tools/builtins/sandbox/index.d.ts +3 -1
- package/dist/tools/builtins/sandbox/index.js +7 -1
- package/dist/tools/builtins/sandbox/read.d.ts +2 -2
- package/dist/tools/builtins/sandbox/read.js +21 -14
- package/dist/tools/builtins/sandbox/task-output.d.ts +63 -0
- package/dist/tools/builtins/sandbox/task-output.js +304 -0
- package/dist/tools/builtins/sandbox/task-stop.d.ts +10 -0
- package/dist/tools/builtins/sandbox/task-stop.js +112 -0
- package/dist/tools/builtins/sandbox/write.d.ts +1 -1
- package/dist/tools/builtins/sandbox/write.js +37 -33
- package/dist/tools/builtins/skill-load.d.ts +3 -3
- package/dist/tools/builtins/skill-load.js +32 -16
- package/dist/tools/builtins/skill-write.d.ts +4 -4
- package/dist/tools/builtins/skill-write.js +10 -10
- package/dist/tools/builtins/tool-search.d.ts +13 -9
- package/dist/tools/builtins/tool-search.js +25 -14
- package/dist/tools/builtins/web/errors.d.ts +8 -0
- package/dist/tools/builtins/web/errors.js +53 -0
- package/dist/tools/builtins/web/extract.d.ts +62 -0
- package/dist/tools/builtins/web/extract.js +267 -0
- package/dist/tools/builtins/web/fetch.d.ts +55 -0
- package/dist/tools/builtins/web/fetch.js +174 -0
- package/dist/tools/builtins/web/index.d.ts +13 -0
- package/dist/tools/builtins/web/index.js +12 -0
- package/dist/tools/builtins/web/page-cache.d.ts +25 -0
- package/dist/tools/builtins/web/page-cache.js +77 -0
- package/dist/tools/builtins/web/search.d.ts +25 -0
- package/dist/tools/builtins/web/search.js +209 -0
- package/dist/tools/builtins/web/url.d.ts +17 -0
- package/dist/tools/builtins/web/url.js +43 -0
- package/dist/tools/connectors.service.js +4 -4
- package/dist/tools/display-names.d.ts +9 -0
- package/dist/tools/display-names.js +24 -0
- package/dist/tools/drift.js +5 -5
- package/dist/tools/elicitation.js +1 -1
- package/dist/tools/info.d.ts +20 -4
- package/dist/tools/info.js +55 -32
- package/dist/tools/legacy-data.d.ts +34 -0
- package/dist/tools/legacy-data.js +76 -0
- package/dist/tools/legacy-keys.d.ts +51 -0
- package/dist/tools/legacy-keys.js +115 -0
- package/dist/tools/naming.d.ts +1 -5
- package/dist/tools/naming.js +1 -7
- package/dist/tools/oauth/flow-paths.d.ts +1 -1
- package/dist/tools/oauth/flow-paths.js +1 -1
- package/dist/tools/outputs.js +1 -1
- package/dist/tools/pipeline.d.ts +13 -7
- package/dist/tools/pipeline.js +112 -39
- package/dist/tools/policy.d.ts +1 -14
- package/dist/tools/policy.js +13 -19
- package/dist/tools/questions.controller.d.ts +1 -1
- package/dist/tools/questions.controller.js +1 -1
- package/dist/tools/questions.service.d.ts +1 -1
- package/dist/tools/registry.d.ts +38 -24
- package/dist/tools/registry.js +54 -47
- package/dist/tools/resources.d.ts +1 -1
- package/dist/tools/resources.js +1 -1
- package/dist/tools/tools.module.js +13 -1
- package/dist/tools/validate.js +1 -1
- package/package.json +3 -3
- package/src/migrations/0063_tool_keys_claude_code.sql +220 -0
- package/src/migrations/0064_account_last_org.sql +7 -0
- package/src/migrations/0065_conversation_archive.sql +8 -0
- package/src/migrations/0066_extension_display_name.sql +4 -0
- package/src/migrations/0067_agent_profiles.sql +20 -0
- package/src/migrations/0068_agent_avatar_uploads.sql +7 -0
- package/src/migrations/0069_attachments_agent_idx.sql +3 -0
- package/src/migrations/0070_background_tasks.sql +37 -0
- package/src/migrations/0071_background_tasks_reserve.sql +6 -0
- package/src/migrations/0072_background_tasks_stopping.sql +5 -0
- package/src/migrations/0073_org_extension_point_defaults.sql +11 -0
- package/dist/tools/builtins/sandbox/names.d.ts +0 -7
- package/dist/tools/builtins/sandbox/names.js +0 -20
|
@@ -22,8 +22,9 @@ import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
|
22
22
|
import { KERNEL_BUS, KERNEL_LOGGER, KEYRING } from "../infra/tokens.js";
|
|
23
23
|
import { KERNEL_APP_OPTIONS } from "../lifecycle/tokens.js";
|
|
24
24
|
import { toIssues } from "./config-issues.js";
|
|
25
|
-
import {
|
|
26
|
-
import { DEPLOYMENT_SECRETS_ORG, deleteDeep, mergeDeploymentConfig, readStoredDeploymentConfig, SECRETS_NAMESPACE, schemaFields, secretKey, secretPathsOf, setDeep, } from "./deployment-config-store.js";
|
|
25
|
+
import { checkConfigUi, configMessages, hintedSecretPaths, safeConfigFormSchema, } from "./config-json-schema.js";
|
|
26
|
+
import { DEPLOYMENT_SECRETS_ORG, deleteDeep, isObj, mergeDeploymentConfig, readStoredDeploymentConfig, SECRETS_NAMESPACE, schemaFields, secretKey, secretPathsOf, setDeep, } from "./deployment-config-store.js";
|
|
27
|
+
import { ExtensionDisplayNames } from "./display-name.js";
|
|
27
28
|
import { ExtensionHost } from "./host.js";
|
|
28
29
|
import { ExtensionInstalls } from "./installs.js";
|
|
29
30
|
import { ExtensionLifecycle } from "./lifecycle.js";
|
|
@@ -31,16 +32,6 @@ import { PLUGIN_DEPLOYMENT_CONFIG_TOPIC } from "./lifecycle-topics.js";
|
|
|
31
32
|
import { PluginDeploymentConfigLock } from "./locks.js";
|
|
32
33
|
export { DEPLOYMENT_SECRETS_ORG, mergeDeploymentConfig, readStoredDeploymentConfig, schemaFields, secretPathsOf, };
|
|
33
34
|
export { PLUGIN_DEPLOYMENT_CONFIG_TOPIC };
|
|
34
|
-
/** JSON Schema 转换按 schema 对象缓存(清单不可变)。 */
|
|
35
|
-
const jsonSchemaCache = new WeakMap();
|
|
36
|
-
function jsonSchemaOf(schema) {
|
|
37
|
-
let js = jsonSchemaCache.get(schema);
|
|
38
|
-
if (!js) {
|
|
39
|
-
js = configToJsonSchema(schema);
|
|
40
|
-
jsonSchemaCache.set(schema, js);
|
|
41
|
-
}
|
|
42
|
-
return structuredClone(js);
|
|
43
|
-
}
|
|
44
35
|
/** 某字段 zod 叶子上的默认值(整份配置不合法、校验没能补上默认值时,视图仍按它显示)。 */
|
|
45
36
|
function defaultOf(schema, path) {
|
|
46
37
|
const f = configFields(schema).find((x) => x.path === path);
|
|
@@ -69,6 +60,7 @@ let ExtensionDeploymentConfigService = class ExtensionDeploymentConfigService {
|
|
|
69
60
|
lifecycle;
|
|
70
61
|
bus;
|
|
71
62
|
log;
|
|
63
|
+
displayNames;
|
|
72
64
|
/** Where each startup-config field comes from (see `extensionConfigSources`); those fields are read-only. */
|
|
73
65
|
sources;
|
|
74
66
|
constructor(kdb, txHost,
|
|
@@ -81,7 +73,7 @@ let ExtensionDeploymentConfigService = class ExtensionDeploymentConfigService {
|
|
|
81
73
|
/** Applies a saved config on this replica at once (other replicas through the bus). */
|
|
82
74
|
lifecycle,
|
|
83
75
|
/** Publishes {@link PLUGIN_DEPLOYMENT_CONFIG_TOPIC} after a save (a failure only warns). */
|
|
84
|
-
bus, log, options) {
|
|
76
|
+
bus, log, options, displayNames) {
|
|
85
77
|
this.kdb = kdb;
|
|
86
78
|
this.txHost = txHost;
|
|
87
79
|
this.adminLock = adminLock;
|
|
@@ -93,6 +85,7 @@ let ExtensionDeploymentConfigService = class ExtensionDeploymentConfigService {
|
|
|
93
85
|
this.lifecycle = lifecycle;
|
|
94
86
|
this.bus = bus;
|
|
95
87
|
this.log = log;
|
|
88
|
+
this.displayNames = displayNames;
|
|
96
89
|
const env = options.env ?? process.env;
|
|
97
90
|
this.sources =
|
|
98
91
|
options.extensionConfigSources ??
|
|
@@ -125,8 +118,11 @@ let ExtensionDeploymentConfigService = class ExtensionDeploymentConfigService {
|
|
|
125
118
|
/** Admin view; an extension unknown to the deployment -> `extension.not_found`. */
|
|
126
119
|
async view(plugin) {
|
|
127
120
|
const info = await this.info(plugin);
|
|
128
|
-
const stored = await
|
|
129
|
-
|
|
121
|
+
const [stored, displayName] = await Promise.all([
|
|
122
|
+
this.readStored(plugin, info),
|
|
123
|
+
this.displayNames.get(plugin),
|
|
124
|
+
]);
|
|
125
|
+
return this.render(plugin, info, stored, displayName);
|
|
130
126
|
}
|
|
131
127
|
/** `REPEATABLE READ` read-only: every stored field from one snapshot. */
|
|
132
128
|
readStored(plugin, info) {
|
|
@@ -141,12 +137,17 @@ let ExtensionDeploymentConfigService = class ExtensionDeploymentConfigService {
|
|
|
141
137
|
* invalid after merging (except a problem in a read-only startup-config field itself) ->
|
|
142
138
|
* `extension.config_invalid` (details carry only paths and messages);
|
|
143
139
|
* - a field present in the startup config (file / Nacos / env) -> 409 `extension.config_readonly`.
|
|
140
|
+
* `secretEntries` change single keys of secret records some `x-ui.secrets[].path` names
|
|
141
|
+
* ({@link SecretEntry}; spec §4.3): applied under the same locks to the decrypted record, which
|
|
142
|
+
* is re-encrypted whole, then validated with `values`; the audit lists the record's path, no keys.
|
|
143
|
+
* A path no hint names -> 400 `validation_failed`; one in the startup config -> 409
|
|
144
|
+
* `extension.config_readonly`.
|
|
144
145
|
* In a transaction, first `lockEnterpriseAdminsAndAuthorize` (re-checks the enterprise admin under
|
|
145
146
|
* the lock), then an advisory lock per extension; audit `extension.deployment_config_updated`
|
|
146
147
|
* (detail only `changedPaths`). After the commit publishes {@link PLUGIN_DEPLOYMENT_CONFIG_TOPIC} and
|
|
147
148
|
* applies it on this replica right away.
|
|
148
149
|
*/
|
|
149
|
-
async put(plugin, values, actor, actorTokenId) {
|
|
150
|
+
async put(plugin, values, actor, actorTokenId, secretEntries = []) {
|
|
150
151
|
const info = await this.info(plugin);
|
|
151
152
|
if (info.fields.length === 0) {
|
|
152
153
|
throw new ApiError("extension.config_invalid", `Extension ${plugin} has no deployment config`);
|
|
@@ -156,14 +157,16 @@ let ExtensionDeploymentConfigService = class ExtensionDeploymentConfigService {
|
|
|
156
157
|
if (unknown.length > 0) {
|
|
157
158
|
throw new ApiError("extension.config_invalid", `Unknown deployment config fields for extension ${plugin}`, unknown.map((path) => ({ path, message: "unknown field" })));
|
|
158
159
|
}
|
|
160
|
+
this.checkSecretEntries(plugin, info, values, secretEntries);
|
|
159
161
|
const sources = this.sources[plugin];
|
|
160
|
-
const
|
|
162
|
+
const entryPaths = [...new Set(secretEntries.map((e) => e.path))];
|
|
163
|
+
const readonly = [...Object.keys(values), ...entryPaths].filter((p) => fieldSource(sources, p) !== undefined);
|
|
161
164
|
if (readonly.length > 0) {
|
|
162
165
|
throw new ApiError("extension.config_readonly", `These deployment config fields of extension ${plugin} are set in the startup config (file, Nacos or environment) and are read-only here: ${readonly.join(", ")}`, readonly.map((path) => ({ path, source: fieldSource(sources, path) })));
|
|
163
166
|
}
|
|
164
167
|
const fileValue = this.fileConfig()[plugin];
|
|
165
168
|
const fieldPaths = info.fields.map((f) => f.path);
|
|
166
|
-
const { saved, changed } = await this.write(plugin, values, actor, actorTokenId, info, sources, fileValue);
|
|
169
|
+
const { saved, changed } = await this.write(plugin, values, secretEntries, actor, actorTokenId, info, sources, fileValue);
|
|
167
170
|
const stored = saved ?? {};
|
|
168
171
|
if (info.schema) {
|
|
169
172
|
const secrets = secretValues(info.schema, mergeDeploymentConfig(stored, fileValue, fieldPaths));
|
|
@@ -187,9 +190,38 @@ let ExtensionDeploymentConfigService = class ExtensionDeploymentConfigService {
|
|
|
187
190
|
});
|
|
188
191
|
}
|
|
189
192
|
}
|
|
190
|
-
return this.render(plugin, info, stored);
|
|
193
|
+
return this.render(plugin, info, stored, await this.displayNames.get(plugin));
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Secret entries name a secret record field some hint names (else 400 `validation_failed`, also
|
|
197
|
+
* for a path given in `values` too, an entry with neither `value` nor `renameFrom`, or a key
|
|
198
|
+
* `__proto__`). Messages carry paths and keys only, never values.
|
|
199
|
+
*/
|
|
200
|
+
checkSecretEntries(plugin, info, values, entries) {
|
|
201
|
+
if (entries.length === 0)
|
|
202
|
+
return;
|
|
203
|
+
const hinted = this.hintedPaths(plugin, info);
|
|
204
|
+
const secret = new Set(secretPathsOf(info.fields));
|
|
205
|
+
const problems = [];
|
|
206
|
+
for (const e of entries) {
|
|
207
|
+
if (!hinted.has(e.path) || !secret.has(e.path)) {
|
|
208
|
+
problems.push({ path: e.path, message: "no config UI hint draws this secret per item" });
|
|
209
|
+
}
|
|
210
|
+
else if (Object.hasOwn(values, e.path)) {
|
|
211
|
+
problems.push({ path: e.path, message: "given both in values and in secretEntries" });
|
|
212
|
+
}
|
|
213
|
+
else if (e.value === undefined && e.renameFrom === undefined) {
|
|
214
|
+
problems.push({ path: e.path, message: `entry ${e.key} has neither value nor renameFrom` });
|
|
215
|
+
}
|
|
216
|
+
else if (e.key === "__proto__" || e.renameFrom === "__proto__") {
|
|
217
|
+
problems.push({ path: e.path, message: "__proto__ is not a valid key" });
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (problems.length > 0) {
|
|
221
|
+
throw new ApiError("validation_failed", `Invalid secret entries for the deployment config of extension ${plugin}`, problems);
|
|
222
|
+
}
|
|
191
223
|
}
|
|
192
|
-
async write(plugin, values, actor, actorTokenId, info, sources, fileValue) {
|
|
224
|
+
async write(plugin, values, secretEntries, actor, actorTokenId, info, sources, fileValue) {
|
|
193
225
|
const fieldPaths = info.fields.map((f) => f.path);
|
|
194
226
|
let changed = [];
|
|
195
227
|
const t = this.db;
|
|
@@ -206,17 +238,19 @@ let ExtensionDeploymentConfigService = class ExtensionDeploymentConfigService {
|
|
|
206
238
|
else
|
|
207
239
|
setDeep(next, path, structuredClone(v));
|
|
208
240
|
}
|
|
241
|
+
applySecretEntries(next, secretEntries);
|
|
242
|
+
const touched = new Set([...Object.keys(values), ...secretEntries.map((e) => e.path)]);
|
|
209
243
|
if (info.schema) {
|
|
210
244
|
const r = info.schema.safeParse(mergeDeploymentConfig(next, fileValue, fieldPaths));
|
|
211
245
|
if (!r.success) {
|
|
212
246
|
// 启动配置里只读字段自己的问题这里改不了(照样保存,插件保持待配置),其余拒绝
|
|
213
|
-
const issues = toIssues(r.error).filter((i) => i.path === "" || fieldSource(sources, i.path) === undefined);
|
|
247
|
+
const issues = toIssues(r.error, this.messagesOf(plugin, info)).filter((i) => i.path === "" || fieldSource(sources, i.path) === undefined);
|
|
214
248
|
if (issues.length > 0) {
|
|
215
249
|
throw new ApiError("extension.config_invalid", `Invalid deployment config for extension ${plugin}`, issues);
|
|
216
250
|
}
|
|
217
251
|
}
|
|
218
252
|
}
|
|
219
|
-
changed =
|
|
253
|
+
changed = [...touched]
|
|
220
254
|
.filter((p) => !isDeepStrictEqual(getPath(before, p), getPath(next, p)))
|
|
221
255
|
.sort();
|
|
222
256
|
const saved = next;
|
|
@@ -228,7 +262,7 @@ let ExtensionDeploymentConfigService = class ExtensionDeploymentConfigService {
|
|
|
228
262
|
if (!f.secret)
|
|
229
263
|
continue;
|
|
230
264
|
deleteDeep(plain, f.path);
|
|
231
|
-
if (!(f.path
|
|
265
|
+
if (!touched.has(f.path))
|
|
232
266
|
continue;
|
|
233
267
|
const v = getPath(next, f.path);
|
|
234
268
|
if (v === undefined)
|
|
@@ -261,7 +295,7 @@ let ExtensionDeploymentConfigService = class ExtensionDeploymentConfigService {
|
|
|
261
295
|
}
|
|
262
296
|
return info;
|
|
263
297
|
}
|
|
264
|
-
render(plugin, info, stored) {
|
|
298
|
+
render(plugin, info, stored, displayName) {
|
|
265
299
|
const fileValue = this.fileConfig()[plugin];
|
|
266
300
|
const sources = this.sources[plugin];
|
|
267
301
|
const raw = mergeDeploymentConfig(stored, fileValue, info.fields.map((f) => f.path));
|
|
@@ -274,9 +308,11 @@ let ExtensionDeploymentConfigService = class ExtensionDeploymentConfigService {
|
|
|
274
308
|
effective = r.data;
|
|
275
309
|
else {
|
|
276
310
|
valid = false;
|
|
277
|
-
issues = toIssues(r.error);
|
|
311
|
+
issues = toIssues(r.error, this.messagesOf(plugin, info));
|
|
278
312
|
}
|
|
279
313
|
}
|
|
314
|
+
const formSchema = this.formSchemaOf(plugin, info);
|
|
315
|
+
const hinted = formSchema ? hintedSecretPaths(formSchema) : new Set();
|
|
280
316
|
const fields = info.fields.map((f) => {
|
|
281
317
|
const from = fieldSource(sources, f.path);
|
|
282
318
|
let value = getPath(effective, f.path);
|
|
@@ -298,21 +334,48 @@ let ExtensionDeploymentConfigService = class ExtensionDeploymentConfigService {
|
|
|
298
334
|
source,
|
|
299
335
|
readonly: from !== undefined,
|
|
300
336
|
};
|
|
337
|
+
// a schema default (e.g. `secret(record).default({})`) is no secret anybody set
|
|
338
|
+
const set = value !== undefined && source !== "default";
|
|
339
|
+
if (f.secret && hinted.has(f.path)) {
|
|
340
|
+
// record keys are item names, never values
|
|
341
|
+
return { ...base, set, keys: set && isObj(value) ? Object.keys(value).sort() : [] };
|
|
342
|
+
}
|
|
301
343
|
if (f.secret)
|
|
302
|
-
return { ...base, set
|
|
344
|
+
return { ...base, set };
|
|
303
345
|
return value === undefined ? base : { ...base, value: structuredClone(value) };
|
|
304
346
|
});
|
|
305
347
|
return {
|
|
306
348
|
plugin,
|
|
349
|
+
displayName,
|
|
307
350
|
version: info.version,
|
|
308
351
|
configurable: info.fields.length > 0,
|
|
309
352
|
fields,
|
|
310
|
-
schema:
|
|
353
|
+
schema: structuredClone(formSchema ?? null),
|
|
311
354
|
valid,
|
|
312
355
|
validated: info.schema !== undefined,
|
|
313
356
|
issues,
|
|
314
357
|
};
|
|
315
358
|
}
|
|
359
|
+
/**
|
|
360
|
+
* The form JSON Schema of the description: the zod schema's, else the package's static one. A
|
|
361
|
+
* hint conversion that throws (a hand-made package) drops the hints: the plain schema, or none
|
|
362
|
+
* when even the conversion fails; one warning per schema. Never throws.
|
|
363
|
+
*/
|
|
364
|
+
formSchemaOf(plugin, info) {
|
|
365
|
+
if (!info.schema)
|
|
366
|
+
return info.jsonSchema;
|
|
367
|
+
const r = safeConfigFormSchema(info.schema, "deployment", (err, schema) => this.log.warn("the deployment config form schema could not be built with its UI hints; hints dropped", { plugin, version: info.version, schema, err }));
|
|
368
|
+
return r?.schema;
|
|
369
|
+
}
|
|
370
|
+
messagesOf(plugin, info) {
|
|
371
|
+
const js = this.formSchemaOf(plugin, info);
|
|
372
|
+
return js && configMessages(js);
|
|
373
|
+
}
|
|
374
|
+
/** The secret record paths some hint of the form schema names. */
|
|
375
|
+
hintedPaths(plugin, info) {
|
|
376
|
+
const js = this.formSchemaOf(plugin, info);
|
|
377
|
+
return js ? hintedSecretPaths(js) : new Set();
|
|
378
|
+
}
|
|
316
379
|
};
|
|
317
380
|
__decorate([
|
|
318
381
|
Transactional({
|
|
@@ -337,11 +400,38 @@ ExtensionDeploymentConfigService = __decorate([
|
|
|
337
400
|
__param(8, Inject(ExtensionLifecycle)),
|
|
338
401
|
__param(9, Inject(KERNEL_BUS)),
|
|
339
402
|
__param(10, Inject(KERNEL_LOGGER)),
|
|
340
|
-
__param(11, Inject(KERNEL_APP_OPTIONS))
|
|
403
|
+
__param(11, Inject(KERNEL_APP_OPTIONS)),
|
|
404
|
+
__param(12, Inject(ExtensionDisplayNames))
|
|
341
405
|
], ExtensionDeploymentConfigService);
|
|
342
406
|
export { ExtensionDeploymentConfigService };
|
|
407
|
+
/**
|
|
408
|
+
* Applies secret entries in order to the decrypted config `next` (in place): each record is read
|
|
409
|
+
* from `next` at its path, renamed, set or removed, and put back; an empty record is removed (the
|
|
410
|
+
* field falls back to its default).
|
|
411
|
+
*/
|
|
412
|
+
function applySecretEntries(next, entries) {
|
|
413
|
+
for (const e of entries) {
|
|
414
|
+
const cur = getPath(next, e.path);
|
|
415
|
+
const rec = isObj(cur) ? { ...cur } : {};
|
|
416
|
+
if (e.renameFrom !== undefined && e.renameFrom !== e.key && Object.hasOwn(rec, e.renameFrom)) {
|
|
417
|
+
rec[e.key] = rec[e.renameFrom];
|
|
418
|
+
delete rec[e.renameFrom];
|
|
419
|
+
}
|
|
420
|
+
if (e.value === null)
|
|
421
|
+
delete rec[e.key];
|
|
422
|
+
else if (e.value !== undefined)
|
|
423
|
+
rec[e.key] = e.value;
|
|
424
|
+
if (Object.keys(rec).length === 0)
|
|
425
|
+
deleteDeep(next, e.path);
|
|
426
|
+
else
|
|
427
|
+
setDeep(next, e.path, rec);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
343
430
|
/**
|
|
344
431
|
* 本副本拿不到模块时(未加载的安装记录)按包内审阅过的静态清单给出字段(没有 zod schema:不校验,加载时再校验)。
|
|
432
|
+
* The package's `extension.configSchemas.deployment` (written by the packer) is the form schema;
|
|
433
|
+
* its hints are checked like a loaded schema's (stripped when invalid, silently: a hand-made
|
|
434
|
+
* package). It is not compared with the module (not part of `manifest_mismatch`, spec §4.5).
|
|
345
435
|
*/
|
|
346
436
|
export async function staticDeploymentSchema(db, plugin) {
|
|
347
437
|
const row = await db
|
|
@@ -355,8 +445,15 @@ export async function staticDeploymentSchema(db, plugin) {
|
|
|
355
445
|
// new rows hold the plugin's extension section, pre-0.1.0 rows the old capybara section; both
|
|
356
446
|
// carry the static manifest
|
|
357
447
|
const section = row.section;
|
|
448
|
+
const stored = section.configSchemas?.deployment;
|
|
449
|
+
let jsonSchema;
|
|
450
|
+
if (typeof stored === "object" && stored !== null && !Array.isArray(stored)) {
|
|
451
|
+
jsonSchema = structuredClone(stored);
|
|
452
|
+
checkConfigUi(jsonSchema, "deployment");
|
|
453
|
+
}
|
|
358
454
|
return {
|
|
359
455
|
version: row.version,
|
|
456
|
+
...(jsonSchema !== undefined && { jsonSchema }),
|
|
360
457
|
fields: (section.manifest.config?.deployment ?? []).map((f) => ({
|
|
361
458
|
path: f.path,
|
|
362
459
|
secret: f.secret,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { LocalizedName } from "@capybara-hq/plugin-sdk";
|
|
2
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
3
|
+
import { ExtensionHost } from "./host.js";
|
|
4
|
+
/**
|
|
5
|
+
* Extension display names (extension config forms spec §2.2), the one resolver every extension and
|
|
6
|
+
* model API uses: a config-declared extension's plugin.json (read by this replica's host at load,
|
|
7
|
+
* the same on every replica), else the installed package's `display_name`, else the live catalog
|
|
8
|
+
* item of the same name, else null. No backfill: a package stored before 0066 gets a name with its
|
|
9
|
+
* next version. Stateless; one query per call.
|
|
10
|
+
*/
|
|
11
|
+
export declare class ExtensionDisplayNames {
|
|
12
|
+
private readonly db;
|
|
13
|
+
/** The config-declared extensions (they win over an install record of the same name, C15). */
|
|
14
|
+
private readonly host;
|
|
15
|
+
constructor(db: KernelDb,
|
|
16
|
+
/** The config-declared extensions (they win over an install record of the same name, C15). */
|
|
17
|
+
host: ExtensionHost);
|
|
18
|
+
/** One extension's display name. */
|
|
19
|
+
get(name: string): Promise<LocalizedName | null>;
|
|
20
|
+
/** The display names of `names` (each one a key, null when it has none), in one query. */
|
|
21
|
+
many(names: string[]): Promise<Map<string, LocalizedName | null>>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
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 { sql } from "kysely";
|
|
12
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
13
|
+
import { ExtensionHost } from "./host.js";
|
|
14
|
+
/**
|
|
15
|
+
* Extension display names (extension config forms spec §2.2), the one resolver every extension and
|
|
16
|
+
* model API uses: a config-declared extension's plugin.json (read by this replica's host at load,
|
|
17
|
+
* the same on every replica), else the installed package's `display_name`, else the live catalog
|
|
18
|
+
* item of the same name, else null. No backfill: a package stored before 0066 gets a name with its
|
|
19
|
+
* next version. Stateless; one query per call.
|
|
20
|
+
*/
|
|
21
|
+
let ExtensionDisplayNames = class ExtensionDisplayNames {
|
|
22
|
+
db;
|
|
23
|
+
host;
|
|
24
|
+
constructor(db,
|
|
25
|
+
/** The config-declared extensions (they win over an install record of the same name, C15). */
|
|
26
|
+
host) {
|
|
27
|
+
this.db = db;
|
|
28
|
+
this.host = host;
|
|
29
|
+
}
|
|
30
|
+
/** One extension's display name. */
|
|
31
|
+
async get(name) {
|
|
32
|
+
return (await this.many([name])).get(name) ?? null;
|
|
33
|
+
}
|
|
34
|
+
/** The display names of `names` (each one a key, null when it has none), in one query. */
|
|
35
|
+
async many(names) {
|
|
36
|
+
const out = new Map();
|
|
37
|
+
if (names.length === 0)
|
|
38
|
+
return out;
|
|
39
|
+
const declared = new Map(this.host.declaredPlugins().map((p) => [p.name, p]));
|
|
40
|
+
const rest = [];
|
|
41
|
+
for (const n of new Set(names)) {
|
|
42
|
+
const d = declared.get(n);
|
|
43
|
+
if (d)
|
|
44
|
+
out.set(n, d.displayName);
|
|
45
|
+
else
|
|
46
|
+
rest.push(n);
|
|
47
|
+
}
|
|
48
|
+
if (rest.length === 0)
|
|
49
|
+
return out;
|
|
50
|
+
const rows = await this.db
|
|
51
|
+
.selectFrom("extension_installs")
|
|
52
|
+
.innerJoin("extension_packages", "extension_packages.sha256", "extension_installs.sha256")
|
|
53
|
+
.select([
|
|
54
|
+
"extension_installs.name as name",
|
|
55
|
+
"extension_packages.display_name as display_name",
|
|
56
|
+
sql `0`.as("rank"),
|
|
57
|
+
])
|
|
58
|
+
.where("extension_installs.name", "in", rest)
|
|
59
|
+
.unionAll((eb) => eb
|
|
60
|
+
.selectFrom("catalog_items")
|
|
61
|
+
.select(["name", "display_name", sql `1`.as("rank")])
|
|
62
|
+
.where("name", "in", rest)
|
|
63
|
+
.where("deleted_at", "is", null))
|
|
64
|
+
.execute();
|
|
65
|
+
rows.sort((a, b) => Number(a.rank) - Number(b.rank));
|
|
66
|
+
for (const n of rest) {
|
|
67
|
+
out.set(n, rows.find((r) => r.name === n && r.display_name !== null)?.display_name ?? null);
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
ExtensionDisplayNames = __decorate([
|
|
73
|
+
Injectable(),
|
|
74
|
+
__param(0, Inject(KernelDb)),
|
|
75
|
+
__param(1, Inject(ExtensionHost))
|
|
76
|
+
], ExtensionDisplayNames);
|
|
77
|
+
export { ExtensionDisplayNames };
|
|
@@ -15,11 +15,13 @@ import { ExtensionApprovals } from "./approvals.js";
|
|
|
15
15
|
import { ExtensionBlobs } from "./blobs.js";
|
|
16
16
|
import { BootstrapService } from "./bootstrap.js";
|
|
17
17
|
import { ExtensionDeploymentConfigService } from "./deployment-config.js";
|
|
18
|
+
import { ExtensionDisplayNames } from "./display-name.js";
|
|
18
19
|
import { ExtensionHost } from "./host.js";
|
|
19
20
|
import { ExtensionInstalls } from "./installs.js";
|
|
20
21
|
import { ExtensionLifecycle } from "./lifecycle.js";
|
|
21
22
|
import { PluginApproveLock, PluginDeploymentConfigLock, PluginInstallLock } from "./locks.js";
|
|
22
23
|
import { OrgExtensionConfigs } from "./org-config.js";
|
|
24
|
+
import { ExtensionPointDefaults } from "./point-defaults.js";
|
|
23
25
|
import { ExtensionRegistryModule } from "./registry.js";
|
|
24
26
|
import { ReplicaStatusStore } from "./sources.js";
|
|
25
27
|
/**
|
|
@@ -52,8 +54,10 @@ ExtensionsModule = __decorate([
|
|
|
52
54
|
ExtensionLifecycle,
|
|
53
55
|
ExtensionAdmin,
|
|
54
56
|
ExtensionAdminOps,
|
|
57
|
+
ExtensionDisplayNames,
|
|
55
58
|
ExtensionDeploymentConfigService,
|
|
56
59
|
OrgExtensionConfigs,
|
|
60
|
+
ExtensionPointDefaults,
|
|
57
61
|
BootstrapService,
|
|
58
62
|
],
|
|
59
63
|
exports: [
|
|
@@ -68,8 +72,10 @@ ExtensionsModule = __decorate([
|
|
|
68
72
|
ExtensionLifecycle,
|
|
69
73
|
ExtensionAdmin,
|
|
70
74
|
ExtensionAdminOps,
|
|
75
|
+
ExtensionDisplayNames,
|
|
71
76
|
ExtensionDeploymentConfigService,
|
|
72
77
|
OrgExtensionConfigs,
|
|
78
|
+
ExtensionPointDefaults,
|
|
73
79
|
BootstrapService,
|
|
74
80
|
],
|
|
75
81
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ExtensionManifest, type ExtensionPointRef, type ToolHandler, type ToolSpec, type UiContribution } from "@capybara-hq/plugin-sdk";
|
|
1
|
+
import { type ExtensionManifest, type ExtensionPointRef, type LocalizedName, type ToolHandler, type ToolSpec, type UiContribution } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import type { Redis } from "ioredis";
|
|
3
3
|
import type { core } from "zod";
|
|
4
4
|
import type { KernelAppOptions } from "../app.js";
|
|
@@ -46,6 +46,8 @@ export interface InspectedExtension {
|
|
|
46
46
|
dir: string;
|
|
47
47
|
/** 规范化的权限集合,见 {@link computePermissionSet}。 */
|
|
48
48
|
permissions: PermissionSet;
|
|
49
|
+
/** The plugin.json `displayName` of the module's plugin directory, if any. */
|
|
50
|
+
displayName: LocalizedName | null;
|
|
49
51
|
}
|
|
50
52
|
/**
|
|
51
53
|
* 插件两级配置 schema 中的每个 `secret()` 都必须标在对象路径的字段上(见 `unreachableSecrets`),
|
|
@@ -84,6 +86,8 @@ export interface DeclaredExtensionInfo {
|
|
|
84
86
|
configurable: boolean;
|
|
85
87
|
/** 启动配置里的部署配置按 schema 校验通过(没有 schema 时恒为 true)。 */
|
|
86
88
|
configValid: boolean;
|
|
89
|
+
/** The plugin.json `displayName` of the module's plugin directory, if any. */
|
|
90
|
+
displayName: LocalizedName | null;
|
|
87
91
|
}
|
|
88
92
|
/** The extension sources of {@link ExtensionHost.load}, loaded in this order (see {@link ExtensionSource}). */
|
|
89
93
|
export interface ExtensionLoadPlan {
|
|
@@ -191,6 +195,11 @@ export declare class ExtensionHost {
|
|
|
191
195
|
private readonly retiring;
|
|
192
196
|
/** 配置声明插件的清单与权限集合(含未加载的;后台列表与网页批准用)。 */
|
|
193
197
|
private readonly declaredInfo;
|
|
198
|
+
/**
|
|
199
|
+
* Config-declared extensions' display names, read from their plugin directory's plugin.json at
|
|
200
|
+
* load (from the startup config, the same on every replica; never written elsewhere).
|
|
201
|
+
*/
|
|
202
|
+
private readonly declaredDisplayNames;
|
|
194
203
|
/** 导入过的插件名 → 来源与包(含未加载的;重名被跳过的一方不在这里)。 */
|
|
195
204
|
private readonly sources;
|
|
196
205
|
private didLoad;
|
|
@@ -210,6 +219,8 @@ export declare class ExtensionHost {
|
|
|
210
219
|
private readonly configValidity;
|
|
211
220
|
/** 已告警过的「部署配置不合法」(插件名 → 说明;每个周期都会重新判定,同一说明只告警一次)。 */
|
|
212
221
|
private readonly configWarned;
|
|
222
|
+
/** `<name>@<version>` whose invalid config UI hints were warned about (a log dedupe only). */
|
|
223
|
+
private readonly configUiWarned;
|
|
213
224
|
/**
|
|
214
225
|
* The host builds each extension's `ctx` from the injected kernel services: the pool for
|
|
215
226
|
* `ctx.db` on the extension's schema, Redis for `kv` / `lock` / `bus` and the queues, the
|
|
@@ -290,6 +301,11 @@ export declare class ExtensionHost {
|
|
|
290
301
|
* `plugin host closed during load` at the next checkpoint.
|
|
291
302
|
*/
|
|
292
303
|
load(plan: string[] | ExtensionLoadPlan): Promise<void>;
|
|
304
|
+
/**
|
|
305
|
+
* Records each config-declared extension's display name from its plugin directory's plugin.json
|
|
306
|
+
* (spec §2.2); an invalid plugin.json only warns (no display name).
|
|
307
|
+
*/
|
|
308
|
+
private noteDisplayNames;
|
|
293
309
|
/**
|
|
294
310
|
* Config-declared extensions also take their name (I4, an addition to Ruling P3): the
|
|
295
311
|
* name is inserted into `extension_name_owners` with its npm package name (left alone when present).
|
|
@@ -356,6 +372,15 @@ export declare class ExtensionHost {
|
|
|
356
372
|
* - 缺的能力没有任何提供方 → 与此前一样抛错(内核启动失败)。
|
|
357
373
|
*/
|
|
358
374
|
private loadDeferred;
|
|
375
|
+
/**
|
|
376
|
+
* Checks the config UI hints of a loaded module's deployment and org schemas (spec §4.1). Invalid
|
|
377
|
+
* hints never fail the load: the form schemas drop their `x-ui` (`configFormSchema`), one warning
|
|
378
|
+
* per `<name>@<version>` is logged, and the returned text goes into the status detail (null when
|
|
379
|
+
* every hint is valid). The packer refuses such a package; this covers hand-made ones. It never
|
|
380
|
+
* throws (it runs after the instance is active, before its status row is written): a conversion
|
|
381
|
+
* that throws is warned about and reported in the detail the same way.
|
|
382
|
+
*/
|
|
383
|
+
private checkConfigUi;
|
|
359
384
|
/** 给已有状态行补说明;失败只记 warn。 */
|
|
360
385
|
private noteStatus;
|
|
361
386
|
/**
|