@kontextmind/kxm 0.7.83 → 0.7.85
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/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +32 -9
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/cli/hub.ts +36 -4
- package/plugins/kxm/src/cli/system.ts +13 -6
- package/plugins/kxm/src/kxm-update.ts +15 -0
- package/plugins/kxm/src/mcp-server.ts +1 -1
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "kxm",
|
|
4
4
|
"displayName": "KXM",
|
|
5
|
-
"version": "0.7.
|
|
5
|
+
"version": "0.7.85",
|
|
6
6
|
"description": "Headless multi-agent orchestration, durable workflows, and a live operator dashboard for Pi and Claude Code",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "KontextMind",
|
package/plugins/kxm/dist/cli.js
CHANGED
|
@@ -18176,6 +18176,13 @@ function readInstalledKxmVersion(root) {
|
|
|
18176
18176
|
}
|
|
18177
18177
|
return pkg.version;
|
|
18178
18178
|
}
|
|
18179
|
+
function installedKxmVersion(root) {
|
|
18180
|
+
try {
|
|
18181
|
+
return readInstalledKxmVersion(root);
|
|
18182
|
+
} catch {
|
|
18183
|
+
return void 0;
|
|
18184
|
+
}
|
|
18185
|
+
}
|
|
18179
18186
|
function parseSemver(value) {
|
|
18180
18187
|
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(value.trim());
|
|
18181
18188
|
if (!match) return void 0;
|
|
@@ -44610,6 +44617,13 @@ function installProbeFrom(runtime) {
|
|
|
44610
44617
|
env: partial.env ?? runtime.env
|
|
44611
44618
|
};
|
|
44612
44619
|
}
|
|
44620
|
+
function moduleInstallRoot() {
|
|
44621
|
+
try {
|
|
44622
|
+
return findKxmRepoRoot(import.meta.url);
|
|
44623
|
+
} catch {
|
|
44624
|
+
return dirname20(fileURLToPath3(import.meta.url));
|
|
44625
|
+
}
|
|
44626
|
+
}
|
|
44613
44627
|
function warnIgnoredProjectUpdateYaml(runtime) {
|
|
44614
44628
|
const projectFile = join41(runtime.dirs.workspace, "update.yaml");
|
|
44615
44629
|
if (!existsSync31(projectFile)) return;
|
|
@@ -44617,11 +44631,20 @@ function warnIgnoredProjectUpdateYaml(runtime) {
|
|
|
44617
44631
|
runtime.io.stderr(`kxm: ignoring .kxm/update.yaml in ${runtime.dirs.workdir}; update settings are read only from ${userFile}
|
|
44618
44632
|
`);
|
|
44619
44633
|
}
|
|
44620
|
-
async function refreshKxmUpdateNotice(runtime, config) {
|
|
44634
|
+
async function refreshKxmUpdateNotice(runtime, config, current) {
|
|
44621
44635
|
const resolved = config ?? loadKxmUpdateConfig(runtime.env);
|
|
44622
|
-
const
|
|
44636
|
+
const installed = current ?? installedKxmVersion(findKxmRepoRoot(import.meta.url)) ?? installedKxmVersion(moduleInstallRoot());
|
|
44637
|
+
if (installed === void 0) {
|
|
44638
|
+
return {
|
|
44639
|
+
current: "unknown",
|
|
44640
|
+
available: false,
|
|
44641
|
+
auto: false,
|
|
44642
|
+
source: resolved.source,
|
|
44643
|
+
message: `kxm update check skipped: the installed version is unreadable at ${moduleInstallRoot()}`
|
|
44644
|
+
};
|
|
44645
|
+
}
|
|
44623
44646
|
const fetched = await fetchLatestKxmVersion(resolved.source, runtime.env, runtime.fetchImpl);
|
|
44624
|
-
const notice = noticeFromVersions(
|
|
44647
|
+
const notice = noticeFromVersions(installed, fetched.latest, resolved, fetched.error, fetched.asset);
|
|
44625
44648
|
writeUpdateCache(runtime.dirs.state, notice);
|
|
44626
44649
|
return notice;
|
|
44627
44650
|
}
|
|
@@ -47142,16 +47165,16 @@ async function cmdUpdate(runtime, harness, options) {
|
|
|
47142
47165
|
warnIgnoredProjectUpdateYaml(runtime);
|
|
47143
47166
|
const probe = installProbeFrom(runtime);
|
|
47144
47167
|
const classified = classifyInstallRoot(probe);
|
|
47145
|
-
const current =
|
|
47168
|
+
const current = installedKxmVersion(classified.root) ?? installedKxmVersion(findKxmRepoRoot(import.meta.url));
|
|
47146
47169
|
let notice;
|
|
47147
47170
|
let kindReport = classified;
|
|
47148
47171
|
if (classified.kind === "source") {
|
|
47149
47172
|
if (options.check) {
|
|
47150
|
-
const message = `kxm ${current} (running from source at ${classified.root})`;
|
|
47173
|
+
const message = `kxm ${current ?? "unknown"} (running from source at ${classified.root})`;
|
|
47151
47174
|
print(runtime.io, runtime.json, {
|
|
47152
47175
|
ok: true,
|
|
47153
47176
|
command: "update check",
|
|
47154
|
-
current,
|
|
47177
|
+
current: current ?? "unknown",
|
|
47155
47178
|
available: false,
|
|
47156
47179
|
auto: false,
|
|
47157
47180
|
source: "github",
|
|
@@ -47173,15 +47196,15 @@ async function cmdUpdate(runtime, harness, options) {
|
|
|
47173
47196
|
return 2;
|
|
47174
47197
|
}
|
|
47175
47198
|
notice = {
|
|
47176
|
-
current,
|
|
47199
|
+
current: current ?? "unknown",
|
|
47177
47200
|
available: false,
|
|
47178
47201
|
auto: false,
|
|
47179
47202
|
source: "github",
|
|
47180
|
-
message: `kxm ${current} (running from source)`
|
|
47203
|
+
message: `kxm ${current ?? "unknown"} (running from source)`
|
|
47181
47204
|
};
|
|
47182
47205
|
} else {
|
|
47183
47206
|
try {
|
|
47184
|
-
notice = await refreshKxmUpdateNotice(runtime);
|
|
47207
|
+
notice = await refreshKxmUpdateNotice(runtime, void 0, current);
|
|
47185
47208
|
} catch (error) {
|
|
47186
47209
|
if (error instanceof KxmUpdateConfigError) {
|
|
47187
47210
|
print(runtime.io, runtime.json, { ok: false, command: "update", error: error.code, ...installKindPayload(classified) }, error.message);
|
|
@@ -17182,7 +17182,7 @@ async function deliverInboxNotification(messageId, delivered, notify) {
|
|
|
17182
17182
|
}
|
|
17183
17183
|
|
|
17184
17184
|
// plugins/kxm/src/mcp-server.ts
|
|
17185
|
-
var VERSION = "0.7.
|
|
17185
|
+
var VERSION = "0.7.85";
|
|
17186
17186
|
var inbox = /* @__PURE__ */ new Map();
|
|
17187
17187
|
var notifiedInbox = /* @__PURE__ */ new Set();
|
|
17188
17188
|
var meshClient;
|
package/plugins/kxm/package.json
CHANGED
|
@@ -93,7 +93,17 @@ export function installProbeFrom(runtime: Runtime): InstallProbe {
|
|
|
93
93
|
|
|
94
94
|
import { fileURLToPath } from "node:url";
|
|
95
95
|
import { dirname } from "node:path";
|
|
96
|
-
import { tryFindKxmRepoRoot } from "../repo-root.ts";
|
|
96
|
+
import { findKxmRepoRoot, tryFindKxmRepoRoot } from "../repo-root.ts";
|
|
97
|
+
import { installedKxmVersion } from "../kxm-update.ts";
|
|
98
|
+
|
|
99
|
+
/** The install root derived from the loaded module; `unknown` never crashes a caller. */
|
|
100
|
+
function moduleInstallRoot(): string {
|
|
101
|
+
try {
|
|
102
|
+
return findKxmRepoRoot(import.meta.url);
|
|
103
|
+
} catch {
|
|
104
|
+
return dirname(fileURLToPath(import.meta.url));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
97
107
|
import { homedir } from "node:os";
|
|
98
108
|
|
|
99
109
|
export function warnIgnoredProjectUpdateYaml(runtime: Runtime): void {
|
|
@@ -103,11 +113,33 @@ export function warnIgnoredProjectUpdateYaml(runtime: Runtime): void {
|
|
|
103
113
|
runtime.io.stderr(`kxm: ignoring .kxm/update.yaml in ${runtime.dirs.workdir}; update settings are read only from ${userFile}\n`);
|
|
104
114
|
}
|
|
105
115
|
|
|
106
|
-
export async function refreshKxmUpdateNotice(
|
|
116
|
+
export async function refreshKxmUpdateNotice(
|
|
117
|
+
runtime: Runtime,
|
|
118
|
+
config?: KxmUpdateConfig,
|
|
119
|
+
current?: string,
|
|
120
|
+
): Promise<KxmUpdateNotice> {
|
|
107
121
|
const resolved = config ?? loadKxmUpdateConfig(runtime.env);
|
|
108
|
-
|
|
122
|
+
// The version being compared is the one **running**, taken from the install
|
|
123
|
+
// root. Reading it from the caller's directory made `cd ~ && kxm update --kxm`
|
|
124
|
+
// die with a raw ENOENT on `$HOME/package.json` — and silently compared a
|
|
125
|
+
// stranger's version wherever the operator happened to stand and a
|
|
126
|
+
// package.json did exist. Callers that already resolved it pass it in.
|
|
127
|
+
const installed = current
|
|
128
|
+
?? installedKxmVersion(findKxmRepoRoot(import.meta.url))
|
|
129
|
+
?? installedKxmVersion(moduleInstallRoot());
|
|
130
|
+
if (installed === undefined) {
|
|
131
|
+
// No version to compare against: say nothing rather than crash a hub start
|
|
132
|
+
// over an update notice.
|
|
133
|
+
return {
|
|
134
|
+
current: "unknown",
|
|
135
|
+
available: false,
|
|
136
|
+
auto: false,
|
|
137
|
+
source: resolved.source,
|
|
138
|
+
message: `kxm update check skipped: the installed version is unreadable at ${moduleInstallRoot()}`,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
109
141
|
const fetched = await fetchLatestKxmVersion(resolved.source, runtime.env, runtime.fetchImpl);
|
|
110
|
-
const notice = noticeFromVersions(
|
|
142
|
+
const notice = noticeFromVersions(installed, fetched.latest, resolved, fetched.error, fetched.asset);
|
|
111
143
|
writeUpdateCache(runtime.dirs.state, notice);
|
|
112
144
|
return notice;
|
|
113
145
|
}
|
|
@@ -63,6 +63,7 @@ import {
|
|
|
63
63
|
type InstallProbe,
|
|
64
64
|
} from "../kxm-install-kind.ts";
|
|
65
65
|
import {
|
|
66
|
+
installedKxmVersion,
|
|
66
67
|
fetchLatestKxmVersion,
|
|
67
68
|
kxmReleaseAssetName,
|
|
68
69
|
noticeFromVersions,
|
|
@@ -296,16 +297,22 @@ export async function cmdUpdate(runtime: Runtime, harness: string | undefined, o
|
|
|
296
297
|
warnIgnoredProjectUpdateYaml(runtime);
|
|
297
298
|
const probe = installProbeFrom(runtime);
|
|
298
299
|
const classified = classifyInstallRoot(probe);
|
|
299
|
-
|
|
300
|
+
// The version of the install being updated, taken from the root that was just
|
|
301
|
+
// classified — not from whichever directory the operator stood in. A
|
|
302
|
+
// `readInstalledKxmVersion(resolve("."))` in the notice path turned
|
|
303
|
+
// `cd ~ && kxm update --kxm` into an uncaught ENOENT on `$HOME/package.json`,
|
|
304
|
+
// and would happily compare a stranger project's version wherever one did
|
|
305
|
+
// exist. Unreadable is now a stated refusal.
|
|
306
|
+
const current = installedKxmVersion(classified.root) ?? installedKxmVersion(findKxmRepoRoot(import.meta.url));
|
|
300
307
|
let notice: KxmUpdateNotice;
|
|
301
308
|
let kindReport = classified;
|
|
302
309
|
if (classified.kind === "source") {
|
|
303
310
|
if (options.check) {
|
|
304
|
-
const message = `kxm ${current} (running from source at ${classified.root})`;
|
|
311
|
+
const message = `kxm ${current ?? "unknown"} (running from source at ${classified.root})`;
|
|
305
312
|
print(runtime.io, runtime.json, {
|
|
306
313
|
ok: true,
|
|
307
314
|
command: "update check",
|
|
308
|
-
current,
|
|
315
|
+
current: current ?? "unknown",
|
|
309
316
|
available: false,
|
|
310
317
|
auto: false,
|
|
311
318
|
source: "github",
|
|
@@ -327,15 +334,15 @@ export async function cmdUpdate(runtime: Runtime, harness: string | undefined, o
|
|
|
327
334
|
return 2;
|
|
328
335
|
}
|
|
329
336
|
notice = {
|
|
330
|
-
current,
|
|
337
|
+
current: current ?? "unknown",
|
|
331
338
|
available: false,
|
|
332
339
|
auto: false,
|
|
333
340
|
source: "github",
|
|
334
|
-
message: `kxm ${current} (running from source)`,
|
|
341
|
+
message: `kxm ${current ?? "unknown"} (running from source)`,
|
|
335
342
|
};
|
|
336
343
|
} else {
|
|
337
344
|
try {
|
|
338
|
-
notice = await refreshKxmUpdateNotice(runtime);
|
|
345
|
+
notice = await refreshKxmUpdateNotice(runtime, undefined, current);
|
|
339
346
|
} catch (error) {
|
|
340
347
|
if (error instanceof KxmUpdateConfigError) {
|
|
341
348
|
print(runtime.io, runtime.json, { ok: false, command: "update", error: error.code, ...installKindPayload(classified) }, error.message);
|
|
@@ -51,6 +51,21 @@ export function readInstalledKxmVersion(root: string): string {
|
|
|
51
51
|
return pkg.version;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* `readInstalledKxmVersion` without the raw filesystem failure. The installed
|
|
56
|
+
* version is read to decide whether a candidate is an upgrade, a downgrade or
|
|
57
|
+
* the same thing — so a directory that has no readable `package.json` must come
|
|
58
|
+
* back as "unknown" and be refused in words, not surface as an uncaught ENOENT
|
|
59
|
+
* stack from `kxm update`.
|
|
60
|
+
*/
|
|
61
|
+
export function installedKxmVersion(root: string): string | undefined {
|
|
62
|
+
try {
|
|
63
|
+
return readInstalledKxmVersion(root);
|
|
64
|
+
} catch {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
54
69
|
export function parseSemver(value: string): [number, number, number] | undefined {
|
|
55
70
|
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(value.trim());
|
|
56
71
|
if (!match) return undefined;
|
|
@@ -8,7 +8,7 @@ import { AGENT_COMMANDS_MAP, enforceToolPolicy, getMcpTools, reconcileInbox } fr
|
|
|
8
8
|
import { deliverInboxNotification } from "./inbox.ts";
|
|
9
9
|
import type { HubEvent, MessageRecord } from "./protocol.ts";
|
|
10
10
|
|
|
11
|
-
const VERSION = "0.7.
|
|
11
|
+
const VERSION = "0.7.85";
|
|
12
12
|
const inbox = new Map<string, MessageRecord>();
|
|
13
13
|
const notifiedInbox = new Set<string>();
|
|
14
14
|
let meshClient: HubClient | undefined;
|