@lesliechan721/aw 0.1.0-beta.10 → 0.1.0-beta.12
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/authoring/assets/aw-config.d.mts +1 -50
- package/dist/authoring/assets/aw-config.mjs +58 -928
- package/dist/authoring/assets/aw-config.mjs.map +1 -1
- package/dist/authoring/scripts/init-plugin.mjs +28 -33
- package/dist/authoring/scripts/init-plugin.mjs.map +1 -1
- package/dist/authoring/scripts/lib/plugin-version-check.d.mts +1 -0
- package/dist/authoring/scripts/lib/plugin-version-check.mjs +229 -8
- package/dist/authoring/scripts/lib/plugin-version-check.mjs.map +1 -1
- package/dist/authoring/scripts/validate-plugin.mjs +159 -48
- package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
- package/dist/scripts/bundle-plugins.js +18 -4
- package/dist/scripts/bundle-plugins.js.map +1 -1
- package/dist/scripts/test-plugin-scripts.d.ts +2 -0
- package/dist/scripts/test-plugin-scripts.js +21 -5
- package/dist/scripts/test-plugin-scripts.js.map +1 -1
- package/dist/src/commands/aw-capabilities.d.ts +1 -1
- package/dist/src/commands/aw-capabilities.js +1 -1
- package/dist/src/commands/aw-capabilities.js.map +1 -1
- package/dist/src/commands/catalog-dev-source.d.ts +6 -3
- package/dist/src/commands/catalog-dev-source.js +96 -35
- package/dist/src/commands/catalog-dev-source.js.map +1 -1
- package/dist/src/commands/catalog-publication-inspection.d.ts +1 -1
- package/dist/src/commands/catalog-publication-inspection.js +54 -8
- package/dist/src/commands/catalog-publication-inspection.js.map +1 -1
- package/dist/src/commands/catalog-publication-journal.js +1 -1
- package/dist/src/commands/catalog-publication-journal.js.map +1 -1
- package/dist/src/commands/catalog-source.d.ts +19 -4
- package/dist/src/commands/catalog-source.js +121 -12
- package/dist/src/commands/catalog-source.js.map +1 -1
- package/dist/src/commands/catalog-store.d.ts +26 -7
- package/dist/src/commands/catalog-store.js +361 -42
- package/dist/src/commands/catalog-store.js.map +1 -1
- package/dist/src/commands/console.js +28 -17
- package/dist/src/commands/console.js.map +1 -1
- package/dist/src/commands/operation-plan.d.ts +2 -1
- package/dist/src/commands/operation-plan.js +24 -0
- package/dist/src/commands/operation-plan.js.map +1 -1
- package/dist/src/commands/operation-planner.d.ts +2 -2
- package/dist/src/commands/operation-planner.js +22 -20
- package/dist/src/commands/operation-planner.js.map +1 -1
- package/dist/src/commands/options.d.ts +2 -2
- package/dist/src/commands/options.js +18 -4
- package/dist/src/commands/options.js.map +1 -1
- package/dist/src/commands/plugin-capabilities.js +2 -2
- package/dist/src/commands/plugin-capabilities.js.map +1 -1
- package/dist/src/commands/rebuild-command.d.ts +19 -0
- package/dist/src/commands/rebuild-command.js +828 -283
- package/dist/src/commands/rebuild-command.js.map +1 -1
- package/dist/src/commands/rebuild-integration.d.ts +25 -47
- package/dist/src/commands/rebuild-integration.js +1176 -1016
- package/dist/src/commands/rebuild-integration.js.map +1 -1
- package/dist/src/commands/rebuild-operations.d.ts +50 -12
- package/dist/src/commands/rebuild-operations.js +207 -101
- package/dist/src/commands/rebuild-operations.js.map +1 -1
- package/dist/src/commands/status-v6.d.ts +21 -2
- package/dist/src/commands/status-v6.js +163 -31
- package/dist/src/commands/status-v6.js.map +1 -1
- package/dist/src/commands/sync-command.d.ts +17 -0
- package/dist/src/commands/sync-command.js +45 -37
- package/dist/src/commands/sync-command.js.map +1 -1
- package/dist/src/commands/write-commands.d.ts +5 -0
- package/dist/src/commands/write-commands.js +50 -3
- package/dist/src/commands/write-commands.js.map +1 -1
- package/dist/src/generators/local-plugin.js +14 -4
- package/dist/src/generators/local-plugin.js.map +1 -1
- package/dist/src/index.js +260 -91
- package/dist/src/index.js.map +1 -1
- package/dist/src/output/command-receipt.js +1 -3
- package/dist/src/output/command-receipt.js.map +1 -1
- package/dist/src/output/rebuild-progress.js +1 -3
- package/dist/src/output/rebuild-progress.js.map +1 -1
- package/dist/src/portable/materializer.js +10 -8
- package/dist/src/portable/materializer.js.map +1 -1
- package/dist/src/tui/catalog-generation.js +41 -1
- package/dist/src/tui/catalog-generation.js.map +1 -1
- package/dist/src/tui/catalog-sources/session.d.ts +1 -0
- package/dist/src/tui/catalog-sources/session.js +16 -3
- package/dist/src/tui/catalog-sources/session.js.map +1 -1
- package/dist/src/tui/catalog-sources/types.d.ts +3 -2
- package/dist/src/tui/components.d.ts +4 -0
- package/dist/src/tui/components.js +36 -24
- package/dist/src/tui/components.js.map +1 -1
- package/dist/src/tui/console-app-v4.d.ts +13 -4
- package/dist/src/tui/console-app-v4.js +2065 -857
- package/dist/src/tui/console-app-v4.js.map +1 -1
- package/dist/src/tui/controller-runtime.js +731 -62
- package/dist/src/tui/controller-runtime.js.map +1 -1
- package/dist/src/tui/controller.d.ts +156 -10
- package/dist/src/tui/controller.js +1187 -163
- package/dist/src/tui/controller.js.map +1 -1
- package/dist/src/tui/diagnostic-projection.d.ts +22 -0
- package/dist/src/tui/diagnostic-projection.js +437 -0
- package/dist/src/tui/diagnostic-projection.js.map +1 -0
- package/dist/src/tui/diagnostics.d.ts +1 -1
- package/dist/src/tui/diagnostics.js +7 -2
- package/dist/src/tui/diagnostics.js.map +1 -1
- package/dist/src/tui/glossary.d.ts +23 -0
- package/dist/src/tui/glossary.js +42 -0
- package/dist/src/tui/glossary.js.map +1 -0
- package/dist/src/tui/index.d.ts +4 -1
- package/dist/src/tui/index.js +4 -1
- package/dist/src/tui/index.js.map +1 -1
- package/dist/src/tui/keys.d.ts +44 -0
- package/dist/src/tui/keys.js +43 -15
- package/dist/src/tui/keys.js.map +1 -1
- package/dist/src/tui/lifecycle-action-view.d.ts +6 -0
- package/dist/src/tui/lifecycle-action-view.js +34 -0
- package/dist/src/tui/lifecycle-action-view.js.map +1 -0
- package/dist/src/tui/model.d.ts +12 -2
- package/dist/src/tui/model.js +128 -52
- package/dist/src/tui/model.js.map +1 -1
- package/dist/src/tui/operation-diagnostic-screens.d.ts +21 -0
- package/dist/src/tui/operation-diagnostic-screens.js +101 -0
- package/dist/src/tui/operation-diagnostic-screens.js.map +1 -0
- package/dist/src/tui/operation-history.d.ts +80 -0
- package/dist/src/tui/operation-history.js +130 -0
- package/dist/src/tui/operation-history.js.map +1 -0
- package/dist/src/tui/operation-review-planner.js +366 -99
- package/dist/src/tui/operation-review-planner.js.map +1 -1
- package/dist/src/tui/router.d.ts +82 -17
- package/dist/src/tui/router.js +186 -38
- package/dist/src/tui/router.js.map +1 -1
- package/dist/src/tui/screen-registry.d.ts +546 -0
- package/dist/src/tui/screen-registry.js +179 -0
- package/dist/src/tui/screen-registry.js.map +1 -0
- package/dist/src/tui/session-console-app.d.ts +6 -0
- package/dist/src/tui/session-console-app.js +13 -0
- package/dist/src/tui/session-console-app.js.map +1 -0
- package/dist/src/tui/session-host.d.ts +44 -0
- package/dist/src/tui/session-host.js +197 -0
- package/dist/src/tui/session-host.js.map +1 -0
- package/dist/src/types.d.ts +64 -3
- package/dist/src/types.js +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/agent-version.js +1 -1
- package/dist/src/utils/agent-version.js.map +1 -1
- package/dist/src/utils/artifact-plan.d.ts +2 -2
- package/dist/src/utils/artifact-plan.js +8 -6
- package/dist/src/utils/artifact-plan.js.map +1 -1
- package/dist/src/utils/artifact-renderer.d.ts +2 -1
- package/dist/src/utils/artifact-renderer.js +139 -120
- package/dist/src/utils/artifact-renderer.js.map +1 -1
- package/dist/src/utils/artifact-request.d.ts +5 -0
- package/dist/src/utils/artifact-request.js +40 -0
- package/dist/src/utils/artifact-request.js.map +1 -1
- package/dist/src/utils/bundle-layout.js +4 -4
- package/dist/src/utils/bundle-layout.js.map +1 -1
- package/dist/src/utils/catalog-capability-projection.d.ts +8 -0
- package/dist/src/utils/catalog-capability-projection.js +14 -0
- package/dist/src/utils/catalog-capability-projection.js.map +1 -0
- package/dist/src/utils/catalog-generation-resolver.d.ts +14 -2
- package/dist/src/utils/catalog-generation-resolver.js +49 -27
- package/dist/src/utils/catalog-generation-resolver.js.map +1 -1
- package/dist/src/utils/catalog-generation-service.d.ts +8 -1
- package/dist/src/utils/catalog-generation-service.js +81 -47
- package/dist/src/utils/catalog-generation-service.js.map +1 -1
- package/dist/src/utils/catalog-generation-store.d.ts +1 -0
- package/dist/src/utils/catalog-generation-store.js +60 -5
- package/dist/src/utils/catalog-generation-store.js.map +1 -1
- package/dist/src/utils/catalog-operation-context.js +1 -0
- package/dist/src/utils/catalog-operation-context.js.map +1 -1
- package/dist/src/utils/catalog-public-error.js +4 -0
- package/dist/src/utils/catalog-public-error.js.map +1 -1
- package/dist/src/utils/catalog-source-impact.d.ts +3 -2
- package/dist/src/utils/catalog-source-impact.js +142 -20
- package/dist/src/utils/catalog-source-impact.js.map +1 -1
- package/dist/src/utils/catalog-source-references.js +95 -9
- package/dist/src/utils/catalog-source-references.js.map +1 -1
- package/dist/src/utils/catalog-sources.d.ts +1 -1
- package/dist/src/utils/catalog-sources.js +19 -3
- package/dist/src/utils/catalog-sources.js.map +1 -1
- package/dist/src/utils/codex-manager.js +8 -0
- package/dist/src/utils/codex-manager.js.map +1 -1
- package/dist/src/utils/codex-native-observation.d.ts +34 -1
- package/dist/src/utils/codex-native-observation.js +132 -0
- package/dist/src/utils/codex-native-observation.js.map +1 -1
- package/dist/src/utils/codex-reconciler.d.ts +0 -2
- package/dist/src/utils/codex-reconciler.js.map +1 -1
- package/dist/src/utils/codex-shared-native.d.ts +2 -26
- package/dist/src/utils/codex-shared-native.js +8 -82
- package/dist/src/utils/codex-shared-native.js.map +1 -1
- package/dist/src/utils/git-catalog-provider.d.ts +3 -0
- package/dist/src/utils/git-catalog-provider.js +40 -1
- package/dist/src/utils/git-catalog-provider.js.map +1 -1
- package/dist/src/utils/local-marketplace.d.ts +1 -0
- package/dist/src/utils/local-marketplace.js +69 -73
- package/dist/src/utils/local-marketplace.js.map +1 -1
- package/dist/src/utils/multi-source-catalog.js +1 -0
- package/dist/src/utils/multi-source-catalog.js.map +1 -1
- package/dist/src/utils/native-cli.d.ts +9 -4
- package/dist/src/utils/native-cli.js +280 -34
- package/dist/src/utils/native-cli.js.map +1 -1
- package/dist/src/utils/path-catalog-provider.js +2 -0
- package/dist/src/utils/path-catalog-provider.js.map +1 -1
- package/dist/src/utils/plugin-config-impact.d.ts +33 -0
- package/dist/src/utils/plugin-config-impact.js +298 -0
- package/dist/src/utils/plugin-config-impact.js.map +1 -0
- package/dist/src/utils/plugin-config-write.d.ts +36 -14
- package/dist/src/utils/plugin-config-write.js +709 -225
- package/dist/src/utils/plugin-config-write.js.map +1 -1
- package/dist/src/utils/plugin-config.d.ts +58 -4
- package/dist/src/utils/plugin-config.js +328 -60
- package/dist/src/utils/plugin-config.js.map +1 -1
- package/dist/src/utils/plugin-scripts.d.ts +20 -12
- package/dist/src/utils/plugin-scripts.js +389 -114
- package/dist/src/utils/plugin-scripts.js.map +1 -1
- package/dist/src/utils/process-tree.d.ts +2 -2
- package/dist/src/utils/process-tree.js +1 -1
- package/dist/src/utils/process-tree.js.map +1 -1
- package/dist/src/utils/project-boundary.d.ts +11 -1
- package/dist/src/utils/project-boundary.js +33 -11
- package/dist/src/utils/project-boundary.js.map +1 -1
- package/dist/src/utils/safe-operation-diagnostic.d.ts +15 -0
- package/dist/src/utils/safe-operation-diagnostic.js +33 -0
- package/dist/src/utils/safe-operation-diagnostic.js.map +1 -0
- package/dist/src/utils/sensitive-content.d.ts +4 -0
- package/dist/src/utils/sensitive-content.js +36 -0
- package/dist/src/utils/sensitive-content.js.map +1 -0
- package/dist/src/utils/windows-claude-shim.d.ts +9 -0
- package/dist/src/utils/windows-claude-shim.js +141 -0
- package/dist/src/utils/windows-claude-shim.js.map +1 -0
- package/dist/vitest.config.js +91 -10
- package/dist/vitest.config.js.map +1 -1
- package/package.json +9 -9
- package/dist/authoring/templates/aw-config-runtime.d.mts +0 -2
- package/dist/authoring/templates/aw-config-runtime.mjs +0 -407
- package/dist/authoring/templates/aw-config-runtime.mjs.map +0 -1
|
@@ -2,13 +2,20 @@ import crypto from 'node:crypto';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { statusCommandV7, statusTargetIntent, } from '../commands/status-v6.js';
|
|
4
4
|
import { addCatalogSourceCommand, listCatalogSources, preflightCatalogSourceMutation, removeCatalogSourceCommand, setPrimaryCatalogSourceCommand, updateCatalogSourceCommand, } from '../commands/catalog-source.js';
|
|
5
|
-
import { cleanupWriteCommand, installWriteCommand, reinstallWriteCommand, syncWriteCommand, uninstallWriteCommand, } from '../commands/write-commands.js';
|
|
5
|
+
import { cleanupWriteCommand, failedWriteCommandResult, installWriteCommand, mergeWriteCommandResults, reinstallWriteCommand, syncWriteCommand, uninstallWriteCommand, } from '../commands/write-commands.js';
|
|
6
|
+
import { resolveSyncIntentSelection } from '../commands/sync-command.js';
|
|
7
|
+
import { parseScriptTimeoutMs, SCRIPT_TIMEOUT_DEFAULT_MS, } from '../commands/options.js';
|
|
6
8
|
import { readCliPackageInfo } from '../utils/local-marketplace.js';
|
|
9
|
+
import { createCodexNativeObservationSession, } from '../utils/codex-native-observation.js';
|
|
7
10
|
import { readCatalogSourcesConfigSnapshot, recoverInvalidCatalogSourcesConfig, } from '../utils/catalog-sources.js';
|
|
8
11
|
import { withResolvedCatalogPlugin, withResolvedMultiSourceCatalog, formatPluginId, parsePluginId, } from '../utils/multi-source-catalog.js';
|
|
9
|
-
import { coercePluginConfigUpdates, inspectPluginConfigResetTarget, readPluginConfigStore, resolveConfigRead, resolveEffectivePluginConfig, } from '../utils/plugin-config.js';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
+
import { coercePluginConfigUpdates, inspectPluginConfigResetTarget, listNamespacedPluginConfigStoreIdentities, readPluginConfigStore, resolveConfigRead, resolveEffectivePluginConfig, resolvePluginConfigStorePath, } from '../utils/plugin-config.js';
|
|
13
|
+
import { assertProjectSharedConfigPathVisible } from '../utils/project-boundary.js';
|
|
14
|
+
import { readPluginIntentState } from '../utils/plugin-intent-state.js';
|
|
15
|
+
import { applyPluginConfigWrite, replayConfigRuntimeWrites, resolveConfigPreApplyAuthorization, resetPluginConfigWithHelper, } from '../utils/plugin-config-write.js';
|
|
16
|
+
import { analyzePluginConfigMutationImpact } from '../utils/plugin-config-impact.js';
|
|
17
|
+
import { createBatchIntentCompatiblePlanFingerprint } from '../commands/operation-plan.js';
|
|
18
|
+
import { offlineCleanupEvidenceFromInventory, offlineCleanupEvidenceMatches, } from '../commands/offline-cleanup-evidence.js';
|
|
12
19
|
import { inventoryCatalogSourceReferences } from '../utils/catalog-source-references.js';
|
|
13
20
|
import { operationEvidenceMatches, operationEvidenceFingerprint, TuiConfigInvalidStoreError, TuiController, TuiOperationBlockedError, } from './controller.js';
|
|
14
21
|
import { buildConfigGroups, buildConfigPage, projectPlatformPlacement, } from './model.js';
|
|
@@ -112,16 +119,32 @@ export function configAffectedStatusTargets(targets, pluginId, configScope) {
|
|
|
112
119
|
.sort((left, right) => `${left.platform}\0${left.scope}`
|
|
113
120
|
.localeCompare(`${right.platform}\0${right.scope}`, 'en'));
|
|
114
121
|
}
|
|
115
|
-
function
|
|
116
|
-
const changed = new Set(changedKeys);
|
|
122
|
+
function configRetrySharedNativeRenderTargets(plugin) {
|
|
117
123
|
return (plugin.manifest.artifacts?.targets ?? []).flatMap((target) => target.platform === 'codex'
|
|
118
124
|
&& target.target === 'codex.skill'
|
|
119
125
|
&& target.delivery.mode === 'codex-native'
|
|
120
126
|
&& target.skillKey
|
|
121
|
-
&& target.refreshKeys.
|
|
127
|
+
&& target.refreshKeys.length > 0
|
|
122
128
|
? [{ id: target.id, skillKey: target.skillKey, refreshKeys: [...target.refreshKeys] }]
|
|
123
129
|
: []);
|
|
124
130
|
}
|
|
131
|
+
function configImpactVisibleTargets(pluginName, targets) {
|
|
132
|
+
return targets.map((target) => ({
|
|
133
|
+
pluginName,
|
|
134
|
+
platform: target.platform,
|
|
135
|
+
scope: target.scope,
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
function configIntentRequestsApply(intent) {
|
|
139
|
+
if (!intent.apply)
|
|
140
|
+
return false;
|
|
141
|
+
if (intent.retryApply === true)
|
|
142
|
+
return true;
|
|
143
|
+
if (intent.changes)
|
|
144
|
+
return intent.changes.length > 0;
|
|
145
|
+
return Object.keys(intent.updates ?? {}).length > 0
|
|
146
|
+
|| (intent.removeKeys?.length ?? 0) > 0;
|
|
147
|
+
}
|
|
125
148
|
function operationReviewStale(message) {
|
|
126
149
|
return new TuiOperationBlockedError('operationReviewStale', `operationReviewStale: ${message}`);
|
|
127
150
|
}
|
|
@@ -130,6 +153,7 @@ function sourceEvidenceForPlugin(source, pluginName) {
|
|
|
130
153
|
return {
|
|
131
154
|
sourceId: source.sourceId,
|
|
132
155
|
sourceIdentity: source.sourceIdentity,
|
|
156
|
+
logicalIdentity: source.logicalIdentity,
|
|
133
157
|
requestedRef: source.requestedRef,
|
|
134
158
|
resolvedCommit: source.resolvedCommit,
|
|
135
159
|
manifestDigest: source.manifestDigest,
|
|
@@ -140,9 +164,27 @@ function sourceEvidenceForPlugin(source, pluginName) {
|
|
|
140
164
|
channel: source.manifest.channel,
|
|
141
165
|
};
|
|
142
166
|
}
|
|
167
|
+
async function inspectConfigShareability(options) {
|
|
168
|
+
if (options.scope !== 'project')
|
|
169
|
+
return undefined;
|
|
170
|
+
const targetPath = resolvePluginConfigStorePath({
|
|
171
|
+
sourceId: options.sourceId,
|
|
172
|
+
pluginName: options.pluginName,
|
|
173
|
+
scope: 'project',
|
|
174
|
+
cwd: options.cwd,
|
|
175
|
+
env: options.env,
|
|
176
|
+
});
|
|
177
|
+
const visibility = await assertProjectSharedConfigPathVisible({
|
|
178
|
+
cwd: options.cwd,
|
|
179
|
+
targetPath,
|
|
180
|
+
env: options.env,
|
|
181
|
+
});
|
|
182
|
+
return visibility.state === 'unverified' ? 'unverified' : 'verified';
|
|
183
|
+
}
|
|
143
184
|
function assertSourceEvidenceMatches(expected, actual) {
|
|
144
185
|
if (actual.sourceId !== expected.sourceId
|
|
145
186
|
|| actual.sourceIdentity !== expected.sourceIdentity
|
|
187
|
+
|| actual.logicalIdentity !== expected.logicalIdentity
|
|
146
188
|
|| actual.resolvedCommit !== expected.resolvedCommit
|
|
147
189
|
|| actual.manifestDigest !== expected.manifestDigest
|
|
148
190
|
|| actual.snapshotDigest !== expected.snapshotDigest
|
|
@@ -150,10 +192,12 @@ function assertSourceEvidenceMatches(expected, actual) {
|
|
|
150
192
|
throw operationReviewStale('确认后来源内容发生变化。');
|
|
151
193
|
}
|
|
152
194
|
}
|
|
153
|
-
function
|
|
154
|
-
|
|
195
|
+
function writeReviewIsStale(result) {
|
|
196
|
+
return result.targetResults.some((target) => target.errorCode === 'operationReviewStale'
|
|
155
197
|
|| target.errorCode === 'operationPlanStale');
|
|
156
|
-
|
|
198
|
+
}
|
|
199
|
+
function throwIfWriteReviewStale(result) {
|
|
200
|
+
if (writeReviewIsStale(result)) {
|
|
157
201
|
throw operationReviewStale('确认后实际写入计划发生变化。');
|
|
158
202
|
}
|
|
159
203
|
}
|
|
@@ -163,6 +207,122 @@ const SOURCE_PROGRESS_PHASES = {
|
|
|
163
207
|
function pluginIntent(intent) {
|
|
164
208
|
return 'pluginId' in intent;
|
|
165
209
|
}
|
|
210
|
+
function reviewedScriptTimeoutMs(intent) {
|
|
211
|
+
if ((intent.kind === 'pluginWrite' || intent.kind === 'pluginWriteBatch')
|
|
212
|
+
&& (intent.action === 'install' || intent.action === 'refreshAndSync'
|
|
213
|
+
|| intent.action === 'reinstall' || intent.action === 'sync')) {
|
|
214
|
+
return parseScriptTimeoutMs(intent.scriptTimeoutMs ?? SCRIPT_TIMEOUT_DEFAULT_MS);
|
|
215
|
+
}
|
|
216
|
+
if (intent.kind === 'configSave' && intent.apply) {
|
|
217
|
+
return parseScriptTimeoutMs(intent.scriptTimeoutMs ?? SCRIPT_TIMEOUT_DEFAULT_MS);
|
|
218
|
+
}
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
function selectedBatchGroups(intent) {
|
|
222
|
+
if (intent.selection.kind !== 'selected' && intent.selection.kind !== 'targets') {
|
|
223
|
+
throw new TuiOperationBlockedError('syncSelectionRequired', '当前项目全部同步必须从项目 intent roots 解析。');
|
|
224
|
+
}
|
|
225
|
+
const rawTargets = intent.selection.kind === 'targets'
|
|
226
|
+
? intent.selection.targets
|
|
227
|
+
: intent.selection.pluginIds.map((pluginId) => ({
|
|
228
|
+
pluginId, platform: intent.platform, scope: intent.scope,
|
|
229
|
+
}));
|
|
230
|
+
const normalizedTargets = rawTargets.map((target) => {
|
|
231
|
+
if ((target.platform !== 'codex' && target.platform !== 'claude' && target.platform !== 'both')
|
|
232
|
+
|| target.scope !== intent.scope
|
|
233
|
+
|| (intent.selection.kind === 'targets' && target.platform === 'both')) {
|
|
234
|
+
throw new TuiOperationBlockedError('batchTargetInvalid', '批量精确目标必须使用共同 scope 和单个平台。');
|
|
235
|
+
}
|
|
236
|
+
const pluginId = target.pluginId;
|
|
237
|
+
const parsed = parsePluginId(pluginId);
|
|
238
|
+
if (!parsed.sourceId) {
|
|
239
|
+
throw new TuiOperationBlockedError('invalidPluginId', '批量操作必须使用 canonical pluginId。');
|
|
240
|
+
}
|
|
241
|
+
const canonicalPluginId = formatPluginId({ sourceId: parsed.sourceId, pluginName: parsed.pluginName });
|
|
242
|
+
if (intent.selection.kind === 'targets' && canonicalPluginId !== pluginId) {
|
|
243
|
+
throw new TuiOperationBlockedError('invalidPluginId', '批量精确目标必须使用 canonical pluginId。');
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
pluginId: canonicalPluginId,
|
|
247
|
+
platform: target.platform,
|
|
248
|
+
scope: target.scope,
|
|
249
|
+
};
|
|
250
|
+
}).sort((left, right) => [left.pluginId, left.platform, left.scope].join('\0')
|
|
251
|
+
.localeCompare([right.pluginId, right.platform, right.scope].join('\0'), 'en'));
|
|
252
|
+
const uniqueTargets = [...new Map(normalizedTargets.map((target) => [
|
|
253
|
+
[target.pluginId, target.platform, target.scope].join('\0'), target,
|
|
254
|
+
])).values()];
|
|
255
|
+
const requestedPluginIds = [...new Set(uniqueTargets.map((target) => target.pluginId))];
|
|
256
|
+
if (requestedPluginIds.length === 0) {
|
|
257
|
+
throw new TuiOperationBlockedError('syncSelectionRequired', '批量操作至少需要一个插件。');
|
|
258
|
+
}
|
|
259
|
+
const groups = new Map();
|
|
260
|
+
for (const target of uniqueTargets) {
|
|
261
|
+
const pluginId = target.pluginId;
|
|
262
|
+
const sourceId = parsePluginId(pluginId).sourceId;
|
|
263
|
+
const groupKey = [sourceId, target.platform, target.scope].join('\0');
|
|
264
|
+
const group = groups.get(groupKey) ?? {
|
|
265
|
+
groupId: groupKey,
|
|
266
|
+
sourceId,
|
|
267
|
+
platform: target.platform,
|
|
268
|
+
scope: target.scope,
|
|
269
|
+
requestedPluginIds: [],
|
|
270
|
+
};
|
|
271
|
+
group.requestedPluginIds.push(pluginId);
|
|
272
|
+
groups.set(groupKey, group);
|
|
273
|
+
}
|
|
274
|
+
return { requestedPluginIds, groups: [...groups.values()] };
|
|
275
|
+
}
|
|
276
|
+
async function resolveBatchGroups(intent, env, cwd, frozenRequestedPluginIds) {
|
|
277
|
+
if (intent.selection.kind === 'selected' || intent.selection.kind === 'targets') {
|
|
278
|
+
return selectedBatchGroups(intent);
|
|
279
|
+
}
|
|
280
|
+
if (intent.action !== 'sync' || intent.scope !== 'project') {
|
|
281
|
+
throw new TuiOperationBlockedError('syncSelectionRequired', '当前项目全部操作只支持 project scope sync。');
|
|
282
|
+
}
|
|
283
|
+
const state = await readPluginIntentState({ scope: 'project', cwd, env });
|
|
284
|
+
const selection = resolveSyncIntentSelection({
|
|
285
|
+
roots: state.roots,
|
|
286
|
+
selectors: frozenRequestedPluginIds ?? [],
|
|
287
|
+
all: frozenRequestedPluginIds === undefined,
|
|
288
|
+
platform: intent.platform,
|
|
289
|
+
});
|
|
290
|
+
if (selection.requestedPluginIds.length === 0) {
|
|
291
|
+
throw new TuiOperationBlockedError('syncSelectionRequired', '当前项目没有可同步的 intent roots。');
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
requestedPluginIds: selection.requestedPluginIds,
|
|
295
|
+
groups: selection.groups.map((group) => ({
|
|
296
|
+
groupId: `${group.sourceId}\0${group.platform}\0${intent.scope}`,
|
|
297
|
+
sourceId: group.sourceId,
|
|
298
|
+
platform: group.platform,
|
|
299
|
+
scope: intent.scope,
|
|
300
|
+
requestedPluginIds: group.pluginIds,
|
|
301
|
+
})),
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
async function runBatchWriteGroup(options) {
|
|
305
|
+
const commandOptions = {
|
|
306
|
+
cwd: options.cwd,
|
|
307
|
+
platform: options.group.platform,
|
|
308
|
+
scope: options.group.scope,
|
|
309
|
+
...(reviewedScriptTimeoutMs(options.intent) === undefined
|
|
310
|
+
? {}
|
|
311
|
+
: { scriptTimeoutMs: reviewedScriptTimeoutMs(options.intent) }),
|
|
312
|
+
};
|
|
313
|
+
switch (options.intent.action) {
|
|
314
|
+
case 'install':
|
|
315
|
+
return installWriteCommand(options.group.requestedPluginIds, commandOptions, options.runtime);
|
|
316
|
+
case 'sync':
|
|
317
|
+
return syncWriteCommand(options.group.requestedPluginIds, commandOptions, options.runtime);
|
|
318
|
+
case 'reinstall':
|
|
319
|
+
return reinstallWriteCommand(options.group.requestedPluginIds, commandOptions, options.runtime);
|
|
320
|
+
case 'uninstall':
|
|
321
|
+
return uninstallWriteCommand(options.group.requestedPluginIds, commandOptions, options.runtime);
|
|
322
|
+
case 'cleanup':
|
|
323
|
+
return cleanupWriteCommand(options.group.requestedPluginIds, commandOptions, options.runtime);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
166
326
|
async function loadDependencyOverviews(options) {
|
|
167
327
|
const graph = await withResolvedMultiSourceCatalog({
|
|
168
328
|
cliVersion: options.cliVersion,
|
|
@@ -437,6 +597,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
437
597
|
};
|
|
438
598
|
};
|
|
439
599
|
const catalogOperationByEvidence = new WeakMap();
|
|
600
|
+
const codexManagerByEvidence = new WeakMap();
|
|
440
601
|
let sessionCatalogOperationContext;
|
|
441
602
|
let sessionStatusResult;
|
|
442
603
|
const sessionContextForPlugin = (pluginId) => {
|
|
@@ -450,6 +611,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
450
611
|
const stores = await Promise.all(scopes.map((scope) => readPluginConfigStore({
|
|
451
612
|
sourceId: config.sourceId,
|
|
452
613
|
sourceIdentity: config.sourceIdentity,
|
|
614
|
+
logicalIdentity: config.logicalIdentity,
|
|
453
615
|
pluginName: config.pluginName,
|
|
454
616
|
scope,
|
|
455
617
|
cwd: context.cwd,
|
|
@@ -541,14 +703,38 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
541
703
|
signal.throwIfAborted();
|
|
542
704
|
const catalogGenerations = await loadCatalogGenerations();
|
|
543
705
|
signal.throwIfAborted();
|
|
706
|
+
const configStoreInventory = (await Promise.all(['user', 'project'].map(async (scope) => {
|
|
707
|
+
try {
|
|
708
|
+
return (await listNamespacedPluginConfigStoreIdentities({
|
|
709
|
+
cwd: context.cwd,
|
|
710
|
+
env: context.env,
|
|
711
|
+
scope,
|
|
712
|
+
})).map(({ pluginId, sourceId, pluginName }) => ({
|
|
713
|
+
pluginId, sourceId, pluginName, scope,
|
|
714
|
+
}));
|
|
715
|
+
}
|
|
716
|
+
catch {
|
|
717
|
+
await context.debugLogger.log({
|
|
718
|
+
type: 'tui:config-inventory-error',
|
|
719
|
+
level: 'debug',
|
|
720
|
+
target: 'debugLog',
|
|
721
|
+
message: 'TUI saved config inventory could not be read.',
|
|
722
|
+
data: { scope },
|
|
723
|
+
});
|
|
724
|
+
return [];
|
|
725
|
+
}
|
|
726
|
+
}))).flat();
|
|
727
|
+
signal.throwIfAborted();
|
|
544
728
|
const statusById = new Map(result.payload.catalog.sources.map((source) => [source.id, source]));
|
|
545
729
|
return {
|
|
546
730
|
cliChannel: packageInfo.version.includes('-') ? 'beta' : 'latest',
|
|
731
|
+
configuredSources: structuredClone(configured.sources),
|
|
547
732
|
payload: result.payload,
|
|
548
733
|
pluginSummaries: result.pluginSummaries,
|
|
549
734
|
targetRevisions: result.targetRevisions,
|
|
550
735
|
dependencyOverviews,
|
|
551
736
|
portablePluginIds,
|
|
737
|
+
configStoreInventory,
|
|
552
738
|
catalogGenerations,
|
|
553
739
|
sessionGenerationKeys: Object.fromEntries((catalogOperationContext?.generationSet.sources ?? [])
|
|
554
740
|
.map((source) => [source.sourceId, source.storeKey])),
|
|
@@ -580,7 +766,8 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
580
766
|
}
|
|
581
767
|
throw new TuiOperationBlockedError('operationReviewStale', '状态读取期间来源配置持续变化。请重试。');
|
|
582
768
|
};
|
|
583
|
-
const captureEvidence = async (intent, signal, preparation, operationInventory = createOperationInventoryReader(), freshCatalog = false, reusableCandidate) => {
|
|
769
|
+
const captureEvidence = async (intent, signal, preparation, operationInventory = createOperationInventoryReader(), freshCatalog = false, reusableCandidate, codexObservationSession, frozenBatchEvidence) => {
|
|
770
|
+
reviewedScriptTimeoutMs(intent);
|
|
584
771
|
if (intent.kind === 'configReset') {
|
|
585
772
|
const parsed = parsePluginId(intent.pluginId);
|
|
586
773
|
if (!parsed.sourceId || !parsed.pluginName) {
|
|
@@ -598,10 +785,16 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
598
785
|
if (target.kind === 'special') {
|
|
599
786
|
throw new TuiOperationBlockedError('configResetTargetUnsupported', '设置目标是特殊文件系统节点,不能自动重置。请手动移动后重试。');
|
|
600
787
|
}
|
|
601
|
-
|
|
788
|
+
const relevantTargets = sessionStatusResult
|
|
789
|
+
? configAffectedStatusTargets(sessionStatusResult.payload.targets, intent.pluginId, intent.scope)
|
|
790
|
+
: [];
|
|
791
|
+
const relevantRevisions = (sessionStatusResult?.targetRevisions ?? []).filter((revision) => relevantTargets.some((statusTarget) => statusTarget.platform === revision.platform
|
|
792
|
+
&& statusTarget.scope === revision.scope
|
|
793
|
+
&& statusTarget.pluginId === revision.pluginId));
|
|
794
|
+
let selected;
|
|
602
795
|
try {
|
|
603
796
|
const packageInfo = await readCliPackageInfo();
|
|
604
|
-
|
|
797
|
+
selected = await withResolvedCatalogPlugin({
|
|
605
798
|
selector: intent.pluginId,
|
|
606
799
|
cliVersion: packageInfo.version,
|
|
607
800
|
env: context.env,
|
|
@@ -609,16 +802,23 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
609
802
|
? { operationContext: sessionContextForPlugin(intent.pluginId) }
|
|
610
803
|
: {}),
|
|
611
804
|
...(signal ? { signal } : {}),
|
|
612
|
-
consume: async ({ plugin, source: resolvedSource }) =>
|
|
805
|
+
consume: async ({ plugin, source: resolvedSource }) => ({
|
|
806
|
+
source: sourceEvidenceForPlugin(resolvedSource, plugin.manifest.name),
|
|
807
|
+
impact: await analyzePluginConfigMutationImpact({
|
|
808
|
+
plugin,
|
|
809
|
+
scope: intent.scope,
|
|
810
|
+
cwd: context.cwd,
|
|
811
|
+
env: context.env,
|
|
812
|
+
visibleTargets: configImpactVisibleTargets(plugin.manifest.name, relevantTargets),
|
|
813
|
+
mutation: { kind: 'reset' },
|
|
814
|
+
}),
|
|
815
|
+
}),
|
|
613
816
|
});
|
|
614
817
|
}
|
|
615
818
|
catch {
|
|
616
|
-
|
|
819
|
+
selected = undefined;
|
|
617
820
|
}
|
|
618
821
|
signal?.throwIfAborted();
|
|
619
|
-
const relevantTargets = sessionStatusResult
|
|
620
|
-
? configAffectedStatusTargets(sessionStatusResult.payload.targets, intent.pluginId, intent.scope)
|
|
621
|
-
: [];
|
|
622
822
|
await preparation?.reporter.emit('evidence');
|
|
623
823
|
return {
|
|
624
824
|
catalog: sessionStatusResult ? {
|
|
@@ -628,11 +828,20 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
628
828
|
configDigest: 'config-reset-offline',
|
|
629
829
|
compositeDigest: 'config-reset-target',
|
|
630
830
|
},
|
|
631
|
-
...(
|
|
831
|
+
...(selected ? { source: selected.source } : {}),
|
|
832
|
+
...(sessionStatusResult ? {
|
|
833
|
+
targetFingerprint: statusTargetFingerprint(relevantTargets, relevantRevisions),
|
|
834
|
+
} : {}),
|
|
632
835
|
config: {
|
|
633
836
|
scope: intent.scope,
|
|
634
|
-
storeDigest: target.fingerprint,
|
|
635
|
-
|
|
837
|
+
storeDigest: selected?.impact.storeDigest ?? target.fingerprint,
|
|
838
|
+
impactState: selected?.impact.impactState ?? 'unknown',
|
|
839
|
+
...(selected?.impact.noEffectiveChange ? { noEffectiveChange: true } : {}),
|
|
840
|
+
affectedTargets: (selected?.impact.affectedTargets
|
|
841
|
+
?? relevantTargets).map(({ platform, scope }) => ({ platform, scope })),
|
|
842
|
+
...((selected?.impact.sharedNativeRenderTargets.length ?? 0) > 0
|
|
843
|
+
? { sharedNativeRenderTargets: selected.impact.sharedNativeRenderTargets }
|
|
844
|
+
: {}),
|
|
636
845
|
},
|
|
637
846
|
resetTarget: {
|
|
638
847
|
sourceId: parsed.sourceId,
|
|
@@ -684,12 +893,16 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
684
893
|
&& (preview.identityChanged || sourceFingerprintChanged);
|
|
685
894
|
if (preview.identityChanged)
|
|
686
895
|
sourceIdentityChangeImpact = {
|
|
687
|
-
impactSchemaVersion:
|
|
896
|
+
impactSchemaVersion: 3,
|
|
688
897
|
sourceId: preview.sourceId,
|
|
898
|
+
primaryChange: preview.references.primaryChange,
|
|
689
899
|
inventoryComplete: preview.references.inventoryComplete,
|
|
690
900
|
references: preview.references.references,
|
|
691
901
|
affectedReferences: preview.references.references,
|
|
692
|
-
changes: {
|
|
902
|
+
changes: {
|
|
903
|
+
added: [], removed: [], changed: [], newlyIncompatible: [],
|
|
904
|
+
dependencyChanged: [], platformSupportChanged: [],
|
|
905
|
+
},
|
|
693
906
|
errors: preview.references.errors,
|
|
694
907
|
};
|
|
695
908
|
if (!explicitSourceChange) {
|
|
@@ -828,7 +1041,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
828
1041
|
if (intent.action !== 'replaceDamaged' && !explicitSourceChange && candidateRelation === 'rollbackDetected') {
|
|
829
1042
|
throw new TuiOperationBlockedError('catalogRollbackDetected', '候选 Catalog 版本低于当前 Active。普通更新已阻止。');
|
|
830
1043
|
}
|
|
831
|
-
const impact =
|
|
1044
|
+
const impact = exactRepair ? undefined
|
|
832
1045
|
: sourceIdentityChangeImpact ?? await inspectCatalogSourceImpact({
|
|
833
1046
|
sourceId: intent.sourceId,
|
|
834
1047
|
cwd: context.cwd,
|
|
@@ -837,6 +1050,29 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
837
1050
|
mode: 'generation',
|
|
838
1051
|
candidateManifest: probe.manifest,
|
|
839
1052
|
});
|
|
1053
|
+
const primaryPreview = intent.setPrimaryAfterActivation
|
|
1054
|
+
? await preflightCatalogSourceMutation({
|
|
1055
|
+
request: { action: 'setPrimary', sourceId: intent.sourceId },
|
|
1056
|
+
cwd: context.cwd,
|
|
1057
|
+
env: context.env,
|
|
1058
|
+
})
|
|
1059
|
+
: undefined;
|
|
1060
|
+
if (primaryPreview && primaryPreview.configDigest !== config.digest) {
|
|
1061
|
+
throw operationReviewStale('准备主来源切换期间来源配置发生变化。');
|
|
1062
|
+
}
|
|
1063
|
+
const primaryImpact = primaryPreview ? {
|
|
1064
|
+
impactSchemaVersion: 3,
|
|
1065
|
+
sourceId: primaryPreview.sourceId,
|
|
1066
|
+
primaryChange: primaryPreview.references.primaryChange,
|
|
1067
|
+
inventoryComplete: primaryPreview.references.inventoryComplete,
|
|
1068
|
+
references: primaryPreview.references.references,
|
|
1069
|
+
affectedReferences: primaryPreview.references.references,
|
|
1070
|
+
changes: {
|
|
1071
|
+
added: [], removed: [], changed: [], newlyIncompatible: [],
|
|
1072
|
+
dependencyChanged: [], platformSupportChanged: [],
|
|
1073
|
+
},
|
|
1074
|
+
errors: primaryPreview.references.errors,
|
|
1075
|
+
} : undefined;
|
|
840
1076
|
return {
|
|
841
1077
|
catalog: {
|
|
842
1078
|
configDigest: config.digest,
|
|
@@ -857,6 +1093,11 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
857
1093
|
impactDigest: calculateCatalogSourceImpactDigest(impact),
|
|
858
1094
|
impactMode: sourceIdentityChangeImpact ? 'identityChange' : 'generation',
|
|
859
1095
|
} : {}),
|
|
1096
|
+
...(primaryPreview && primaryImpact ? {
|
|
1097
|
+
primaryImpact,
|
|
1098
|
+
primaryImpactDigest: primaryPreview.impactDigest,
|
|
1099
|
+
primaryConfigDigest: primaryPreview.configDigest,
|
|
1100
|
+
} : {}),
|
|
860
1101
|
configDigest: config.digest,
|
|
861
1102
|
...(proposedConfigDigest ? { proposedConfigDigest } : {}),
|
|
862
1103
|
...(proposedSource ? { proposedSource } : {}),
|
|
@@ -896,12 +1137,16 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
896
1137
|
referenceCount: preview.references.references.length,
|
|
897
1138
|
inventoryComplete: preview.references.inventoryComplete,
|
|
898
1139
|
impact: {
|
|
899
|
-
impactSchemaVersion:
|
|
1140
|
+
impactSchemaVersion: 3,
|
|
900
1141
|
sourceId: preview.sourceId,
|
|
1142
|
+
primaryChange: preview.references.primaryChange,
|
|
901
1143
|
inventoryComplete: preview.references.inventoryComplete,
|
|
902
1144
|
references: preview.references.references,
|
|
903
1145
|
affectedReferences: preview.references.references,
|
|
904
|
-
changes: {
|
|
1146
|
+
changes: {
|
|
1147
|
+
added: [], removed: [], changed: [], newlyIncompatible: [],
|
|
1148
|
+
dependencyChanged: [], platformSupportChanged: [],
|
|
1149
|
+
},
|
|
905
1150
|
errors: preview.references.errors,
|
|
906
1151
|
},
|
|
907
1152
|
},
|
|
@@ -912,10 +1157,95 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
912
1157
|
}
|
|
913
1158
|
return evidence;
|
|
914
1159
|
}
|
|
915
|
-
if (!pluginIntent(intent)) {
|
|
1160
|
+
if (!pluginIntent(intent) && intent.kind !== 'pluginWriteBatch') {
|
|
916
1161
|
throw new TuiOperationBlockedError('operationNotImplemented', '这个写操作尚未接入新 Controller。');
|
|
917
1162
|
}
|
|
918
1163
|
signal?.throwIfAborted();
|
|
1164
|
+
if (intent.kind === 'pluginWriteBatch') {
|
|
1165
|
+
await preparation?.reporter.emit('status');
|
|
1166
|
+
const selection = await resolveBatchGroups(intent, context.env, context.cwd, frozenBatchEvidence?.requestedPluginIds);
|
|
1167
|
+
signal?.throwIfAborted();
|
|
1168
|
+
const configSnapshot = await readCatalogSourcesConfigSnapshot(context.env);
|
|
1169
|
+
const groups = [];
|
|
1170
|
+
const ownsObservationSession = !codexObservationSession
|
|
1171
|
+
&& selection.groups.some((group) => {
|
|
1172
|
+
const reviewed = frozenBatchEvidence?.groups.find((candidate) => candidate.groupId === group.groupId);
|
|
1173
|
+
return reviewed?.executable !== false
|
|
1174
|
+
&& (group.platform === 'codex' || group.platform === 'both');
|
|
1175
|
+
});
|
|
1176
|
+
const observationSession = codexObservationSession ?? (ownsObservationSession
|
|
1177
|
+
? await createCodexNativeObservationSession({
|
|
1178
|
+
exactCwd: context.cwd,
|
|
1179
|
+
env: context.env,
|
|
1180
|
+
runner: context.nativeCliRunner,
|
|
1181
|
+
})
|
|
1182
|
+
: undefined);
|
|
1183
|
+
try {
|
|
1184
|
+
await preparation?.reporter.emit('catalog');
|
|
1185
|
+
for (const group of selection.groups) {
|
|
1186
|
+
signal?.throwIfAborted();
|
|
1187
|
+
const reviewed = frozenBatchEvidence?.groups.find((candidate) => candidate.groupId === group.groupId);
|
|
1188
|
+
if (reviewed?.executable === false) {
|
|
1189
|
+
groups.push({ ...group, preview: reviewed.preview, executable: false });
|
|
1190
|
+
continue;
|
|
1191
|
+
}
|
|
1192
|
+
let catalogOperation;
|
|
1193
|
+
try {
|
|
1194
|
+
catalogOperation = !freshCatalog && sessionCatalogOperationContext
|
|
1195
|
+
? selectCatalogOperationContext(sessionCatalogOperationContext, [group.sourceId])
|
|
1196
|
+
: await resolveCatalogOperationContext({
|
|
1197
|
+
sourceIds: [group.sourceId],
|
|
1198
|
+
env: context.env,
|
|
1199
|
+
...(!freshCatalog ? { validatedStoreEntries, validatingStoreEntries } : {}),
|
|
1200
|
+
...(signal ? { signal } : {}),
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
catch {
|
|
1204
|
+
catalogOperation = undefined;
|
|
1205
|
+
}
|
|
1206
|
+
const preview = await runBatchWriteGroup({
|
|
1207
|
+
intent,
|
|
1208
|
+
group,
|
|
1209
|
+
cwd: context.cwd,
|
|
1210
|
+
runtime: {
|
|
1211
|
+
...context,
|
|
1212
|
+
inventoryCatalogSourceReferences: operationInventory,
|
|
1213
|
+
expectedCatalogConfigDigest: configSnapshot.digest,
|
|
1214
|
+
...(catalogOperation ? {
|
|
1215
|
+
catalogOperationContext: catalogOperation,
|
|
1216
|
+
expectedGenerationSetDigest: catalogOperation.generationSetDigest,
|
|
1217
|
+
} : {}),
|
|
1218
|
+
previewOperationPlan: true,
|
|
1219
|
+
...(observationSession ? { codexObservationSession: observationSession } : {}),
|
|
1220
|
+
...(preparation ? {
|
|
1221
|
+
onPreviewStage: (stage) => stage === 'catalog' ? undefined : preparation.reporter.emit(stage),
|
|
1222
|
+
} : {}),
|
|
1223
|
+
},
|
|
1224
|
+
});
|
|
1225
|
+
groups.push({ ...group, preview, executable: preview.operationPlan !== undefined });
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
finally {
|
|
1229
|
+
if (ownsObservationSession)
|
|
1230
|
+
await observationSession?.dispose();
|
|
1231
|
+
}
|
|
1232
|
+
await preparation?.reporter.emit('evidence');
|
|
1233
|
+
signal?.throwIfAborted();
|
|
1234
|
+
const merged = mergeWriteCommandResults(groups.map((group) => group.preview));
|
|
1235
|
+
const evidence = {
|
|
1236
|
+
catalog: {
|
|
1237
|
+
configDigest: configSnapshot.digest,
|
|
1238
|
+
compositeDigest: sessionStatusResult?.payload.catalog.compositeDigest
|
|
1239
|
+
?? digest(groups.map((group) => [group.groupId, group.preview.operationPlan?.planFingerprint])),
|
|
1240
|
+
},
|
|
1241
|
+
requestedPluginIds: selection.requestedPluginIds,
|
|
1242
|
+
groups,
|
|
1243
|
+
...(merged.dependencyPlan ? { dependencyPlan: merged.dependencyPlan } : {}),
|
|
1244
|
+
...(merged.codexReconcilePlans ? { codexReconcilePlans: merged.codexReconcilePlans } : {}),
|
|
1245
|
+
...(merged.operationPlan ? { operationPlan: merged.operationPlan } : {}),
|
|
1246
|
+
};
|
|
1247
|
+
return evidence;
|
|
1248
|
+
}
|
|
919
1249
|
const packageInfo = await readCliPackageInfo();
|
|
920
1250
|
const offlineCleanupReason = intent.kind === 'pluginWrite'
|
|
921
1251
|
&& intent.action === 'cleanup'
|
|
@@ -988,12 +1318,14 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
988
1318
|
if (configSnapshot.digest !== sessionStatusResult.payload.catalog.configDigest) {
|
|
989
1319
|
throw operationReviewStale('准备设置确认期间来源配置发生变化。');
|
|
990
1320
|
}
|
|
1321
|
+
const relevantTargets = configAffectedStatusTargets(sessionStatusResult.payload.targets, intent.pluginId, intent.scope);
|
|
1322
|
+
const preparedCatalogOperation = catalogOperation;
|
|
991
1323
|
const selected = await withResolvedCatalogPlugin({
|
|
992
1324
|
selector: intent.pluginId,
|
|
993
1325
|
cliVersion: packageInfo.version,
|
|
994
1326
|
configSnapshot,
|
|
995
1327
|
env: context.env,
|
|
996
|
-
|
|
1328
|
+
operationContext: preparedCatalogOperation,
|
|
997
1329
|
...(signal ? { signal } : {}),
|
|
998
1330
|
consume: async ({ plugin, source }) => {
|
|
999
1331
|
if (!plugin.manifest.config) {
|
|
@@ -1011,30 +1343,56 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1011
1343
|
}
|
|
1012
1344
|
}
|
|
1013
1345
|
}
|
|
1346
|
+
const impact = intent.retryApply ? undefined : await analyzePluginConfigMutationImpact({
|
|
1347
|
+
plugin,
|
|
1348
|
+
scope: intent.scope,
|
|
1349
|
+
cwd: context.cwd,
|
|
1350
|
+
env: context.env,
|
|
1351
|
+
visibleTargets: configImpactVisibleTargets(plugin.manifest.name, relevantTargets),
|
|
1352
|
+
mutation: {
|
|
1353
|
+
kind: 'patch',
|
|
1354
|
+
updates: intent.updates,
|
|
1355
|
+
removeKeys: intent.removeKeys,
|
|
1356
|
+
},
|
|
1357
|
+
});
|
|
1358
|
+
const affectedTargets = intent.retryApply
|
|
1359
|
+
? configImpactVisibleTargets(plugin.manifest.name, relevantTargets)
|
|
1360
|
+
: impact.affectedTargets;
|
|
1014
1361
|
return {
|
|
1015
1362
|
pluginName: plugin.manifest.name,
|
|
1016
1363
|
source: sourceEvidenceForPlugin(source, plugin.manifest.name),
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1364
|
+
impact,
|
|
1365
|
+
preApplyAuthorization: configIntentRequestsApply(intent)
|
|
1366
|
+
? (await resolveConfigPreApplyAuthorization({
|
|
1367
|
+
plugin,
|
|
1368
|
+
scope: intent.scope,
|
|
1369
|
+
cwd: context.cwd,
|
|
1370
|
+
env: context.env,
|
|
1371
|
+
applyTargets: affectedTargets,
|
|
1372
|
+
nativeCliRunner: context.nativeCliRunner,
|
|
1373
|
+
rebuildRuntime: {
|
|
1374
|
+
catalogOperationContext: preparedCatalogOperation,
|
|
1375
|
+
expectedGenerationSetDigest: preparedCatalogOperation.generationSetDigest,
|
|
1376
|
+
inventoryCatalogSourceReferences: operationInventory,
|
|
1377
|
+
},
|
|
1378
|
+
})).targets
|
|
1022
1379
|
: [],
|
|
1380
|
+
sharedNativeRenderTargets: intent.retryApply
|
|
1381
|
+
? configRetrySharedNativeRenderTargets(plugin)
|
|
1382
|
+
: impact.sharedNativeRenderTargets,
|
|
1023
1383
|
};
|
|
1024
1384
|
},
|
|
1025
1385
|
});
|
|
1026
|
-
const
|
|
1027
|
-
sourceId: selected.source
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
: {}),
|
|
1386
|
+
const retryStore = intent.retryApply ? await readPluginConfigStore({
|
|
1387
|
+
sourceId: selected.source.sourceId,
|
|
1388
|
+
sourceIdentity: selected.source.sourceIdentity,
|
|
1389
|
+
logicalIdentity: selected.source.logicalIdentity,
|
|
1031
1390
|
pluginName: selected.pluginName,
|
|
1032
1391
|
scope: intent.scope,
|
|
1033
1392
|
cwd: context.cwd,
|
|
1034
1393
|
env: context.env,
|
|
1035
|
-
});
|
|
1394
|
+
}) : undefined;
|
|
1036
1395
|
signal?.throwIfAborted();
|
|
1037
|
-
const relevantTargets = configAffectedStatusTargets(sessionStatusResult.payload.targets, intent.pluginId, intent.scope);
|
|
1038
1396
|
const relevantRevisions = (sessionStatusResult.targetRevisions ?? []).filter((revision) => relevantTargets.some((target) => target.platform === revision.platform
|
|
1039
1397
|
&& target.scope === revision.scope
|
|
1040
1398
|
&& target.pluginId === revision.pluginId));
|
|
@@ -1050,8 +1408,15 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1050
1408
|
config: {
|
|
1051
1409
|
scope: intent.scope,
|
|
1052
1410
|
...(selected.source?.manifestDigest ? { schemaIdentity: selected.source.manifestDigest } : {}),
|
|
1053
|
-
storeDigest:
|
|
1054
|
-
|
|
1411
|
+
storeDigest: selected.impact?.storeDigest
|
|
1412
|
+
?? digest({ exists: retryStore?.exists, rawDigest: retryStore?.rawDigest }),
|
|
1413
|
+
impactState: selected.impact?.impactState ?? 'known',
|
|
1414
|
+
...(selected.impact?.noEffectiveChange ? { noEffectiveChange: true } : {}),
|
|
1415
|
+
affectedTargets: (selected.impact?.affectedTargets
|
|
1416
|
+
?? relevantTargets).map(({ platform, scope }) => ({ platform, scope })),
|
|
1417
|
+
...(selected.preApplyAuthorization.length > 0
|
|
1418
|
+
? { preApplyAuthorization: selected.preApplyAuthorization }
|
|
1419
|
+
: {}),
|
|
1055
1420
|
...(selected.sharedNativeRenderTargets.length > 0
|
|
1056
1421
|
? { sharedNativeRenderTargets: selected.sharedNativeRenderTargets }
|
|
1057
1422
|
: {}),
|
|
@@ -1099,6 +1464,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1099
1464
|
let dependencyPlan;
|
|
1100
1465
|
let codexReconcilePlans;
|
|
1101
1466
|
let operationPlan;
|
|
1467
|
+
let forceCleanupEvidence;
|
|
1102
1468
|
await preparation?.reporter.emit('catalog');
|
|
1103
1469
|
const offlineCleanupTarget = offlineCleanupReason && intent.kind === 'pluginWrite'
|
|
1104
1470
|
? status.payload.targets.find((target) => target.pluginId === intent.pluginId
|
|
@@ -1131,6 +1497,9 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1131
1497
|
throw operationReviewStale('离线清理现场证据已消失或无法验证。');
|
|
1132
1498
|
}
|
|
1133
1499
|
}
|
|
1500
|
+
const configVisibleTargets = intent.kind === 'configSave'
|
|
1501
|
+
? configAffectedStatusTargets(status.payload.targets, intent.pluginId, intent.scope)
|
|
1502
|
+
: [];
|
|
1134
1503
|
const selected = offlineCleanupTarget
|
|
1135
1504
|
? {
|
|
1136
1505
|
pluginName: offlineCleanupTarget.pluginName,
|
|
@@ -1165,19 +1534,54 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1165
1534
|
}
|
|
1166
1535
|
}
|
|
1167
1536
|
}
|
|
1537
|
+
const impact = intent.kind === 'configSave' && !intent.retryApply
|
|
1538
|
+
? await analyzePluginConfigMutationImpact({
|
|
1539
|
+
plugin,
|
|
1540
|
+
scope: intent.scope,
|
|
1541
|
+
cwd: context.cwd,
|
|
1542
|
+
env: context.env,
|
|
1543
|
+
visibleTargets: configImpactVisibleTargets(plugin.manifest.name, configVisibleTargets),
|
|
1544
|
+
mutation: {
|
|
1545
|
+
kind: 'patch',
|
|
1546
|
+
updates: intent.updates,
|
|
1547
|
+
removeKeys: intent.removeKeys,
|
|
1548
|
+
},
|
|
1549
|
+
})
|
|
1550
|
+
: undefined;
|
|
1168
1551
|
return {
|
|
1169
1552
|
pluginName: plugin.manifest.name,
|
|
1170
1553
|
source: sourceEvidenceForPlugin(source, plugin.manifest.name),
|
|
1554
|
+
impact,
|
|
1555
|
+
preApplyAuthorization: intent.kind === 'configSave'
|
|
1556
|
+
&& configIntentRequestsApply(intent)
|
|
1557
|
+
? (await resolveConfigPreApplyAuthorization({
|
|
1558
|
+
plugin,
|
|
1559
|
+
scope: intent.scope,
|
|
1560
|
+
cwd: context.cwd,
|
|
1561
|
+
env: context.env,
|
|
1562
|
+
applyTargets: intent.retryApply
|
|
1563
|
+
? configImpactVisibleTargets(plugin.manifest.name, configVisibleTargets)
|
|
1564
|
+
: impact.affectedTargets,
|
|
1565
|
+
nativeCliRunner: context.nativeCliRunner,
|
|
1566
|
+
rebuildRuntime: {
|
|
1567
|
+
...(catalogOperation ? { catalogOperationContext: catalogOperation } : {}),
|
|
1568
|
+
...(catalogOperation?.generationSetDigest
|
|
1569
|
+
? { expectedGenerationSetDigest: catalogOperation.generationSetDigest }
|
|
1570
|
+
: {}),
|
|
1571
|
+
inventoryCatalogSourceReferences: operationInventory,
|
|
1572
|
+
},
|
|
1573
|
+
})).targets
|
|
1574
|
+
: [],
|
|
1171
1575
|
sharedNativeRenderTargets: intent.kind === 'configSave'
|
|
1172
|
-
?
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
])
|
|
1576
|
+
? intent.retryApply
|
|
1577
|
+
? configRetrySharedNativeRenderTargets(plugin)
|
|
1578
|
+
: impact.sharedNativeRenderTargets
|
|
1176
1579
|
: [],
|
|
1177
1580
|
};
|
|
1178
1581
|
},
|
|
1179
1582
|
});
|
|
1180
1583
|
let codexManager;
|
|
1584
|
+
let resolvedCodexManager;
|
|
1181
1585
|
const hasDeclaredDependencies = (status.pluginSummaries.find((summary) => summary.pluginId === intent.pluginId)?.dependencyTotalCount ?? 0) > 0;
|
|
1182
1586
|
if (intent.kind === 'pluginWrite') {
|
|
1183
1587
|
const command = {
|
|
@@ -1192,6 +1596,9 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1192
1596
|
cwd: context.cwd,
|
|
1193
1597
|
platform: intent.platform,
|
|
1194
1598
|
scope: intent.scope,
|
|
1599
|
+
...(reviewedScriptTimeoutMs(intent) === undefined
|
|
1600
|
+
? {}
|
|
1601
|
+
: { scriptTimeoutMs: reviewedScriptTimeoutMs(intent) }),
|
|
1195
1602
|
...(intent.action === 'install' && intent.dependencyScopeOverrides
|
|
1196
1603
|
? { dependencyScopeOverrides: intent.dependencyScopeOverrides }
|
|
1197
1604
|
: {}),
|
|
@@ -1205,6 +1612,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1205
1612
|
expectedGenerationSetDigest: catalogOperation.generationSetDigest,
|
|
1206
1613
|
} : {}),
|
|
1207
1614
|
previewOperationPlan: true,
|
|
1615
|
+
...(codexObservationSession ? { codexObservationSession } : {}),
|
|
1208
1616
|
...(preparation ? {
|
|
1209
1617
|
onPreviewStage: (stage) => stage === 'catalog' ? undefined : preparation.reporter.emit(stage),
|
|
1210
1618
|
} : {}),
|
|
@@ -1212,6 +1620,17 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1212
1620
|
signal?.throwIfAborted();
|
|
1213
1621
|
codexReconcilePlans = preview?.codexReconcilePlans;
|
|
1214
1622
|
operationPlan = preview?.operationPlan;
|
|
1623
|
+
if (intent.action === 'cleanup' && intent.force === true) {
|
|
1624
|
+
const candidates = preview?.offlineCleanupPlans?.filter((candidate) => candidate.forceExclusive === true
|
|
1625
|
+
&& candidate.pluginId === intent.pluginId
|
|
1626
|
+
&& candidate.platform === intent.platform
|
|
1627
|
+
&& candidate.scope === intent.scope
|
|
1628
|
+
&& candidate.plan.actions.length > 0) ?? [];
|
|
1629
|
+
if (candidates.length !== 1) {
|
|
1630
|
+
throw new TuiOperationBlockedError('forceCleanupPathUnavailable', '没有唯一且可验证的精确清理目标。');
|
|
1631
|
+
}
|
|
1632
|
+
[forceCleanupEvidence] = candidates;
|
|
1633
|
+
}
|
|
1215
1634
|
if (hasDeclaredDependencies
|
|
1216
1635
|
&& (intent.action === 'install'
|
|
1217
1636
|
|| intent.action === 'refreshAndSync'
|
|
@@ -1234,6 +1653,9 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1234
1653
|
throw new TuiOperationBlockedError(managerPreview.code, `${managerPreview.code}: ${message}`);
|
|
1235
1654
|
}
|
|
1236
1655
|
if (managerPreview) {
|
|
1656
|
+
if (managerPreview.state === 'system' || managerPreview.state === 'cached') {
|
|
1657
|
+
resolvedCodexManager = managerPreview.manager;
|
|
1658
|
+
}
|
|
1237
1659
|
codexManager = {
|
|
1238
1660
|
state: managerPreview.state,
|
|
1239
1661
|
packageName: MANAGED_CODEX_PACKAGE_NAME,
|
|
@@ -1246,7 +1668,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1246
1668
|
await preparation?.reporter.emit('evidence');
|
|
1247
1669
|
signal?.throwIfAborted();
|
|
1248
1670
|
const evidenceTargets = intent.kind === 'configSave'
|
|
1249
|
-
?
|
|
1671
|
+
? configVisibleTargets
|
|
1250
1672
|
: status.payload.targets;
|
|
1251
1673
|
const evidenceRevisions = intent.kind === 'configSave'
|
|
1252
1674
|
? (status.targetRevisions ?? []).filter((revision) => evidenceTargets.some((target) => target.platform === revision.platform
|
|
@@ -1263,6 +1685,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1263
1685
|
},
|
|
1264
1686
|
source: selected.source,
|
|
1265
1687
|
...(offlineCleanup ? { offlineCleanup } : {}),
|
|
1688
|
+
...(forceCleanupEvidence ? { offlineCleanup: forceCleanupEvidence } : {}),
|
|
1266
1689
|
...(dependencyPlan ? { dependencyPlan } : {}),
|
|
1267
1690
|
...(codexReconcilePlans ? { codexReconcilePlans } : {}),
|
|
1268
1691
|
...(operationPlan ? { operationPlan } : {}),
|
|
@@ -1270,30 +1693,53 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1270
1693
|
targetFingerprint: statusTargetFingerprint(evidenceTargets, evidenceRevisions),
|
|
1271
1694
|
};
|
|
1272
1695
|
if (intent.kind === 'configSave') {
|
|
1273
|
-
const
|
|
1696
|
+
const impact = 'impact' in selected ? selected.impact : undefined;
|
|
1697
|
+
const retryStore = intent.retryApply ? await readPluginConfigStore({
|
|
1274
1698
|
sourceId: selected.source.sourceId,
|
|
1275
1699
|
sourceIdentity: selected.source.sourceIdentity,
|
|
1700
|
+
...('logicalIdentity' in selected.source
|
|
1701
|
+
? { logicalIdentity: selected.source.logicalIdentity }
|
|
1702
|
+
: {}),
|
|
1276
1703
|
pluginName: selected.pluginName,
|
|
1277
1704
|
scope: intent.scope,
|
|
1278
1705
|
cwd: context.cwd,
|
|
1279
1706
|
env: context.env,
|
|
1280
|
-
});
|
|
1707
|
+
}) : undefined;
|
|
1281
1708
|
signal?.throwIfAborted();
|
|
1282
1709
|
evidence.config = {
|
|
1283
1710
|
scope: intent.scope,
|
|
1284
1711
|
...('manifestDigest' in selected.source
|
|
1285
1712
|
? { schemaIdentity: selected.source.manifestDigest }
|
|
1286
1713
|
: {}),
|
|
1287
|
-
storeDigest:
|
|
1288
|
-
|
|
1714
|
+
storeDigest: impact?.storeDigest
|
|
1715
|
+
?? digest({ exists: retryStore?.exists, rawDigest: retryStore?.rawDigest }),
|
|
1716
|
+
impactState: impact?.impactState ?? 'known',
|
|
1717
|
+
...(impact?.noEffectiveChange ? { noEffectiveChange: true } : {}),
|
|
1718
|
+
affectedTargets: (impact?.affectedTargets
|
|
1719
|
+
?? evidenceTargets).map(({ platform, scope }) => ({ platform, scope })),
|
|
1720
|
+
...(intent.scope === 'project' ? {
|
|
1721
|
+
shareability: await inspectConfigShareability({
|
|
1722
|
+
sourceId: selected.source.sourceId,
|
|
1723
|
+
pluginName: selected.pluginName,
|
|
1724
|
+
scope: intent.scope,
|
|
1725
|
+
cwd: context.cwd,
|
|
1726
|
+
env: context.env,
|
|
1727
|
+
}),
|
|
1728
|
+
} : {}),
|
|
1289
1729
|
...('sharedNativeRenderTargets' in selected
|
|
1290
1730
|
&& selected.sharedNativeRenderTargets.length > 0
|
|
1291
1731
|
? { sharedNativeRenderTargets: selected.sharedNativeRenderTargets }
|
|
1292
1732
|
: {}),
|
|
1733
|
+
...('preApplyAuthorization' in selected
|
|
1734
|
+
&& selected.preApplyAuthorization.length > 0
|
|
1735
|
+
? { preApplyAuthorization: selected.preApplyAuthorization }
|
|
1736
|
+
: {}),
|
|
1293
1737
|
};
|
|
1294
1738
|
}
|
|
1295
1739
|
if (catalogOperation)
|
|
1296
1740
|
catalogOperationByEvidence.set(evidence, catalogOperation);
|
|
1741
|
+
if (resolvedCodexManager)
|
|
1742
|
+
codexManagerByEvidence.set(evidence, resolvedCodexManager);
|
|
1297
1743
|
return evidence;
|
|
1298
1744
|
};
|
|
1299
1745
|
const dependencies = {
|
|
@@ -1501,6 +1947,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1501
1947
|
const stores = await readConfigStoresForTui({
|
|
1502
1948
|
sourceId: plugin.sourceId,
|
|
1503
1949
|
sourceIdentity: plugin.sourceIdentity,
|
|
1950
|
+
logicalIdentity: plugin.catalogLogicalIdentity,
|
|
1504
1951
|
pluginName: plugin.manifest.name,
|
|
1505
1952
|
schema: plugin.manifest.config.fields,
|
|
1506
1953
|
scope: layer.scope,
|
|
@@ -1535,6 +1982,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1535
1982
|
const effectiveRaw = await resolveEffectivePluginConfig({
|
|
1536
1983
|
sourceId: plugin.sourceId,
|
|
1537
1984
|
sourceIdentity: plugin.sourceIdentity,
|
|
1985
|
+
logicalIdentity: plugin.catalogLogicalIdentity,
|
|
1538
1986
|
pluginName: plugin.manifest.name,
|
|
1539
1987
|
manifest: plugin.manifest,
|
|
1540
1988
|
targetScope: layer.scope === 'user' ? 'user' : 'project',
|
|
@@ -1569,9 +2017,10 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1569
2017
|
throw new TuiOperationBlockedError('invalidPluginId', '设置目标必须使用 canonical pluginId。');
|
|
1570
2018
|
}
|
|
1571
2019
|
let sourceIdentity;
|
|
2020
|
+
let logicalIdentity;
|
|
1572
2021
|
try {
|
|
1573
2022
|
const packageInfo = await readCliPackageInfo();
|
|
1574
|
-
|
|
2023
|
+
const source = await withResolvedCatalogPlugin({
|
|
1575
2024
|
selector: pluginId,
|
|
1576
2025
|
cliVersion: packageInfo.version,
|
|
1577
2026
|
env: context.env,
|
|
@@ -1579,11 +2028,17 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1579
2028
|
...(sessionContextForPlugin(pluginId)
|
|
1580
2029
|
? { operationContext: sessionContextForPlugin(pluginId) }
|
|
1581
2030
|
: {}),
|
|
1582
|
-
consume: async ({ source }) =>
|
|
2031
|
+
consume: async ({ source }) => ({
|
|
2032
|
+
sourceIdentity: source.sourceIdentity,
|
|
2033
|
+
logicalIdentity: source.logicalIdentity,
|
|
2034
|
+
}),
|
|
1583
2035
|
});
|
|
2036
|
+
sourceIdentity = source.sourceIdentity;
|
|
2037
|
+
logicalIdentity = source.logicalIdentity;
|
|
1584
2038
|
}
|
|
1585
2039
|
catch {
|
|
1586
2040
|
sourceIdentity = undefined;
|
|
2041
|
+
logicalIdentity = undefined;
|
|
1587
2042
|
}
|
|
1588
2043
|
signal.throwIfAborted();
|
|
1589
2044
|
const target = await inspectPluginConfigResetTarget({
|
|
@@ -1598,6 +2053,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1598
2053
|
const store = await readPluginConfigStore({
|
|
1599
2054
|
sourceId: parsed.sourceId,
|
|
1600
2055
|
...(sourceIdentity ? { sourceIdentity } : {}),
|
|
2056
|
+
...(logicalIdentity ? { logicalIdentity } : {}),
|
|
1601
2057
|
pluginName: parsed.pluginName,
|
|
1602
2058
|
scope: layer.scope,
|
|
1603
2059
|
cwd: context.cwd,
|
|
@@ -1645,13 +2101,21 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1645
2101
|
expectedConfigDigest: expected.configDigest,
|
|
1646
2102
|
};
|
|
1647
2103
|
if (intent.sourceMutation.action === 'add') {
|
|
1648
|
-
await addCatalogSourceCommand({
|
|
2104
|
+
await addCatalogSourceCommand({
|
|
2105
|
+
...common,
|
|
2106
|
+
source: intent.sourceMutation.source,
|
|
2107
|
+
expectedProposedConfigDigest: expected.proposedConfigDigest,
|
|
2108
|
+
expectedImpactDigest: expected.impactDigest,
|
|
2109
|
+
requireImpactConfirmation: true,
|
|
2110
|
+
confirmImpact: true,
|
|
2111
|
+
});
|
|
1649
2112
|
}
|
|
1650
2113
|
else {
|
|
1651
2114
|
await updateCatalogSourceCommand({
|
|
1652
2115
|
...common,
|
|
1653
2116
|
sourceId: intent.sourceId,
|
|
1654
2117
|
update: intent.sourceMutation.update,
|
|
2118
|
+
expectedProposedConfigDigest: expected.proposedConfigDigest,
|
|
1655
2119
|
expectedImpactDigest: expected.impactDigest,
|
|
1656
2120
|
requireIdentityChangeConfirmation: true,
|
|
1657
2121
|
confirmIdentityChange: true,
|
|
@@ -1751,6 +2215,10 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1751
2215
|
sourceId: intent.sourceId,
|
|
1752
2216
|
cwd: context.cwd,
|
|
1753
2217
|
env: context.env,
|
|
2218
|
+
expectedConfigDigest: expected.primaryConfigDigest,
|
|
2219
|
+
expectedImpactDigest: expected.primaryImpactDigest,
|
|
2220
|
+
requireImpactConfirmation: true,
|
|
2221
|
+
confirmImpact: true,
|
|
1754
2222
|
});
|
|
1755
2223
|
primaryChanged = true;
|
|
1756
2224
|
}
|
|
@@ -1761,7 +2229,10 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1761
2229
|
configSaved,
|
|
1762
2230
|
generation,
|
|
1763
2231
|
activeAvailable: true,
|
|
1764
|
-
errorCode: error
|
|
2232
|
+
errorCode: typeof error === 'object' && error !== null
|
|
2233
|
+
&& 'code' in error && typeof error.code === 'string'
|
|
2234
|
+
? error.code
|
|
2235
|
+
: error instanceof Error ? error.name : 'catalogSourcePrimaryFailed',
|
|
1765
2236
|
};
|
|
1766
2237
|
}
|
|
1767
2238
|
}
|
|
@@ -1827,11 +2298,18 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1827
2298
|
cwd: context.cwd,
|
|
1828
2299
|
env: context.env,
|
|
1829
2300
|
expectedConfigDigest: expectedEvidence.sourceWrite?.configDigest,
|
|
2301
|
+
expectedProposedConfigDigest: expectedEvidence.sourceWrite?.proposedConfigDigest,
|
|
1830
2302
|
expectedImpactDigest: expectedEvidence.sourceWrite?.impactDigest,
|
|
1831
2303
|
runtime,
|
|
1832
2304
|
};
|
|
1833
2305
|
if (intent.action === 'add' && intent.source) {
|
|
1834
|
-
return addCatalogSourceCommand({
|
|
2306
|
+
return addCatalogSourceCommand({
|
|
2307
|
+
...common,
|
|
2308
|
+
source: intent.source,
|
|
2309
|
+
cliVersion: packageInfo.version,
|
|
2310
|
+
requireImpactConfirmation: true,
|
|
2311
|
+
confirmImpact: true,
|
|
2312
|
+
});
|
|
1835
2313
|
}
|
|
1836
2314
|
if (intent.action === 'update' && intent.update) {
|
|
1837
2315
|
return updateCatalogSourceCommand({
|
|
@@ -1844,7 +2322,12 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1844
2322
|
});
|
|
1845
2323
|
}
|
|
1846
2324
|
if (intent.action === 'setPrimary') {
|
|
1847
|
-
return setPrimaryCatalogSourceCommand({
|
|
2325
|
+
return setPrimaryCatalogSourceCommand({
|
|
2326
|
+
...common,
|
|
2327
|
+
sourceId: intent.sourceId,
|
|
2328
|
+
requireImpactConfirmation: true,
|
|
2329
|
+
confirmImpact: true,
|
|
2330
|
+
});
|
|
1848
2331
|
}
|
|
1849
2332
|
if (intent.action === 'remove') {
|
|
1850
2333
|
return removeCatalogSourceCommand({
|
|
@@ -1856,12 +2339,165 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1856
2339
|
}
|
|
1857
2340
|
throw new TuiOperationBlockedError('invalidSourceMutation', '来源操作缺少候选输入。');
|
|
1858
2341
|
}
|
|
2342
|
+
const codexObservationSession = intent.kind === 'pluginWrite'
|
|
2343
|
+
|| intent.kind === 'pluginWriteBatch'
|
|
2344
|
+
? await createCodexNativeObservationSession({
|
|
2345
|
+
exactCwd: context.cwd,
|
|
2346
|
+
env: context.env,
|
|
2347
|
+
runner: context.nativeCliRunner,
|
|
2348
|
+
manager: codexManagerByEvidence.get(expectedEvidence),
|
|
2349
|
+
})
|
|
2350
|
+
: undefined;
|
|
1859
2351
|
return withAwHomeMutationLock({
|
|
1860
2352
|
env: context.env,
|
|
1861
2353
|
action: async (awHomeMutationToken) => {
|
|
1862
2354
|
await tuiControllerRuntimeTestHooks?.beforeMutationEvidenceCapture?.();
|
|
1863
2355
|
const operationInventory = createOperationInventoryReader();
|
|
1864
|
-
const currentEvidence = await captureEvidence(intent, undefined, undefined, operationInventory, true
|
|
2356
|
+
const currentEvidence = await captureEvidence(intent, undefined, undefined, operationInventory, true, undefined, codexObservationSession, intent.kind === 'pluginWriteBatch'
|
|
2357
|
+
? expectedEvidence
|
|
2358
|
+
: undefined);
|
|
2359
|
+
if (intent.kind === 'pluginWriteBatch') {
|
|
2360
|
+
const expectedBatch = expectedEvidence;
|
|
2361
|
+
const currentBatch = currentEvidence;
|
|
2362
|
+
const reviewedGroups = expectedBatch.groups.map((group) => ({
|
|
2363
|
+
groupId: group.groupId,
|
|
2364
|
+
sourceId: group.sourceId,
|
|
2365
|
+
platform: group.platform,
|
|
2366
|
+
scope: group.scope,
|
|
2367
|
+
requestedPluginIds: group.requestedPluginIds,
|
|
2368
|
+
executable: group.executable,
|
|
2369
|
+
planFingerprint: group.preview.operationPlan
|
|
2370
|
+
? createBatchIntentCompatiblePlanFingerprint(group.preview.operationPlan)
|
|
2371
|
+
: undefined,
|
|
2372
|
+
}));
|
|
2373
|
+
const currentGroups = currentBatch.groups.map((group) => ({
|
|
2374
|
+
groupId: group.groupId,
|
|
2375
|
+
sourceId: group.sourceId,
|
|
2376
|
+
platform: group.platform,
|
|
2377
|
+
scope: group.scope,
|
|
2378
|
+
requestedPluginIds: group.requestedPluginIds,
|
|
2379
|
+
executable: expectedBatch.groups.find((reviewed) => reviewed.groupId === group.groupId)
|
|
2380
|
+
?.executable === false ? false : group.executable,
|
|
2381
|
+
planFingerprint: expectedBatch.groups.find((reviewed) => reviewed.groupId === group.groupId)
|
|
2382
|
+
?.executable === false
|
|
2383
|
+
? undefined
|
|
2384
|
+
: group.preview.operationPlan
|
|
2385
|
+
? createBatchIntentCompatiblePlanFingerprint(group.preview.operationPlan)
|
|
2386
|
+
: undefined,
|
|
2387
|
+
}));
|
|
2388
|
+
if (expectedBatch.catalog.configDigest !== currentBatch.catalog.configDigest
|
|
2389
|
+
|| JSON.stringify(expectedBatch.requestedPluginIds)
|
|
2390
|
+
!== JSON.stringify(currentBatch.requestedPluginIds)
|
|
2391
|
+
|| JSON.stringify(reviewedGroups) !== JSON.stringify(currentGroups)) {
|
|
2392
|
+
throw operationReviewStale('确认后批量目标或写入计划发生变化。');
|
|
2393
|
+
}
|
|
2394
|
+
await tuiControllerRuntimeTestHooks?.afterMutationEvidenceCapture?.();
|
|
2395
|
+
const groupResults = [];
|
|
2396
|
+
const completedTargetKeys = new Set();
|
|
2397
|
+
let executedGroupCount = 0;
|
|
2398
|
+
const appendStoppedGroups = (startIndex, staleMessage) => {
|
|
2399
|
+
for (const [offset, stopped] of expectedBatch.groups.slice(startIndex).entries()) {
|
|
2400
|
+
groupResults.push({
|
|
2401
|
+
groupId: stopped.groupId,
|
|
2402
|
+
sourceId: stopped.sourceId,
|
|
2403
|
+
platform: stopped.platform,
|
|
2404
|
+
scope: stopped.scope,
|
|
2405
|
+
requestedPluginIds: stopped.requestedPluginIds,
|
|
2406
|
+
result: !stopped.executable ? stopped.preview : failedWriteCommandResult(intent.action, stopped.requestedPluginIds, { cwd: context.cwd, platform: stopped.platform, scope: stopped.scope }, offset === 0
|
|
2407
|
+
? new TuiOperationBlockedError('operationReviewStale', staleMessage)
|
|
2408
|
+
: new TuiOperationBlockedError('batchNotStarted', '前一个批量组的写入计划已变化,因此这个组没有开始。')),
|
|
2409
|
+
});
|
|
2410
|
+
}
|
|
2411
|
+
};
|
|
2412
|
+
for (const [groupIndex, reviewed] of expectedBatch.groups.entries()) {
|
|
2413
|
+
const current = currentBatch.groups.find((group) => group.groupId === reviewed.groupId);
|
|
2414
|
+
if (!reviewed.executable) {
|
|
2415
|
+
groupResults.push({
|
|
2416
|
+
groupId: reviewed.groupId,
|
|
2417
|
+
sourceId: reviewed.sourceId,
|
|
2418
|
+
platform: reviewed.platform,
|
|
2419
|
+
scope: reviewed.scope,
|
|
2420
|
+
requestedPluginIds: reviewed.requestedPluginIds,
|
|
2421
|
+
result: reviewed.preview,
|
|
2422
|
+
});
|
|
2423
|
+
continue;
|
|
2424
|
+
}
|
|
2425
|
+
const groupInventory = groupResults.length === 0
|
|
2426
|
+
? operationInventory
|
|
2427
|
+
: createOperationInventoryReader();
|
|
2428
|
+
let executionPreview = current.preview;
|
|
2429
|
+
if (completedTargetKeys.size > 0) {
|
|
2430
|
+
executionPreview = await runBatchWriteGroup({
|
|
2431
|
+
intent,
|
|
2432
|
+
group: current,
|
|
2433
|
+
cwd: context.cwd,
|
|
2434
|
+
runtime: {
|
|
2435
|
+
...context,
|
|
2436
|
+
awHomeMutationToken,
|
|
2437
|
+
inventoryCatalogSourceReferences: groupInventory,
|
|
2438
|
+
expectedCatalogConfigDigest: expectedBatch.catalog.configDigest,
|
|
2439
|
+
previewOperationPlan: true,
|
|
2440
|
+
...(codexObservationSession ? { codexObservationSession } : {}),
|
|
2441
|
+
},
|
|
2442
|
+
});
|
|
2443
|
+
if (!reviewed.preview.operationPlan || !executionPreview.operationPlan
|
|
2444
|
+
|| createBatchIntentCompatiblePlanFingerprint(reviewed.preview.operationPlan, completedTargetKeys) !== createBatchIntentCompatiblePlanFingerprint(executionPreview.operationPlan, completedTargetKeys)) {
|
|
2445
|
+
appendStoppedGroups(groupIndex, '前序批量结果改变了这个组的实际写入计划。');
|
|
2446
|
+
break;
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
const requiresManagedCodex = reviewed.preview.codexManagerPreview?.state === 'requires-install';
|
|
2450
|
+
const result = await runBatchWriteGroup({
|
|
2451
|
+
intent,
|
|
2452
|
+
group: current,
|
|
2453
|
+
cwd: context.cwd,
|
|
2454
|
+
runtime: {
|
|
2455
|
+
...context,
|
|
2456
|
+
awHomeMutationToken,
|
|
2457
|
+
preApplyConfirmed: true,
|
|
2458
|
+
inventoryCatalogSourceReferences: groupInventory,
|
|
2459
|
+
expectedCatalogConfigDigest: expectedBatch.catalog.configDigest,
|
|
2460
|
+
...(executionPreview.operationPlan ? {
|
|
2461
|
+
expectedPlanFingerprint: executionPreview.operationPlan.planFingerprint,
|
|
2462
|
+
} : {}),
|
|
2463
|
+
...(requiresManagedCodex ? {
|
|
2464
|
+
managedCodexAuthorizer: async () => true,
|
|
2465
|
+
} : {}),
|
|
2466
|
+
...(codexObservationSession ? { codexObservationSession } : {}),
|
|
2467
|
+
},
|
|
2468
|
+
});
|
|
2469
|
+
if (writeReviewIsStale(result)) {
|
|
2470
|
+
if (executedGroupCount === 0)
|
|
2471
|
+
throwIfWriteReviewStale(result);
|
|
2472
|
+
appendStoppedGroups(groupIndex, '这个组的实际写入计划发生变化。');
|
|
2473
|
+
break;
|
|
2474
|
+
}
|
|
2475
|
+
executedGroupCount += 1;
|
|
2476
|
+
for (const target of result.targetResults) {
|
|
2477
|
+
if (target.state === 'completed') {
|
|
2478
|
+
completedTargetKeys.add([
|
|
2479
|
+
target.target.pluginId,
|
|
2480
|
+
target.target.platform,
|
|
2481
|
+
target.target.scope,
|
|
2482
|
+
].join('\0'));
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
groupResults.push({
|
|
2486
|
+
groupId: reviewed.groupId,
|
|
2487
|
+
sourceId: reviewed.sourceId,
|
|
2488
|
+
platform: reviewed.platform,
|
|
2489
|
+
scope: reviewed.scope,
|
|
2490
|
+
requestedPluginIds: reviewed.requestedPluginIds,
|
|
2491
|
+
result,
|
|
2492
|
+
});
|
|
2493
|
+
}
|
|
2494
|
+
const merged = mergeWriteCommandResults(groupResults.map((group) => group.result));
|
|
2495
|
+
return {
|
|
2496
|
+
...merged,
|
|
2497
|
+
requestedPluginIds: expectedBatch.requestedPluginIds,
|
|
2498
|
+
groupResults,
|
|
2499
|
+
};
|
|
2500
|
+
}
|
|
1865
2501
|
if (intent.kind !== 'pluginWrite'
|
|
1866
2502
|
&& !operationEvidenceMatches(expectedEvidence, currentEvidence)) {
|
|
1867
2503
|
throw new TuiOperationBlockedError('operationReviewStale', '确认后状态发生变化。');
|
|
@@ -1877,6 +2513,9 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1877
2513
|
cwd: context.cwd,
|
|
1878
2514
|
platform: intent.platform,
|
|
1879
2515
|
scope: intent.scope,
|
|
2516
|
+
...(reviewedScriptTimeoutMs(intent) === undefined
|
|
2517
|
+
? {}
|
|
2518
|
+
: { scriptTimeoutMs: reviewedScriptTimeoutMs(intent) }),
|
|
1880
2519
|
...(intent.action === 'install' && intent.dependencyScopeOverrides
|
|
1881
2520
|
? { dependencyScopeOverrides: intent.dependencyScopeOverrides }
|
|
1882
2521
|
: {}),
|
|
@@ -1895,12 +2534,21 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1895
2534
|
}[intent.action];
|
|
1896
2535
|
const currentSource = currentEvidence.source;
|
|
1897
2536
|
const offlineCleanup = currentEvidence.offlineCleanup;
|
|
2537
|
+
const reviewedOfflineCleanup = expectedEvidence.offlineCleanup;
|
|
2538
|
+
if ((offlineCleanup || reviewedOfflineCleanup)
|
|
2539
|
+
&& (!offlineCleanup
|
|
2540
|
+
|| !reviewedOfflineCleanup
|
|
2541
|
+
|| !offlineCleanupEvidenceMatches(reviewedOfflineCleanup, offlineCleanup))) {
|
|
2542
|
+
throw new TuiOperationBlockedError('operationReviewStale', '确认后离线清理证据发生变化。');
|
|
2543
|
+
}
|
|
1898
2544
|
if (!offlineCleanup && (!expectedEvidence.source || !currentSource)) {
|
|
1899
2545
|
throw new TuiOperationBlockedError('operationReviewStale', '确认信息缺少来源身份。');
|
|
1900
2546
|
}
|
|
1901
2547
|
const result = await command([intent.pluginId], options, {
|
|
1902
2548
|
...context,
|
|
2549
|
+
...(codexObservationSession ? { codexObservationSession } : {}),
|
|
1903
2550
|
awHomeMutationToken,
|
|
2551
|
+
preApplyConfirmed: true,
|
|
1904
2552
|
inventoryCatalogSourceReferences: operationInventory,
|
|
1905
2553
|
...(expectedEvidence.operationPlan
|
|
1906
2554
|
? { expectedPlanFingerprint: expectedEvidence.operationPlan.planFingerprint }
|
|
@@ -1913,14 +2561,18 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1913
2561
|
...(expectedEvidence.codexManager?.state === 'requires-install'
|
|
1914
2562
|
? { managedCodexAuthorizer: async () => true }
|
|
1915
2563
|
: {}),
|
|
1916
|
-
...(
|
|
1917
|
-
? { expectedOfflineCleanupEvidence:
|
|
2564
|
+
...(reviewedOfflineCleanup
|
|
2565
|
+
? { expectedOfflineCleanupEvidence: reviewedOfflineCleanup }
|
|
1918
2566
|
: { reviewPreflight: (actual) => assertSourceEvidenceMatches(currentSource, actual) }),
|
|
1919
2567
|
});
|
|
1920
2568
|
throwIfWriteReviewStale(result);
|
|
1921
2569
|
return result;
|
|
1922
2570
|
}
|
|
1923
2571
|
if (intent.kind === 'configSave' || intent.kind === 'configReset') {
|
|
2572
|
+
const operationRebuildResults = [];
|
|
2573
|
+
const operationDiagnosticSink = (results) => {
|
|
2574
|
+
operationRebuildResults.push(...structuredClone(results));
|
|
2575
|
+
};
|
|
1924
2576
|
const currentSource = currentEvidence.source;
|
|
1925
2577
|
if (intent.kind === 'configReset') {
|
|
1926
2578
|
const parsed = parsePluginId(intent.pluginId);
|
|
@@ -1937,6 +2589,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1937
2589
|
rebuildRuntime: { ...context, awHomeMutationToken },
|
|
1938
2590
|
awHomeMutationToken,
|
|
1939
2591
|
apply: false,
|
|
2592
|
+
sharedNativeApplyConfirmed: false,
|
|
1940
2593
|
});
|
|
1941
2594
|
}
|
|
1942
2595
|
if (!currentSource) {
|
|
@@ -1950,7 +2603,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1950
2603
|
...(catalogOperation ? { operationContext: catalogOperation } : {}),
|
|
1951
2604
|
consume: async ({ plugin, source }) => {
|
|
1952
2605
|
assertSourceEvidenceMatches(currentSource, sourceEvidenceForPlugin(source, plugin.manifest.name));
|
|
1953
|
-
const applyTargets = intent.apply
|
|
2606
|
+
const applyTargets = intent.retryApply || intent.apply
|
|
1954
2607
|
? currentEvidence.config?.affectedTargets.map((target) => ({
|
|
1955
2608
|
pluginName: plugin.manifest.name,
|
|
1956
2609
|
platform: target.platform,
|
|
@@ -1967,6 +2620,10 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1967
2620
|
rebuildRuntime: {
|
|
1968
2621
|
...context,
|
|
1969
2622
|
awHomeMutationToken,
|
|
2623
|
+
operationDiagnosticSink,
|
|
2624
|
+
...(reviewedScriptTimeoutMs(intent) === undefined
|
|
2625
|
+
? {}
|
|
2626
|
+
: { scriptTimeoutMs: reviewedScriptTimeoutMs(intent) }),
|
|
1970
2627
|
...(catalogOperation ? {
|
|
1971
2628
|
catalogOperationContext: catalogOperation,
|
|
1972
2629
|
expectedGenerationSetDigest: expectedEvidence.catalog.generationSetDigest,
|
|
@@ -1974,6 +2631,9 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1974
2631
|
},
|
|
1975
2632
|
awHomeMutationToken,
|
|
1976
2633
|
applyTargets,
|
|
2634
|
+
sharedNativeApplyConfirmed: true,
|
|
2635
|
+
preApplyConfirmed: true,
|
|
2636
|
+
preApplyAuthorizedTargets: expectedEvidence.config?.preApplyAuthorization ?? [],
|
|
1977
2637
|
})
|
|
1978
2638
|
: await applyPluginConfigWrite({
|
|
1979
2639
|
plugin,
|
|
@@ -1985,6 +2645,10 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1985
2645
|
rebuildRuntime: {
|
|
1986
2646
|
...context,
|
|
1987
2647
|
awHomeMutationToken,
|
|
2648
|
+
operationDiagnosticSink,
|
|
2649
|
+
...(reviewedScriptTimeoutMs(intent) === undefined
|
|
2650
|
+
? {}
|
|
2651
|
+
: { scriptTimeoutMs: reviewedScriptTimeoutMs(intent) }),
|
|
1988
2652
|
...(catalogOperation ? {
|
|
1989
2653
|
catalogOperationContext: catalogOperation,
|
|
1990
2654
|
expectedGenerationSetDigest: expectedEvidence.catalog.generationSetDigest,
|
|
@@ -1993,13 +2657,18 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1993
2657
|
awHomeMutationToken,
|
|
1994
2658
|
applyTargets,
|
|
1995
2659
|
request: { updates: intent.updates, removeKeys: intent.removeKeys },
|
|
2660
|
+
sharedNativeApplyConfirmed: true,
|
|
2661
|
+
preApplyConfirmed: true,
|
|
2662
|
+
preApplyAuthorizedTargets: expectedEvidence.config?.preApplyAuthorization ?? [],
|
|
1996
2663
|
});
|
|
1997
|
-
return result;
|
|
2664
|
+
return { ...result, operationRebuildResults };
|
|
1998
2665
|
},
|
|
1999
2666
|
});
|
|
2000
2667
|
}
|
|
2001
2668
|
throw new TuiOperationBlockedError('operationNotImplemented', '这个写操作尚未接入新 Controller。');
|
|
2002
2669
|
},
|
|
2670
|
+
}).finally(async () => {
|
|
2671
|
+
await codexObservationSession?.dispose();
|
|
2003
2672
|
});
|
|
2004
2673
|
},
|
|
2005
2674
|
};
|