agents-can-communicate 0.5.8 → 0.5.9
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/node_modules/@agents-can-communicate/adapter-claude-code/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/install.mjs +9 -6
- package/node_modules/@agents-can-communicate/adapter-codex/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-codex/src/install.mjs +9 -5
- 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/index.mjs +1 -1
- package/node_modules/@agents-can-communicate/adapter-sdk/src/own-version.mjs +11 -3
- package/node_modules/@agents-can-communicate/cli/package.json +1 -1
- package/node_modules/@agents-can-communicate/cli/src/managed-runtime/install.mjs +6 -1
- package/node_modules/@agents-can-communicate/cli/src/managed-runtime/refresh.mjs +6 -1
- package/node_modules/@agents-can-communicate/core/package.json +1 -1
- package/node_modules/@agents-can-communicate/delivery-router/package.json +1 -1
- package/node_modules/@agents-can-communicate/hook-runner/package.json +1 -1
- package/node_modules/@agents-can-communicate/installer/package.json +1 -1
- 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
|
@@ -9,7 +9,7 @@ import { fileURLToPath } from "node:url";
|
|
|
9
9
|
|
|
10
10
|
import { acccreatedFile, bakeSkillCommand, blankJson, defaultBootstrap, defaultChannel,
|
|
11
11
|
mergeOwnedEntries, ownedEntries,
|
|
12
|
-
|
|
12
|
+
keepVersions, ownVersion, stampPluginVersion,
|
|
13
13
|
removeIfEmpty,
|
|
14
14
|
removeInstalledTree,
|
|
15
15
|
removeOwnedEntries, writeCliShim, writeForeignJson, writeHookShim }
|
|
@@ -181,7 +181,7 @@ async function layOutPlugin(target, { runner, node, cli, channel, live }) {
|
|
|
181
181
|
version: await pluginVersion(), io: { readFile, writeFile } });
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
export async function installClaudePlugin({ configDir, runner, cli,
|
|
184
|
+
export async function installClaudePlugin({ configDir, runner, cli, keepPreviousVersion = null, node = process.execPath,
|
|
185
185
|
channel = defaultChannel(), livePolicy = "off", now = new Date() }) {
|
|
186
186
|
const live = livePolicy === "actionable" || livePolicy === "all";
|
|
187
187
|
// Everything this will merge into, read before a byte is written. A settings
|
|
@@ -206,10 +206,13 @@ export async function installClaudePlugin({ configDir, runner, cli, preserveVers
|
|
|
206
206
|
// run `claude plugin install`, exactly as the Codex adapter does, because the
|
|
207
207
|
// command's only effect is this copy plus the two registry entries below.
|
|
208
208
|
await layOutPlugin(cached, { runner, node, cli, channel, live });
|
|
209
|
-
//
|
|
210
|
-
// so every upgrade would otherwise leave the previous
|
|
211
|
-
// this one - invisible while the version never moved,
|
|
212
|
-
|
|
209
|
+
// The copy just written, plus the one an upgrade moved off. A client caches a
|
|
210
|
+
// plugin under its version, so every upgrade would otherwise leave the previous
|
|
211
|
+
// release's tree beside this one - invisible while the version never moved,
|
|
212
|
+
// three deep once it did. The one it moved off stays because a session open
|
|
213
|
+
// across the upgrade still runs hooks from the path it recorded at start;
|
|
214
|
+
// anything older than that holds no session and is litter.
|
|
215
|
+
await keepVersions({ root: path.dirname(cached), keep: [version, keepPreviousVersion],
|
|
213
216
|
io: { readdir, rm } });
|
|
214
217
|
|
|
215
218
|
await writeClientJson(knownMarketplacesPath(configDir), {
|
|
@@ -5,7 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
7
|
import { bakeSkillCommand, blankJson, blankText, removeIfEmpty, removeInstalledTree,
|
|
8
|
-
|
|
8
|
+
keepVersions, ownVersion, stampPluginVersion,
|
|
9
9
|
tomlString, writeCliShim, writeForeignJson, writeHookShim }
|
|
10
10
|
from "@agents-can-communicate/adapter-sdk";
|
|
11
11
|
import { AccError, EXIT } from "@agents-can-communicate/protocol";
|
|
@@ -160,7 +160,7 @@ const sandboxReview = (config, file, stateRoot) =>
|
|
|
160
160
|
: [];
|
|
161
161
|
|
|
162
162
|
export async function installCodexPlugin({ home, agentsHome = home,
|
|
163
|
-
codexHome = path.join(home, ".codex"), dataHome, stateRoot, runner, node, cli,
|
|
163
|
+
codexHome = path.join(home, ".codex"), dataHome, stateRoot, runner, node, cli, keepPreviousVersion = null,
|
|
164
164
|
requestedLivePolicy, livePolicy, clientVersion, platform }) {
|
|
165
165
|
// Read before writing, so a manifest that will not parse is found before a
|
|
166
166
|
// plugin tree is laid down that nothing will then be able to remove.
|
|
@@ -228,9 +228,13 @@ export async function installCodexPlugin({ home, agentsHome = home,
|
|
|
228
228
|
const cached = cachedVersionPath(codexHome, version);
|
|
229
229
|
await rm(cached, { recursive: true, force: true });
|
|
230
230
|
await cp(target, cached, { recursive: true });
|
|
231
|
-
//
|
|
232
|
-
// directory. The marketplace cache root above it holds other
|
|
233
|
-
|
|
231
|
+
// The copy just written, plus the one an upgrade moved off - and only inside
|
|
232
|
+
// this plugin's own directory. The marketplace cache root above it holds other
|
|
233
|
+
// people's plugins. A session open across the upgrade still fires its hooks
|
|
234
|
+
// from the path it started with, so removing that one now would silence it
|
|
235
|
+
// until restart; anything older than it holds no session and is litter.
|
|
236
|
+
await keepVersions({ root: path.dirname(cached), keep: [version, keepPreviousVersion],
|
|
237
|
+
io: { readdir, rm } });
|
|
234
238
|
|
|
235
239
|
// The plugin's own directory in the cache. Not the versioned one inside it,
|
|
236
240
|
// which goes stale the moment the version changes - and not the marketplace
|
|
@@ -15,7 +15,7 @@ export { BEGIN, END, removeTomlBlock, renderBlock, stripBlock, tomlString, write
|
|
|
15
15
|
export { projectContext, projectContextResult } from "./context-projector.mjs";
|
|
16
16
|
export { decisionBody, decisionLines } from "./decision-text.mjs";
|
|
17
17
|
export { shellWriteTargets } from "./shell-writes.mjs";
|
|
18
|
-
export {
|
|
18
|
+
export { keepVersions, ownVersion, stampPluginVersion } from "./own-version.mjs";
|
|
19
19
|
export { editJson, readJson } from "./json-text.mjs";
|
|
20
20
|
export { formatJsonAs, jsonStyleOf, mergeOwnedConfig, mergeOwnedEntries, ownedEntries, ownedKeys,
|
|
21
21
|
acccreatedFile, removeIfEmpty, removeOwnedConfig, removeOwnedEntries, writeForeignJson,
|
|
@@ -57,23 +57,31 @@ export async function stampPluginVersion({ file, version, io }) {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
|
-
* Leave
|
|
60
|
+
* Leave the named copies of a versioned plugin and remove the rest.
|
|
61
61
|
*
|
|
62
62
|
* These clients cache a plugin under its version. Until the version tracked the
|
|
63
63
|
* package it never changed, every install landed in the same directory and
|
|
64
64
|
* overwrote itself, and nothing accumulated. Once it started moving, the first
|
|
65
65
|
* upgrade left three copies of ACC in a home that should hold one.
|
|
66
66
|
*
|
|
67
|
+
* `keep` is a list rather than the single version just written, because these
|
|
68
|
+
* clients pin one `installPath` per plugin and a session reads it once. A
|
|
69
|
+
* session already open when an upgrade lands still holds the path it started
|
|
70
|
+
* with, so an upgrade names the version it moved off as well as the one it
|
|
71
|
+
* wrote, and that session keeps firing hooks until it is restarted. An install
|
|
72
|
+
* with nothing to hold passes a null, which is dropped here.
|
|
73
|
+
*
|
|
67
74
|
* Scoped to the plugin's own directory. The marketplace cache root above it
|
|
68
75
|
* holds every plugin installed from that marketplace, and removing that root
|
|
69
76
|
* once took a plugin the user had installed themselves - so a sibling here is
|
|
70
77
|
* an older ACC, and a sibling one level up is somebody else's.
|
|
71
78
|
*/
|
|
72
|
-
export async function
|
|
79
|
+
export async function keepVersions({ root, keep, io }) {
|
|
80
|
+
const wanted = new Set(keep.filter(version => typeof version === "string" && version !== ""));
|
|
73
81
|
const entries = await io.readdir(root, { withFileTypes: true }).catch(() => []);
|
|
74
82
|
const removed = [];
|
|
75
83
|
for (const entry of entries) {
|
|
76
|
-
if (!entry.isDirectory() || entry.name
|
|
84
|
+
if (!entry.isDirectory() || wanted.has(entry.name)) continue;
|
|
77
85
|
await io.rm(path.join(root, entry.name), { recursive: true, force: true });
|
|
78
86
|
removed.push(entry.name);
|
|
79
87
|
}
|
|
@@ -56,7 +56,12 @@ export async function installManaged({ packageRoot, managerRoot, dataHome, home,
|
|
|
56
56
|
targets: [...new Set([...(previous?.targets ?? []), ...targets])], notice: null };
|
|
57
57
|
await writeControl(root, control);
|
|
58
58
|
const paths = await writeLaunchers(root, runtime.root);
|
|
59
|
-
|
|
59
|
+
// The guard above admits only an install from the active generation, so
|
|
60
|
+
// this names the version being written and the adapters keep one copy.
|
|
61
|
+
// It is read from the pointer rather than assumed, so a future relaxation
|
|
62
|
+
// of that guard keeps the outgoing copy instead of silently removing it.
|
|
63
|
+
const result = await apply({ ...paths,
|
|
64
|
+
keepPreviousVersion: previous?.active.version ?? null });
|
|
60
65
|
// Service readiness is separate from integration installation. Its failure
|
|
61
66
|
// must not fence a fully installed runtime or make the durable inbox unusable.
|
|
62
67
|
const integrationFailed = result.failed.some(failure => failure.stage !== "service-setup"
|
|
@@ -12,8 +12,13 @@ export async function prepareRefresh({ control, root, env = process.env, callerP
|
|
|
12
12
|
const wanted = new Set(control.targets);
|
|
13
13
|
const adapters = ALL_ADAPTERS().filter(adapter => wanted.has(adapter.id));
|
|
14
14
|
if (adapters.length !== wanted.size) throw new Error("candidate cannot refresh every installed integration");
|
|
15
|
+
// The version this refresh is moving off. Clients that cache a plugin under
|
|
16
|
+
// its version record one path per plugin and read it once per session, so a
|
|
17
|
+
// session open across the update keeps running from the outgoing copy until it
|
|
18
|
+
// restarts. Naming it here keeps that copy; everything older than it goes.
|
|
15
19
|
const context = { ...clientContext(control.home, path.join(dataHome, "acc"),
|
|
16
|
-
{ env, shell: shellOf(env), dataHome }), ...stablePaths(root),
|
|
20
|
+
{ env, shell: shellOf(env), dataHome }), ...stablePaths(root),
|
|
21
|
+
keepPreviousVersion: control.active.version };
|
|
17
22
|
const recorded = (await loadOwnership({ dataHome })).installs;
|
|
18
23
|
const detected = await detectInstallation({ adapters, context, probeTimeoutMs: probeTimeout(env) });
|
|
19
24
|
const deliveryByAdapter = Object.fromEntries(adapters.map(adapter => [adapter.id,
|