kimi-plugin-cc 2.4.0 → 2.4.1
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +9 -0
- package/README.md +14 -6
- package/dist/cli-client.js +2 -2
- package/dist/commands/cli-helpers.js +5 -1
- package/dist/commands/swarm.js +191 -34
- package/dist/hooks/config-safety.js +4 -3
- package/dist/kimi-engine.js +1 -0
- package/dist/process-tree.js +48 -17
- package/dist/swarm-activation.js +812 -0
- package/dist/version.js +1 -1
- package/docs/migration.md +12 -2
- package/docs/registry-releases.md +6 -2
- package/docs/safety.md +17 -5
- package/package.json +2 -2
- package/plugins/kimi-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/kimi-codex/dist/cli-client.js +2 -2
- package/plugins/kimi-codex/dist/commands/cli-helpers.js +5 -1
- package/plugins/kimi-codex/dist/commands/swarm.js +191 -34
- package/plugins/kimi-codex/dist/hooks/config-safety.js +4 -3
- package/plugins/kimi-codex/dist/kimi-engine.js +1 -0
- package/plugins/kimi-codex/dist/process-tree.js +48 -17
- package/plugins/kimi-codex/dist/swarm-activation.js +812 -0
- package/plugins/kimi-codex/dist/version.js +1 -1
|
@@ -6,7 +6,7 @@ const MAX_DESCENDANT_DEPTH = 8;
|
|
|
6
6
|
const MAX_DESCENDANT_PIDS = 512;
|
|
7
7
|
const PROCESS_EXIT_POLL_MS = 10;
|
|
8
8
|
const PROCESS_SNAPSHOT_TIMEOUT_MS = 1_000;
|
|
9
|
-
const PROCESS_IDENTITY_PROBE_TIMEOUT_MS =
|
|
9
|
+
const PROCESS_IDENTITY_PROBE_TIMEOUT_MS = 1_000;
|
|
10
10
|
const PROBE_TIMEOUT = Symbol("process-probe-timeout");
|
|
11
11
|
/**
|
|
12
12
|
* Capture descendant ancestry and reusable identities in the same bounded
|
|
@@ -23,6 +23,18 @@ export async function collectDescendantIdentities(rootPid) {
|
|
|
23
23
|
}
|
|
24
24
|
return snapshot;
|
|
25
25
|
}
|
|
26
|
+
/** Return current members of the selected process groups, or undefined when unreadable. */
|
|
27
|
+
export async function collectProcessGroupsIdentities(processGroupIds) {
|
|
28
|
+
if (process.platform === "win32")
|
|
29
|
+
return undefined;
|
|
30
|
+
const groups = new Set(processGroupIds.filter((id) => Number.isInteger(id) && id > 0));
|
|
31
|
+
if (groups.size === 0)
|
|
32
|
+
return [];
|
|
33
|
+
const rows = await raceValueWithTimeout(collectProcessSnapshotRows(), PROCESS_SNAPSHOT_TIMEOUT_MS);
|
|
34
|
+
if (rows === PROBE_TIMEOUT || rows === undefined)
|
|
35
|
+
return undefined;
|
|
36
|
+
return rows.filter((row) => groups.has(row.processGroupId)).map(toProcessIdentity);
|
|
37
|
+
}
|
|
26
38
|
/**
|
|
27
39
|
* Compatibility surface for callers that only need numeric process listings.
|
|
28
40
|
* Cancellation must use collectDescendantIdentities so ancestry and identity
|
|
@@ -36,15 +48,21 @@ export async function collectDescendants(rootPid) {
|
|
|
36
48
|
return [];
|
|
37
49
|
}
|
|
38
50
|
}
|
|
39
|
-
/**
|
|
40
|
-
export async function
|
|
51
|
+
/** Distinguish a missing process from a failed or timed-out identity probe. */
|
|
52
|
+
export async function probeProcessIdentity(pid) {
|
|
41
53
|
if (!Number.isInteger(pid) || pid <= 0 || process.platform === "win32")
|
|
42
|
-
return
|
|
54
|
+
return { complete: true };
|
|
43
55
|
const read = process.platform === "linux"
|
|
44
56
|
? readProcessIdentityBatchFromProc([pid])
|
|
45
57
|
: readProcessIdentityBatchWithPs([pid]);
|
|
46
58
|
const batch = await raceValueWithTimeout(read, PROCESS_IDENTITY_PROBE_TIMEOUT_MS);
|
|
47
|
-
|
|
59
|
+
if (batch === PROBE_TIMEOUT)
|
|
60
|
+
return { complete: false };
|
|
61
|
+
return { identity: batch.identities.get(pid), complete: batch.complete };
|
|
62
|
+
}
|
|
63
|
+
/** Read one reusable process identity. PID alone is not stable across teardown. */
|
|
64
|
+
export async function readProcessIdentity(pid) {
|
|
65
|
+
return (await probeProcessIdentity(pid)).identity;
|
|
48
66
|
}
|
|
49
67
|
/**
|
|
50
68
|
* Revalidate all captured identities concurrently under one deadline. The
|
|
@@ -63,16 +81,26 @@ export async function revalidateProcessIdentities(expectedIdentities, options =
|
|
|
63
81
|
if (batch === PROBE_TIMEOUT)
|
|
64
82
|
return { identities: [], complete: false };
|
|
65
83
|
const identities = [];
|
|
84
|
+
const groupChanged = [];
|
|
66
85
|
for (const expectedIdentity of expected) {
|
|
67
86
|
const current = batch.identities.get(expectedIdentity.pid);
|
|
68
|
-
if (current
|
|
69
|
-
current.startToken
|
|
70
|
-
current.
|
|
71
|
-
|
|
87
|
+
if (current === undefined ||
|
|
88
|
+
current.startToken !== expectedIdentity.startToken ||
|
|
89
|
+
isQuiescentState(current.state)) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (current.processGroupId !== expectedIdentity.processGroupId) {
|
|
93
|
+
groupChanged.push(current);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
72
96
|
identities.push(current);
|
|
73
97
|
}
|
|
74
98
|
}
|
|
75
|
-
return {
|
|
99
|
+
return {
|
|
100
|
+
identities,
|
|
101
|
+
complete: batch.complete,
|
|
102
|
+
...(groupChanged.length > 0 ? { groupChanged } : {}),
|
|
103
|
+
};
|
|
76
104
|
}
|
|
77
105
|
/** Return the current identity only when pid, start token, and PGID still match. */
|
|
78
106
|
export async function revalidateProcessIdentity(expected, identityReader) {
|
|
@@ -104,7 +132,7 @@ export async function waitForProcessTreeExit(identities, timeoutMs, options = {}
|
|
|
104
132
|
identityReader: options.identityReader,
|
|
105
133
|
timeoutMs: probeTimeoutMs,
|
|
106
134
|
});
|
|
107
|
-
active = !validation.complete || validation.identities.length > 0;
|
|
135
|
+
active = !validation.complete || validation.identities.length > 0 || (validation.groupChanged?.length ?? 0) > 0;
|
|
108
136
|
}
|
|
109
137
|
if (!active)
|
|
110
138
|
return true;
|
|
@@ -117,13 +145,13 @@ export async function waitForProcessTreeExit(identities, timeoutMs, options = {}
|
|
|
117
145
|
async function collectVerifiedDescendantIdentities(rootPid) {
|
|
118
146
|
const initialRows = await collectProcessSnapshotRows();
|
|
119
147
|
if (initialRows === undefined)
|
|
120
|
-
|
|
148
|
+
throw new Error("process snapshot unavailable");
|
|
121
149
|
const candidateRows = descendantRowsFromSnapshot(rootPid, initialRows);
|
|
122
150
|
const initialRoot = initialRows.find((row) => row.pid === rootPid);
|
|
123
151
|
if (initialRoot === undefined || candidateRows.length === 0)
|
|
124
152
|
return [];
|
|
125
|
-
// A second, targeted snapshot closes the cross-row /proc race:
|
|
126
|
-
//
|
|
153
|
+
// A second, targeted snapshot closes the cross-row /proc race: each child
|
|
154
|
+
// must retain its PID and start token. Reparenting and PGID changes are not exit.
|
|
127
155
|
const expectedRows = [initialRoot, ...candidateRows];
|
|
128
156
|
const expectedByPid = new Map(expectedRows.map((row) => [row.pid, row]));
|
|
129
157
|
const verificationRows = await readCurrentSnapshotRows(expectedRows);
|
|
@@ -131,11 +159,9 @@ async function collectVerifiedDescendantIdentities(rootPid) {
|
|
|
131
159
|
const expected = expectedByPid.get(current.pid);
|
|
132
160
|
return (expected !== undefined &&
|
|
133
161
|
current.startToken === expected.startToken &&
|
|
134
|
-
current.processGroupId === expected.processGroupId &&
|
|
135
|
-
current.parentPid === expected.parentPid &&
|
|
136
162
|
!isQuiescentState(current.state));
|
|
137
163
|
});
|
|
138
|
-
return
|
|
164
|
+
return stableRows.map(toProcessIdentity);
|
|
139
165
|
}
|
|
140
166
|
function descendantRowsFromSnapshot(rootPid, rows) {
|
|
141
167
|
const root = rows.find((row) => row.pid === rootPid);
|
|
@@ -186,6 +212,9 @@ async function readCurrentSnapshotRows(expectedRows) {
|
|
|
186
212
|
Promise.all(procPids.map((pid) => readProcRow(pid))),
|
|
187
213
|
collectProcessSnapshotRowsFromPs(psPids),
|
|
188
214
|
]);
|
|
215
|
+
if (procOutcomes.some((outcome) => outcome.status === "error") || (psPids.length > 0 && psRows === undefined)) {
|
|
216
|
+
throw new Error("process identity verification failed");
|
|
217
|
+
}
|
|
189
218
|
return [
|
|
190
219
|
...procOutcomes.flatMap((outcome) => outcome.status === "found" ? [outcome.row] : []),
|
|
191
220
|
...(psRows ?? []),
|
|
@@ -212,6 +241,8 @@ async function collectProcessSnapshotRowsFromProc() {
|
|
|
212
241
|
const outcomes = await Promise.all(entries
|
|
213
242
|
.filter((entry) => /^\d+$/.test(entry))
|
|
214
243
|
.map((entry) => readProcRow(Number.parseInt(entry, 10))));
|
|
244
|
+
if (outcomes.some((outcome) => outcome.status === "error"))
|
|
245
|
+
return undefined;
|
|
215
246
|
return outcomes.flatMap((outcome) => outcome.status === "found" ? [outcome.row] : []);
|
|
216
247
|
}
|
|
217
248
|
async function collectProcessSnapshotRowsFromPs(pids) {
|