Files
Peter Steinberger 8cb53c7b55 perf(doctor): keep bundled doctor contract closures dependency-light (#120698)
* perf(doctor): keep bundled doctor contract closures dependency-light

Doctor contract enumeration cold-loads each plugin's doctor-contract-api
closure via jiti, so a static value import of openclaw/plugin-sdk/runtime-doctor
pulled the state-db/kysely graph (~4.3s per closure) into
listPluginDoctorLegacyConfigRules / listPluginDoctorStateMigrationEntries.

- migrate all light doctor-contract closures (66 files) to the
  dependency-light openclaw/plugin-sdk/runtime-doctor-migrations subpath
- voice-call: load detect/repairOpenClawStateDatabaseSchema* lazily inside
  the migration bodies; keep only a type-only static runtime-doctor import
- matrix: split pure credential record shapes/normalizers into
  credentials-state.ts so the doctor closure no longer imports the sync
  plugin-state store through credentials-read
- guard: doctor-contract-closure-guard.test.ts now forbids static value
  imports of runtime-doctor in closures alongside agent-runtime

* fix(matrix): keep credential revocation record type module-local

Knip production scan flags the export as consumer-less; the type is only
referenced by the exported union and revocation guard signature.
2026-08-08 17:51:31 -07:00

43 lines
1.6 KiB
TypeScript

// Device Pair doctor contract migrates shipped plugin-owned state.
import path from "node:path";
import {
defineLegacyJsonStateMigration,
type PluginDoctorStateMigration,
} from "openclaw/plugin-sdk/runtime-doctor-migrations";
import {
DEVICE_PAIR_NOTIFY_LEGACY_STATE_FILE,
DEVICE_PAIR_NOTIFY_SUBSCRIBER_MAX_ENTRIES,
DEVICE_PAIR_NOTIFY_SUBSCRIBER_NAMESPACE,
normalizeLegacyNotifyState,
notifySubscriberStoreKey,
type LegacyNotifyStateFile,
} from "./notify-state.js";
function resolveLegacyNotifyStatePath(stateDir: string): string {
return path.join(stateDir, DEVICE_PAIR_NOTIFY_LEGACY_STATE_FILE);
}
export const stateMigrations: PluginDoctorStateMigration[] = [
defineLegacyJsonStateMigration<LegacyNotifyStateFile>({
id: "device-pair-notify-json-to-plugin-state",
label: "Device Pair notify subscribers",
resolvePath: resolveLegacyNotifyStatePath,
parse: normalizeLegacyNotifyState,
namespace: DEVICE_PAIR_NOTIFY_SUBSCRIBER_NAMESPACE,
maxEntries: DEVICE_PAIR_NOTIFY_SUBSCRIBER_MAX_ENTRIES,
archiveLabel: "Device Pair notify-state",
describeEntries: (state, { filePath }) => ({
preview: [
`- Device Pair notify subscribers: ${filePath} -> plugin state (${DEVICE_PAIR_NOTIFY_SUBSCRIBER_NAMESPACE}, ${state.subscribers.length} subscriber(s))`,
],
change: ({ imported, alreadyPresent }) =>
`Migrated Device Pair notify subscribers -> plugin state (${imported} imported, ${alreadyPresent} already present)`,
}),
toRows: (state) =>
state.subscribers.map((subscriber) => ({
key: notifySubscriberStoreKey(subscriber),
value: subscriber,
})),
}),
];