@kontextmind/kxm 0.7.79 → 0.7.81
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 +19 -13
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/runtime.js +17 -10
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/cli/project.ts +6 -3
- package/plugins/kxm/src/database.ts +32 -17
- 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.81",
|
|
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
|
@@ -23980,20 +23980,30 @@ function restoreDatabaseFile(backupPath, targetPath, storeId, expectedSchemaVers
|
|
|
23980
23980
|
integrity: "ok"
|
|
23981
23981
|
};
|
|
23982
23982
|
}
|
|
23983
|
+
var KXM_BACKUP_CEILINGS = {
|
|
23984
|
+
"hub-store": 5,
|
|
23985
|
+
registry: 1,
|
|
23986
|
+
"binding-store": 1,
|
|
23987
|
+
events: 7
|
|
23988
|
+
};
|
|
23989
|
+
function kxmBackupCeiling(storeId) {
|
|
23990
|
+
if (storeId.startsWith("events:")) return KXM_BACKUP_CEILINGS.events;
|
|
23991
|
+
return KXM_BACKUP_CEILINGS[storeId] ?? KXM_BACKUP_CEILINGS["hub-store"];
|
|
23992
|
+
}
|
|
23983
23993
|
function discoverProjectStores(projectRoot, options = {}) {
|
|
23984
23994
|
const root = resolve5(projectRoot);
|
|
23985
23995
|
const stores = [];
|
|
23986
23996
|
const hubPath = options.hubDataPath ? resolve5(options.hubDataPath) : join8(root, ".kxm", "state", "kxm.db");
|
|
23987
23997
|
if (existsSync8(hubPath)) {
|
|
23988
|
-
stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion:
|
|
23998
|
+
stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion: kxmBackupCeiling("hub-store") });
|
|
23989
23999
|
}
|
|
23990
24000
|
const registryPath = join8(root, ".kxm", "runtime", "registry.db");
|
|
23991
24001
|
if (existsSync8(registryPath)) {
|
|
23992
|
-
stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion:
|
|
24002
|
+
stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion: kxmBackupCeiling("registry") });
|
|
23993
24003
|
}
|
|
23994
24004
|
const bindingsPath = join8(root, ".kxm", "runtime", "bindings.db");
|
|
23995
24005
|
if (existsSync8(bindingsPath)) {
|
|
23996
|
-
stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion:
|
|
24006
|
+
stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion: kxmBackupCeiling("binding-store") });
|
|
23997
24007
|
}
|
|
23998
24008
|
const eventsDir = join8(root, ".kxm", "runtime", "events");
|
|
23999
24009
|
if (existsSync8(eventsDir)) {
|
|
@@ -24004,7 +24014,7 @@ function discoverProjectStores(projectRoot, options = {}) {
|
|
|
24004
24014
|
stores.push({
|
|
24005
24015
|
storeId: `events:${key}`,
|
|
24006
24016
|
sourcePath: join8(eventsDir, entry.name),
|
|
24007
|
-
maxSupportedVersion:
|
|
24017
|
+
maxSupportedVersion: kxmBackupCeiling(`events:${key}`)
|
|
24008
24018
|
});
|
|
24009
24019
|
}
|
|
24010
24020
|
}
|
|
@@ -24091,12 +24101,7 @@ function restoreBackup(manifestPathOrDir, options = {}) {
|
|
|
24091
24101
|
`backup file ${store.backupFile} sha256 ${actualSha256} does not match manifest hash ${store.sha256}`
|
|
24092
24102
|
);
|
|
24093
24103
|
}
|
|
24094
|
-
|
|
24095
|
-
if (store.storeId === "registry" || store.storeId === "binding-store") {
|
|
24096
|
-
maxSupported = 1;
|
|
24097
|
-
} else if (store.storeId.startsWith("events:")) {
|
|
24098
|
-
maxSupported = 7;
|
|
24099
|
-
}
|
|
24104
|
+
const maxSupported = kxmBackupCeiling(store.storeId);
|
|
24100
24105
|
let targetPath = store.sourcePath;
|
|
24101
24106
|
if (options.projectRoot && manifest.projectRoot && targetPath.startsWith(manifest.projectRoot)) {
|
|
24102
24107
|
const rel = targetPath.slice(manifest.projectRoot.length).replace(/^[\\/]+/, "");
|
|
@@ -32775,7 +32780,7 @@ async function cmdKxmRuntime(runtime, action) {
|
|
|
32775
32780
|
const sync = status.running ? await readKxmSupervisorSync(runtime) : void 0;
|
|
32776
32781
|
print(runtime.io, runtime.json, { ok: true, command: "runtime status", ...status, ...sync ? { sync } : {} }, [
|
|
32777
32782
|
status.running ? `runtime supervisor running: ${status.runtimeId} pid ${status.pid} on 127.0.0.1:${status.port}` : "runtime supervisor is not running",
|
|
32778
|
-
...formatKxmSyncStatus(sync)
|
|
32783
|
+
...formatKxmSyncStatus(sync, status.running)
|
|
32779
32784
|
].join("\n"));
|
|
32780
32785
|
return status.running ? 0 : 1;
|
|
32781
32786
|
}
|
|
@@ -32834,8 +32839,9 @@ async function readKxmSupervisorSync(runtime) {
|
|
|
32834
32839
|
return void 0;
|
|
32835
32840
|
}
|
|
32836
32841
|
}
|
|
32837
|
-
function formatKxmSyncStatus(sync) {
|
|
32838
|
-
if (
|
|
32842
|
+
function formatKxmSyncStatus(sync, running) {
|
|
32843
|
+
if (!running) return [];
|
|
32844
|
+
if (sync === void 0) return ["sync: the supervisor is running but did not answer /v1/sync/status"];
|
|
32839
32845
|
if (sync.length === 0) return ["sync: no project registered with this Runtime yet"];
|
|
32840
32846
|
return sync.map((project) => {
|
|
32841
32847
|
const codes = project.outbox.refusals.map((refusal) => `${refusal.code} x${refusal.count}`).join(", ");
|
|
@@ -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.81";
|
|
17186
17186
|
var inbox = /* @__PURE__ */ new Map();
|
|
17187
17187
|
var notifiedInbox = /* @__PURE__ */ new Set();
|
|
17188
17188
|
var meshClient;
|
|
@@ -18326,20 +18326,30 @@ function restoreDatabaseFile(backupPath, targetPath, storeId, expectedSchemaVers
|
|
|
18326
18326
|
integrity: "ok"
|
|
18327
18327
|
};
|
|
18328
18328
|
}
|
|
18329
|
+
var KXM_BACKUP_CEILINGS = {
|
|
18330
|
+
"hub-store": 5,
|
|
18331
|
+
registry: 1,
|
|
18332
|
+
"binding-store": 1,
|
|
18333
|
+
events: 7
|
|
18334
|
+
};
|
|
18335
|
+
function kxmBackupCeiling(storeId) {
|
|
18336
|
+
if (storeId.startsWith("events:")) return KXM_BACKUP_CEILINGS.events;
|
|
18337
|
+
return KXM_BACKUP_CEILINGS[storeId] ?? KXM_BACKUP_CEILINGS["hub-store"];
|
|
18338
|
+
}
|
|
18329
18339
|
function discoverProjectStores(projectRoot, options = {}) {
|
|
18330
18340
|
const root = resolve3(projectRoot);
|
|
18331
18341
|
const stores = [];
|
|
18332
18342
|
const hubPath = options.hubDataPath ? resolve3(options.hubDataPath) : join4(root, ".kxm", "state", "kxm.db");
|
|
18333
18343
|
if (existsSync4(hubPath)) {
|
|
18334
|
-
stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion:
|
|
18344
|
+
stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion: kxmBackupCeiling("hub-store") });
|
|
18335
18345
|
}
|
|
18336
18346
|
const registryPath = join4(root, ".kxm", "runtime", "registry.db");
|
|
18337
18347
|
if (existsSync4(registryPath)) {
|
|
18338
|
-
stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion:
|
|
18348
|
+
stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion: kxmBackupCeiling("registry") });
|
|
18339
18349
|
}
|
|
18340
18350
|
const bindingsPath = join4(root, ".kxm", "runtime", "bindings.db");
|
|
18341
18351
|
if (existsSync4(bindingsPath)) {
|
|
18342
|
-
stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion:
|
|
18352
|
+
stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion: kxmBackupCeiling("binding-store") });
|
|
18343
18353
|
}
|
|
18344
18354
|
const eventsDir = join4(root, ".kxm", "runtime", "events");
|
|
18345
18355
|
if (existsSync4(eventsDir)) {
|
|
@@ -18350,7 +18360,7 @@ function discoverProjectStores(projectRoot, options = {}) {
|
|
|
18350
18360
|
stores.push({
|
|
18351
18361
|
storeId: `events:${key}`,
|
|
18352
18362
|
sourcePath: join4(eventsDir, entry.name),
|
|
18353
|
-
maxSupportedVersion:
|
|
18363
|
+
maxSupportedVersion: kxmBackupCeiling(`events:${key}`)
|
|
18354
18364
|
});
|
|
18355
18365
|
}
|
|
18356
18366
|
}
|
|
@@ -18437,12 +18447,7 @@ function restoreBackup(manifestPathOrDir, options = {}) {
|
|
|
18437
18447
|
`backup file ${store.backupFile} sha256 ${actualSha256} does not match manifest hash ${store.sha256}`
|
|
18438
18448
|
);
|
|
18439
18449
|
}
|
|
18440
|
-
|
|
18441
|
-
if (store.storeId === "registry" || store.storeId === "binding-store") {
|
|
18442
|
-
maxSupported = 1;
|
|
18443
|
-
} else if (store.storeId.startsWith("events:")) {
|
|
18444
|
-
maxSupported = 7;
|
|
18445
|
-
}
|
|
18450
|
+
const maxSupported = kxmBackupCeiling(store.storeId);
|
|
18446
18451
|
let targetPath = store.sourcePath;
|
|
18447
18452
|
if (options.projectRoot && manifest.projectRoot && targetPath.startsWith(manifest.projectRoot)) {
|
|
18448
18453
|
const rel = targetPath.slice(manifest.projectRoot.length).replace(/^[\\/]+/, "");
|
|
@@ -31288,6 +31293,7 @@ export {
|
|
|
31288
31293
|
IMPROVEMENT_REPORT_SCHEMA,
|
|
31289
31294
|
IMPROVEMENT_REPORT_V1_SCHEMA,
|
|
31290
31295
|
KXM_ABSENT_MEMORY_REVISION,
|
|
31296
|
+
KXM_BACKUP_CEILINGS,
|
|
31291
31297
|
KXM_DRIVE_RECEIPT_SCHEMA,
|
|
31292
31298
|
KXM_EVENT_STORE_SCHEMA_VERSION,
|
|
31293
31299
|
KXM_EVENT_STORE_TABLE_NAMES,
|
|
@@ -31366,6 +31372,7 @@ export {
|
|
|
31366
31372
|
isKxmRuntimeContextClosed,
|
|
31367
31373
|
isTransactionContention,
|
|
31368
31374
|
isWindowsHarnessShim,
|
|
31375
|
+
kxmBackupCeiling,
|
|
31369
31376
|
kxmDeclaredExecutorIds,
|
|
31370
31377
|
kxmDeclaredRepositoryIds,
|
|
31371
31378
|
kxmEventBase,
|
package/plugins/kxm/package.json
CHANGED
|
@@ -758,7 +758,7 @@ export async function cmdKxmRuntime(runtime: Runtime, action: string): Promise<n
|
|
|
758
758
|
status.running
|
|
759
759
|
? `runtime supervisor running: ${status.runtimeId} pid ${status.pid} on 127.0.0.1:${status.port}`
|
|
760
760
|
: "runtime supervisor is not running",
|
|
761
|
-
...formatKxmSyncStatus(sync),
|
|
761
|
+
...formatKxmSyncStatus(sync, status.running),
|
|
762
762
|
].join("\n"));
|
|
763
763
|
return status.running ? 0 : 1;
|
|
764
764
|
}
|
|
@@ -820,8 +820,11 @@ async function readKxmSupervisorSync(runtime: Runtime): Promise<KxmProjectSyncSt
|
|
|
820
820
|
}
|
|
821
821
|
}
|
|
822
822
|
|
|
823
|
-
function formatKxmSyncStatus(sync: KxmProjectSyncStatus[] | undefined): string[] {
|
|
824
|
-
|
|
823
|
+
function formatKxmSyncStatus(sync: KxmProjectSyncStatus[] | undefined, running: boolean): string[] {
|
|
824
|
+
// Nothing was asked, so nothing failed to answer. Saying "did not answer" here
|
|
825
|
+
// would blame a supervisor that was never up.
|
|
826
|
+
if (!running) return [];
|
|
827
|
+
if (sync === undefined) return ["sync: the supervisor is running but did not answer /v1/sync/status"];
|
|
825
828
|
if (sync.length === 0) return ["sync: no project registered with this Runtime yet"];
|
|
826
829
|
return sync.map((project) => {
|
|
827
830
|
const codes = project.outbox.refusals.map((refusal) => `${refusal.code} x${refusal.count}`).join(", ");
|
|
@@ -585,25 +585,50 @@ export function restoreDatabaseFile(
|
|
|
585
585
|
};
|
|
586
586
|
}
|
|
587
587
|
|
|
588
|
+
/**
|
|
589
|
+
* Per-store restore ceilings, held in **one** table read by both backup discovery
|
|
590
|
+
* and restore. Two copies of these numbers drifted once already: a schema bump
|
|
591
|
+
* raised the restore ceiling and left the discovery ceiling behind, and nothing
|
|
592
|
+
* caught it because nothing read the stale copy.
|
|
593
|
+
*
|
|
594
|
+
* Each value MUST track the version its store declares — `HUB_STORE_SCHEMA_VERSION`
|
|
595
|
+
* in `store.ts`, `KXM_REGISTRY_SCHEMA_VERSION` and `KXM_EVENT_STORE_SCHEMA_VERSION`
|
|
596
|
+
* in `runtime-store.ts`. Those modules import this one, so the constants cannot be
|
|
597
|
+
* named here; the gate is the named test
|
|
598
|
+
* `restore ceilings track every store's own schema version` in
|
|
599
|
+
* `test/core/e6-backup-restore-migrations.test.ts`, which is what the deleted
|
|
600
|
+
* "must track" comments were only pretending to be.
|
|
601
|
+
*/
|
|
602
|
+
export const KXM_BACKUP_CEILINGS = {
|
|
603
|
+
"hub-store": 5,
|
|
604
|
+
registry: 1,
|
|
605
|
+
"binding-store": 1,
|
|
606
|
+
events: 7,
|
|
607
|
+
} as const;
|
|
608
|
+
|
|
609
|
+
export function kxmBackupCeiling(storeId: string): number {
|
|
610
|
+
if (storeId.startsWith("events:")) return KXM_BACKUP_CEILINGS.events;
|
|
611
|
+
// An id this build does not know keeps the ceiling restore has always defaulted to.
|
|
612
|
+
return KXM_BACKUP_CEILINGS[storeId as keyof typeof KXM_BACKUP_CEILINGS] ?? KXM_BACKUP_CEILINGS["hub-store"];
|
|
613
|
+
}
|
|
614
|
+
|
|
588
615
|
export function discoverProjectStores(projectRoot: string, options: { hubDataPath?: string } = {}): Array<{ storeId: string; sourcePath: string; maxSupportedVersion: number }> {
|
|
589
616
|
const root = resolve(projectRoot);
|
|
590
617
|
const stores: Array<{ storeId: string; sourcePath: string; maxSupportedVersion: number }> = [];
|
|
591
618
|
|
|
592
619
|
const hubPath = options.hubDataPath ? resolve(options.hubDataPath) : join(root, ".kxm", "state", "kxm.db");
|
|
593
620
|
if (existsSync(hubPath)) {
|
|
594
|
-
|
|
595
|
-
// restored through this ceiling, so a bump left behind here refuses it.
|
|
596
|
-
stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion: 5 });
|
|
621
|
+
stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion: kxmBackupCeiling("hub-store") });
|
|
597
622
|
}
|
|
598
623
|
|
|
599
624
|
const registryPath = join(root, ".kxm", "runtime", "registry.db");
|
|
600
625
|
if (existsSync(registryPath)) {
|
|
601
|
-
stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion:
|
|
626
|
+
stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion: kxmBackupCeiling("registry") });
|
|
602
627
|
}
|
|
603
628
|
|
|
604
629
|
const bindingsPath = join(root, ".kxm", "runtime", "bindings.db");
|
|
605
630
|
if (existsSync(bindingsPath)) {
|
|
606
|
-
stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion:
|
|
631
|
+
stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion: kxmBackupCeiling("binding-store") });
|
|
607
632
|
}
|
|
608
633
|
|
|
609
634
|
const eventsDir = join(root, ".kxm", "runtime", "events");
|
|
@@ -615,7 +640,7 @@ export function discoverProjectStores(projectRoot: string, options: { hubDataPat
|
|
|
615
640
|
stores.push({
|
|
616
641
|
storeId: `events:${key}`,
|
|
617
642
|
sourcePath: join(eventsDir, entry.name),
|
|
618
|
-
maxSupportedVersion:
|
|
643
|
+
maxSupportedVersion: kxmBackupCeiling(`events:${key}`),
|
|
619
644
|
});
|
|
620
645
|
}
|
|
621
646
|
}
|
|
@@ -729,17 +754,7 @@ export function restoreBackup(
|
|
|
729
754
|
);
|
|
730
755
|
}
|
|
731
756
|
|
|
732
|
-
|
|
733
|
-
// same reason as the events ceiling below.
|
|
734
|
-
let maxSupported = 5;
|
|
735
|
-
if (store.storeId === "registry" || store.storeId === "binding-store") {
|
|
736
|
-
maxSupported = 1;
|
|
737
|
-
} else if (store.storeId.startsWith("events:")) {
|
|
738
|
-
// Must track KXM_EVENT_STORE_SCHEMA_VERSION in runtime-store.ts. The pin is
|
|
739
|
-
// the e6 backup/restore round-trip test: bump one without the other and it
|
|
740
|
-
// refuses its own fresh backup.
|
|
741
|
-
maxSupported = 7;
|
|
742
|
-
}
|
|
757
|
+
const maxSupported = kxmBackupCeiling(store.storeId);
|
|
743
758
|
|
|
744
759
|
let targetPath = store.sourcePath;
|
|
745
760
|
if (options.projectRoot && manifest.projectRoot && targetPath.startsWith(manifest.projectRoot)) {
|
|
@@ -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.81";
|
|
12
12
|
const inbox = new Map<string, MessageRecord>();
|
|
13
13
|
const notifiedInbox = new Set<string>();
|
|
14
14
|
let meshClient: HubClient | undefined;
|