agents-can-communicate 0.4.1 → 0.4.3
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/README.md +17 -4
- package/docs/ARCHITECTURE.md +7 -1
- package/docs/CLI.md +23 -3
- package/docs/CONFIGURATION.md +25 -0
- package/docs/GETTING_STARTED.md +17 -5
- package/docs/PROTOCOL.md +4 -0
- package/docs/RELEASING.md +1 -1
- package/docs/SECURITY_MODEL.md +7 -0
- package/docs/TROUBLESHOOTING.md +60 -7
- package/docs/UPGRADING.md +36 -19
- package/node_modules/@agents-can-communicate/adapter-claude-code/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/adapter.mjs +3 -3
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/channel.mjs +2 -4
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/install.mjs +10 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/native-delivery.mjs +3 -1
- package/node_modules/@agents-can-communicate/adapter-codex/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-codex/src/app-server-client.mjs +1 -1
- package/node_modules/@agents-can-communicate/adapter-codex/src/config-block.mjs +4 -88
- package/node_modules/@agents-can-communicate/adapter-codex/src/install.mjs +36 -15
- package/node_modules/@agents-can-communicate/adapter-codex/src/live-permissions.mjs +110 -0
- package/node_modules/@agents-can-communicate/adapter-codex/src/native-delivery.mjs +2 -1
- package/node_modules/@agents-can-communicate/adapter-codex/src/permission-ownership.mjs +109 -0
- package/node_modules/@agents-can-communicate/adapter-codex/src/toml-scan.mjs +99 -0
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/gemini-extension.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-grok/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-kimi/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-sdk/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-sdk/src/channel-directory.mjs +8 -0
- package/node_modules/@agents-can-communicate/adapter-sdk/src/index.mjs +3 -0
- package/node_modules/@agents-can-communicate/adapter-sdk/src/native-attempt-writer.mjs +64 -0
- package/node_modules/@agents-can-communicate/adapter-sdk/src/native-attempt.mjs +65 -0
- package/node_modules/@agents-can-communicate/adapter-sdk/src/native-vocabulary.mjs +1 -0
- package/node_modules/@agents-can-communicate/cli/package.json +1 -1
- package/node_modules/@agents-can-communicate/cli/src/doctor-command.mjs +19 -52
- package/node_modules/@agents-can-communicate/cli/src/install-command.mjs +23 -45
- package/node_modules/@agents-can-communicate/cli/src/main.mjs +3 -1
- package/node_modules/@agents-can-communicate/cli/src/native-delivery-status.mjs +88 -0
- package/node_modules/@agents-can-communicate/cli/src/native-session-diagnostics.mjs +64 -0
- package/node_modules/@agents-can-communicate/core/package.json +1 -1
- package/node_modules/@agents-can-communicate/core/src/receipts.mjs +1 -0
- package/node_modules/@agents-can-communicate/delivery-router/package.json +1 -1
- package/node_modules/@agents-can-communicate/delivery-router/src/router.mjs +1 -1
- package/node_modules/@agents-can-communicate/hook-runner/package.json +1 -1
- package/node_modules/@agents-can-communicate/hook-runner/src/native-attempt.mjs +43 -0
- package/node_modules/@agents-can-communicate/hook-runner/src/runner.mjs +17 -27
- package/node_modules/@agents-can-communicate/installer/package.json +1 -1
- package/node_modules/@agents-can-communicate/installer/src/apply.mjs +2 -0
- package/node_modules/@agents-can-communicate/installer/src/delivery-diagnostics.mjs +36 -0
- package/node_modules/@agents-can-communicate/installer/src/detect.mjs +28 -12
- package/node_modules/@agents-can-communicate/installer/src/index.mjs +3 -1
- package/node_modules/@agents-can-communicate/installer/src/live-policy.mjs +10 -3
- package/node_modules/@agents-can-communicate/installer/src/plan.mjs +12 -2
- package/node_modules/@agents-can-communicate/mcp-server/package.json +1 -1
- package/node_modules/@agents-can-communicate/protocol/package.json +1 -1
- package/node_modules/@agents-can-communicate/storage-filesystem/package.json +1 -1
- package/package.json +1 -1
|
@@ -3,10 +3,9 @@ import { createHash, randomBytes } from "node:crypto";
|
|
|
3
3
|
import { realpath } from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
|
|
6
|
-
import { clearSessionBinding, effectiveCapabilities, loadSessionBinding, storeSessionBinding }
|
|
6
|
+
import { clearNativeAttempt, clearSessionBinding, effectiveCapabilities, loadSessionBinding, storeSessionBinding }
|
|
7
7
|
from "@agents-can-communicate/adapter-sdk";
|
|
8
8
|
import { createCoordinationService } from "@agents-can-communicate/core";
|
|
9
|
-
import { readInstalledLivePolicy } from "@agents-can-communicate/installer";
|
|
10
9
|
import { AccError, createId } from "@agents-can-communicate/protocol";
|
|
11
10
|
import { openFilesystemStore } from "@agents-can-communicate/storage-filesystem";
|
|
12
11
|
import { createGitProbe, discoverWorkspace, platformDataHome, runtimePaths }
|
|
@@ -14,7 +13,7 @@ import { createGitProbe, discoverWorkspace, platformDataHome, runtimePaths }
|
|
|
14
13
|
|
|
15
14
|
import { resolveClientPid } from "./client-pid.mjs";
|
|
16
15
|
import { probeClientVersion as defaultProbeClientVersion } from "./client-version.mjs";
|
|
17
|
-
import {
|
|
16
|
+
import { bindNative, nativeDiagnosticDeadline } from "./native-attempt.mjs";
|
|
18
17
|
import { readProcessTable as defaultReadProcessTable } from "./process-table.mjs";
|
|
19
18
|
import { withSessionLifecycle } from "./session-lifecycle.mjs";
|
|
20
19
|
import { appendToolOwner, ownerHeader, ownerOnlyOutcome } from "./owner-context.mjs";
|
|
@@ -305,22 +304,6 @@ async function projectTurn({ binding, context, adapter, adapterId }) {
|
|
|
305
304
|
offerInputs: writableOffers };
|
|
306
305
|
}
|
|
307
306
|
|
|
308
|
-
// One bounded, fail-open native handshake for this exact session generation.
|
|
309
|
-
// New adapters read durable consent from their installation record; legacy
|
|
310
|
-
// adapters keep the environment exported by an owned shell bootstrap.
|
|
311
|
-
async function bindNative({ adapter, event, hookBinding, clientVersion, platform, context, paths,
|
|
312
|
-
deadline }) {
|
|
313
|
-
assertHookBudget(deadline);
|
|
314
|
-
const livePolicy = adapter?.nativeDelivery?.policySource === "installation-record"
|
|
315
|
-
? await readInstalledLivePolicy({ dataHome: context.dataHome, adapterId: adapter.id })
|
|
316
|
-
: livePolicyFrom(context.env);
|
|
317
|
-
assertHookBudget(deadline);
|
|
318
|
-
return establishNativeBinding({ adapter, event, hookBinding, clientVersion, platform,
|
|
319
|
-
livePolicy, service: context.service, runtimeDir: paths.root,
|
|
320
|
-
clock: context.service.clock, env: context.env,
|
|
321
|
-
timeoutMs: Math.max(1, Math.min(750, deadline - Date.now())) });
|
|
322
|
-
}
|
|
323
|
-
|
|
324
307
|
const HANDLERS = {
|
|
325
308
|
async sessionStart({ event, context, adapter, adapterId, binding, paths,
|
|
326
309
|
readProcessTable, probeClientVersion, platform, deadline }) {
|
|
@@ -356,12 +339,12 @@ const HANDLERS = {
|
|
|
356
339
|
branch: context.descriptor.git?.branch ?? null,
|
|
357
340
|
};
|
|
358
341
|
if (event.kind === "beforeTurn" && binding !== null) {
|
|
359
|
-
// A
|
|
360
|
-
//
|
|
361
|
-
//
|
|
342
|
+
// A genuine prompt can resume after an ephemeral removal or a durable
|
|
343
|
+
// close. Recheck after probes: a CLI replacement can run outside the
|
|
344
|
+
// native lifecycle lock. Never adopt that replacement's identity.
|
|
362
345
|
const previous = await context.service.locateSession(binding.accSessionId);
|
|
363
|
-
if (previous
|
|
364
|
-
|| previous.record.generation !== binding.generation) {
|
|
346
|
+
if (previous !== null && (previous.record.state !== "closed"
|
|
347
|
+
|| previous.record.generation !== binding.generation)) {
|
|
365
348
|
throw new Error("the completed hook owner changed during turn registration");
|
|
366
349
|
}
|
|
367
350
|
}
|
|
@@ -432,6 +415,11 @@ const HANDLERS = {
|
|
|
432
415
|
await context.service.clearDeliveryBinding(owner);
|
|
433
416
|
}
|
|
434
417
|
await clearSessionBinding({ runtimeDir: paths.root, deadlineAt: deadline, harnessSessionId: event.sessionId });
|
|
418
|
+
const diagnosticDeadline = nativeDiagnosticDeadline(deadline);
|
|
419
|
+
if (diagnosticDeadline !== null) {
|
|
420
|
+
await clearNativeAttempt({ runtimeDir: paths.root, harnessSessionId: event.sessionId,
|
|
421
|
+
...binding, deadlineAt: diagnosticDeadline });
|
|
422
|
+
}
|
|
435
423
|
return {};
|
|
436
424
|
},
|
|
437
425
|
|
|
@@ -450,9 +438,11 @@ const HANDLERS = {
|
|
|
450
438
|
return { ...turn, nativeBinding: started.nativeBinding };
|
|
451
439
|
}
|
|
452
440
|
const current = await context.service.locateSession(binding.accSessionId);
|
|
453
|
-
if (current
|
|
454
|
-
|
|
455
|
-
//
|
|
441
|
+
if (current === null
|
|
442
|
+
|| current.record.state === "closed" && current.record.generation === binding.generation) {
|
|
443
|
+
// A solo detach removes its ephemeral record; a durable close retains it.
|
|
444
|
+
// Both end the ACC incarnation while the native conversation may continue.
|
|
445
|
+
// Only a genuine user turn can start another one; tool hooks cannot. Reuse
|
|
456
446
|
// the crash-safe opening path, retaining its full published client facts
|
|
457
447
|
// and its single native handshake rather than binding a second time.
|
|
458
448
|
const started = await HANDLERS.sessionStart(input);
|
|
@@ -35,6 +35,7 @@ export async function applyPlan({ plan, adapters, context, dataHome, dryRun = fa
|
|
|
35
35
|
const createdDirectories = await missingArtifactParents({ home: context.home,
|
|
36
36
|
artifacts: operation.artifacts });
|
|
37
37
|
const installContext = { ...context,
|
|
38
|
+
clientVersion: operation.clientVersion, platform: operation.platform,
|
|
38
39
|
requestedLivePolicy: operation.livePolicy ?? "off",
|
|
39
40
|
livePolicy: operation.effectiveLivePolicy ?? "off" };
|
|
40
41
|
const outcome = await adapter.install(installContext);
|
|
@@ -103,6 +104,7 @@ export async function applyPlan({ plan, adapters, context, dataHome, dryRun = fa
|
|
|
103
104
|
retainedNativeActivation: retainedMechanisms.length === 0 ? null
|
|
104
105
|
: { ...operation.deactivation, mechanisms: retainedMechanisms } });
|
|
105
106
|
results.operations.push({ ...operation, applied: true,
|
|
107
|
+
needsAction: outcome.needsAction ?? [],
|
|
106
108
|
changes: outcome.changes ?? [], removed: owned.removed, kept: owned.kept,
|
|
107
109
|
removedDirectories: directories.removed, keptDirectories: directories.kept,
|
|
108
110
|
missingDirectories: directories.missing,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Shared presentation of observed delivery facts. Vendor probes provide closed
|
|
2
|
+
// reasons; installation and doctor must not turn a version floor into readiness.
|
|
3
|
+
const REASONS = Object.freeze({
|
|
4
|
+
native_delivery_unsupported: "this adapter has no native delivery channel",
|
|
5
|
+
platform_not_captured: "native delivery is not verified on this platform",
|
|
6
|
+
version_unavailable: "the client version could not be verified",
|
|
7
|
+
prerelease_not_captured: "this client version is not a verified stable release",
|
|
8
|
+
below_minimum_version: "the client is below the native delivery minimum version",
|
|
9
|
+
known_bad_version: "this client version has a known native delivery failure",
|
|
10
|
+
native_endpoint_unavailable: "the client's local delivery service is unavailable",
|
|
11
|
+
native_session_unavailable: "the local delivery service has no loaded client session",
|
|
12
|
+
feature_probe_failed: "the native protocol probe did not succeed",
|
|
13
|
+
probe_timeout: "the native protocol probe timed out",
|
|
14
|
+
probe_version_mismatch: "the local service and CLI versions differ",
|
|
15
|
+
protocol_mismatch: "the local service did not confirm the required protocol",
|
|
16
|
+
unsupported_shell: "automatic launch setup requires zsh",
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export function describeNativeReason(reason, { clientVersion, minimumVersion } = {}) {
|
|
20
|
+
if (reason === "below_minimum_version" && clientVersion && minimumVersion) {
|
|
21
|
+
return `client ${clientVersion} needs version ${minimumVersion} or newer for native delivery`;
|
|
22
|
+
}
|
|
23
|
+
return REASONS[reason] ?? reason ?? "readiness is unverified";
|
|
24
|
+
}
|
|
25
|
+
export const describeDeliveryFallback = entry => entry.capabilities?.delivery?.nextTurn === true
|
|
26
|
+
? "next-turn hooks (when enabled) or acc inbox" : "acc inbox";
|
|
27
|
+
|
|
28
|
+
export function describeInstallDelivery(entry, policy, effectivePolicy) {
|
|
29
|
+
const state = policy === "off" ? "off" : effectivePolicy === "off"
|
|
30
|
+
? `consent saved (${policy}); not active` : `enabled (${policy}); waiting for a verified session`;
|
|
31
|
+
const reason = entry.nativeDelivery?.reasonCode;
|
|
32
|
+
return `${entry.displayName ?? entry.adapterId} live delivery: ${state}`
|
|
33
|
+
+ (reason ? `; ${describeNativeReason(reason, { clientVersion: entry.version,
|
|
34
|
+
minimumVersion: entry.nativeDelivery?.eligibility?.minimumVersion })}` : "")
|
|
35
|
+
+ `; fallback: ${describeDeliveryFallback(entry)}`;
|
|
36
|
+
}
|
|
@@ -6,6 +6,8 @@ import { effectiveCapabilities, evaluateNativeEligibility, validateNativeActivat
|
|
|
6
6
|
|
|
7
7
|
import { resolveExecutable, shellOf, shimDirFor } from "./native-activation.mjs";
|
|
8
8
|
|
|
9
|
+
import { describeDeliveryFallback, describeNativeReason } from "./delivery-diagnostics.mjs";
|
|
10
|
+
|
|
9
11
|
const run = promisify(execFile);
|
|
10
12
|
|
|
11
13
|
// Reasons the client itself will not change within an install: unsupported,
|
|
@@ -79,8 +81,14 @@ async function detectNative(adapter, entry, { context, platform, probeTimeoutMs,
|
|
|
79
81
|
}
|
|
80
82
|
if (facts.eligibility.eligible !== true) {
|
|
81
83
|
const reasonCode = facts.eligibility.reasonCode ?? "feature_probe_failed";
|
|
84
|
+
// A stored policy can be consented to before a service/session exists.
|
|
85
|
+
// No activation is planned until the full probe passes; bootstrap-based
|
|
86
|
+
// clients still need their verified plan to disclose launch changes.
|
|
87
|
+
const consentAvailable = adapter.nativeDelivery.policySource === "installation-record"
|
|
88
|
+
&& ["native_endpoint_unavailable", "native_session_unavailable"].includes(reasonCode);
|
|
82
89
|
return STATIC_REASONS.has(reasonCode)
|
|
83
|
-
? { ...unsupported(reasonCode), ...facts }
|
|
90
|
+
? { ...unsupported(reasonCode), ...facts }
|
|
91
|
+
: { ...degraded(reasonCode, facts), consentAvailable };
|
|
84
92
|
}
|
|
85
93
|
let activationPlan;
|
|
86
94
|
try {
|
|
@@ -110,7 +118,7 @@ export async function detectInstallation({ adapters, context, probe = spawnProbe
|
|
|
110
118
|
// deterministic rather than dependent on registry order.
|
|
111
119
|
.sort((left, right) => left.id.localeCompare(right.id))
|
|
112
120
|
.map(async adapter => {
|
|
113
|
-
const entry = { adapterId: adapter.id, displayName: adapter.displayName,
|
|
121
|
+
const entry = { adapterId: adapter.id, displayName: adapter.displayName, platform,
|
|
114
122
|
present: false, version: null, versionOutput: null, installed: false,
|
|
115
123
|
diagnostics: [], needsAction: [], capabilities: effectiveCapabilities(adapter),
|
|
116
124
|
deliveryDiagnostic: null, error: null };
|
|
@@ -138,7 +146,10 @@ export async function detectInstallation({ adapters, context, probe = spawnProbe
|
|
|
138
146
|
? "native_delivery_unsupported" : "version_unavailable");
|
|
139
147
|
|
|
140
148
|
try {
|
|
141
|
-
const detected = await adapter.detect(context
|
|
149
|
+
const detected = await adapter.detect({ ...context, clientVersion: entry.version,
|
|
150
|
+
platform, nativeDelivery: entry.nativeDelivery });
|
|
151
|
+
if (detected.outgoingDelivery) entry.outgoingDelivery = detected.outgoingDelivery;
|
|
152
|
+
if (detected.nativeSetup) entry.nativeSetup = detected.nativeSetup;
|
|
142
153
|
entry.diagnostics = [...(detected.diagnostics ?? [])];
|
|
143
154
|
// What a person has to do, as opposed to what is true. Adapters that
|
|
144
155
|
// have nothing to ask for say nothing.
|
|
@@ -151,15 +162,20 @@ export async function detectInstallation({ adapters, context, probe = spawnProbe
|
|
|
151
162
|
} catch (error) {
|
|
152
163
|
entry.error = entry.error ?? error.message;
|
|
153
164
|
}
|
|
154
|
-
if (entry.nativeDelivery.state !== "eligible"
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
165
|
+
if (entry.nativeDelivery.state !== "eligible") {
|
|
166
|
+
if (adapter.nativeDelivery !== undefined) {
|
|
167
|
+
entry.deliveryDiagnostic = `${adapter.displayName} native delivery: `
|
|
168
|
+
+ `${describeNativeReason(entry.nativeDelivery.reasonCode, { clientVersion: entry.version,
|
|
169
|
+
minimumVersion: entry.nativeDelivery.eligibility?.minimumVersion })}; `
|
|
170
|
+
+ `fallback: ${describeDeliveryFallback(entry)}`;
|
|
171
|
+
} else if (typeof adapter.deliveryFallback?.diagnostic === "string") {
|
|
172
|
+
const downgraded = adapter.capabilities?.delivery?.nextTurn === true
|
|
173
|
+
&& entry.capabilities?.delivery?.nextTurn !== true;
|
|
174
|
+
entry.deliveryDiagnostic = (downgraded
|
|
175
|
+
? `${adapter.displayName} ${entry.version ?? "unknown version"} has no certified `
|
|
176
|
+
+ `next-turn delivery on ${platform}; ` : "") + adapter.deliveryFallback.diagnostic;
|
|
177
|
+
}
|
|
178
|
+
if (entry.deliveryDiagnostic !== null) entry.diagnostics.push(entry.deliveryDiagnostic);
|
|
163
179
|
}
|
|
164
180
|
return entry;
|
|
165
181
|
}));
|
|
@@ -12,4 +12,6 @@ export { BLOCK_BEGIN, BLOCK_END, SHIM_MARKER, SHIM_POLICIES, SUPPORTED_SHELLS,
|
|
|
12
12
|
shellLiteral, uninstallShellBootstrap, validateShimEntry } from "./shell-bootstrap.mjs";
|
|
13
13
|
export { LIVE_POLICIES, describeActivation, describeDeactivation, livePolicyOf, rcFileFor,
|
|
14
14
|
resolveExecutable, shellOf, shimDirFor } from "./native-activation.mjs";
|
|
15
|
-
export { readInstalledLivePolicy } from "./live-policy.mjs";
|
|
15
|
+
export { readInstalledLivePolicy, readInstalledLivePolicyState } from "./live-policy.mjs";
|
|
16
|
+
export { describeDeliveryFallback, describeInstallDelivery, describeNativeReason }
|
|
17
|
+
from "./delivery-diagnostics.mjs";
|
|
@@ -10,12 +10,19 @@ export const livePolicyOf = install => {
|
|
|
10
10
|
? install.nativeActivation.livePolicy : "off";
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
export async function readInstalledLivePolicy(
|
|
13
|
+
export async function readInstalledLivePolicy(input) {
|
|
14
|
+
return (await readInstalledLivePolicyState(input)).policy;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function readInstalledLivePolicyState({ dataHome, adapterId }) {
|
|
14
18
|
try {
|
|
15
19
|
const record = await loadOwnership({ dataHome });
|
|
16
20
|
const install = record.installs.find(entry => entry.adapterId === adapterId);
|
|
17
|
-
|
|
21
|
+
const raw = Object.hasOwn(install ?? {}, "deliveryPolicy")
|
|
22
|
+
? install.deliveryPolicy : install?.nativeActivation?.livePolicy;
|
|
23
|
+
return { policy: livePolicyOf(install), policyStatus: raw === undefined ? "missing"
|
|
24
|
+
: !LIVE_POLICIES.includes(raw) ? "invalid" : raw === "off" ? "off" : "enabled" };
|
|
18
25
|
} catch {
|
|
19
|
-
return "off";
|
|
26
|
+
return { policy: "off", policyStatus: "unavailable" };
|
|
20
27
|
}
|
|
21
28
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { describeInstallDelivery } from "./delivery-diagnostics.mjs";
|
|
2
|
+
|
|
1
3
|
import { AccError, EXIT } from "@agents-can-communicate/protocol";
|
|
2
4
|
|
|
3
5
|
import { LIVE_POLICIES, describeActivation, describeDeactivation, planActivationRetirements, rcFileFor, shimDirFor }
|
|
@@ -112,8 +114,12 @@ export function planInstallation({ adapters, detected, context, action = "instal
|
|
|
112
114
|
?? `${adapter.displayName ?? adapter.id} cannot receive native delivery `
|
|
113
115
|
+ `(${native?.reasonCode ?? "native_delivery_unsupported"}); durable fallback remains active`
|
|
114
116
|
: null;
|
|
117
|
+
const deliverySummary = action === "install"
|
|
118
|
+
? describeInstallDelivery(entry, delivery, effectiveLivePolicy) : null;
|
|
115
119
|
const installContext = { ...context, requestedLivePolicy: delivery,
|
|
116
|
-
livePolicy: effectiveLivePolicy };
|
|
120
|
+
livePolicy: effectiveLivePolicy, clientVersion: entry.version, platform: entry.platform };
|
|
121
|
+
const setupNotes = action === "install" && delivery !== "off"
|
|
122
|
+
? [entry.outgoingDelivery?.setup, entry.nativeSetup].filter(note => typeof note === "string") : [];
|
|
117
123
|
// A consented activation that this run keeps, activates, or takes back.
|
|
118
124
|
// Only an explicit off or an uninstall removes one; an absent record never
|
|
119
125
|
// creates one.
|
|
@@ -135,6 +141,7 @@ export function planInstallation({ adapters, detected, context, action = "instal
|
|
|
135
141
|
displayName: adapter.displayName,
|
|
136
142
|
action,
|
|
137
143
|
clientVersion: entry.version ?? record?.version ?? null,
|
|
144
|
+
platform: entry.platform ?? context?.platform,
|
|
138
145
|
// "Remove these files for a client that is not here" is a different thing
|
|
139
146
|
// to approve than an ordinary uninstall, so it is said rather than left
|
|
140
147
|
// to be inferred from a client version that is null.
|
|
@@ -143,6 +150,8 @@ export function planInstallation({ adapters, detected, context, action = "instal
|
|
|
143
150
|
livePolicy: delivery,
|
|
144
151
|
effectiveLivePolicy,
|
|
145
152
|
...(deliveryDiagnostic === null ? {} : { deliveryDiagnostic }),
|
|
153
|
+
...(deliverySummary === null ? {} : { deliverySummary }),
|
|
154
|
+
...(setupNotes.length ? { setupNotes } : {}),
|
|
146
155
|
...(nativeActivation === null ? {} : { nativeActivation }),
|
|
147
156
|
...(deactivation === null ? {} : { deactivation }),
|
|
148
157
|
artifacts,
|
|
@@ -151,7 +160,8 @@ export function planInstallation({ adapters, detected, context, action = "instal
|
|
|
151
160
|
summary: [
|
|
152
161
|
...(entry.present ? [] : [`${adapter.displayName ?? adapter.id} is no longer on `
|
|
153
162
|
+ "this machine; removing what ACC recorded writing"]),
|
|
154
|
-
...(
|
|
163
|
+
...(deliverySummary === null ? [] : [deliverySummary]),
|
|
164
|
+
...setupNotes,
|
|
155
165
|
...artifacts.filter(a => a.kind === "tree")
|
|
156
166
|
.map(a => `${action === "install" ? "create" : "remove"} ${a.path}`),
|
|
157
167
|
...artifacts.filter(a => a.kind === "merge")
|