mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 14:20:35 +08:00
fix(authority): track supported job types
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -33,6 +33,10 @@ function normalizeFeatureName(value) {
|
||||
return String(value ?? "").trim().toLowerCase();
|
||||
}
|
||||
|
||||
function normalizeJobType(value) {
|
||||
return String(value ?? "").trim().toLowerCase();
|
||||
}
|
||||
|
||||
function addFeature(features, value) {
|
||||
const normalized = normalizeFeatureName(value);
|
||||
if (normalized) features.add(normalized);
|
||||
@@ -319,6 +323,71 @@ export function collectAuthorityFeatures(payload = {}) {
|
||||
return features;
|
||||
}
|
||||
|
||||
function collectJobTypesFromArray(jobTypes, value) {
|
||||
if (!Array.isArray(value)) return false;
|
||||
for (const item of value) {
|
||||
const normalized = normalizeJobType(item);
|
||||
if (normalized) jobTypes.add(normalized);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function collectJobTypesFromEntries(jobTypes, value) {
|
||||
if (!Array.isArray(value)) return false;
|
||||
for (const entry of value) {
|
||||
const normalized = normalizeJobType(entry?.type);
|
||||
if (normalized) jobTypes.add(normalized);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function collectSupportedJobTypes(payload = {}) {
|
||||
const source = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
||||
const jobTypes = new Set();
|
||||
let known = source.supportedJobTypesKnown === true;
|
||||
|
||||
const topLevelSupportedJobTypes = source.supportedJobTypes;
|
||||
if (Array.isArray(topLevelSupportedJobTypes)) {
|
||||
collectJobTypesFromArray(jobTypes, topLevelSupportedJobTypes);
|
||||
known =
|
||||
known ||
|
||||
topLevelSupportedJobTypes.length > 0 ||
|
||||
source.reason === "ok" ||
|
||||
Number(source.lastProbeAt || 0) > 0 ||
|
||||
source.installed === true ||
|
||||
source.healthy === true;
|
||||
}
|
||||
|
||||
for (const value of [
|
||||
source.jobs?.supportedTypes,
|
||||
source.jobs?.builtinTypes,
|
||||
source.jobs?.registry?.jobTypes,
|
||||
source.features?.jobs?.supportedTypes,
|
||||
source.features?.jobs?.builtinTypes,
|
||||
source.features?.jobs?.registry?.jobTypes,
|
||||
source.featureDetails?.jobs?.supportedTypes,
|
||||
source.featureDetails?.jobs?.builtinTypes,
|
||||
source.featureDetails?.jobs?.registry?.jobTypes,
|
||||
source.core?.health?.jobRegistrySummary?.jobTypes,
|
||||
]) {
|
||||
known = collectJobTypesFromArray(jobTypes, value) || known;
|
||||
}
|
||||
|
||||
for (const value of [
|
||||
source.jobs?.registry?.entries,
|
||||
source.features?.jobs?.registry?.entries,
|
||||
source.featureDetails?.jobs?.registry?.entries,
|
||||
source.core?.health?.jobRegistrySummary?.entries,
|
||||
]) {
|
||||
known = collectJobTypesFromEntries(jobTypes, value) || known;
|
||||
}
|
||||
|
||||
return {
|
||||
supportedJobTypes: Array.from(jobTypes).sort(),
|
||||
supportedJobTypesKnown: known,
|
||||
};
|
||||
}
|
||||
|
||||
export function createDefaultAuthorityCapabilityState(overrides = {}) {
|
||||
return {
|
||||
enabledMode: "auto",
|
||||
@@ -332,6 +401,8 @@ export function createDefaultAuthorityCapabilityState(overrides = {}) {
|
||||
storagePrimaryReady: false,
|
||||
triviumPrimaryReady: false,
|
||||
jobsReady: false,
|
||||
supportedJobTypes: [],
|
||||
supportedJobTypesKnown: false,
|
||||
blobReady: false,
|
||||
features: [],
|
||||
missingFeatures: ["sql.query", "sql.mutation", "trivium.search", "jobs", "blob-or-private-files"],
|
||||
@@ -351,6 +422,7 @@ export function normalizeAuthorityCapabilityState(input = {}, settings = {}) {
|
||||
const source = input && typeof input === "object" && !Array.isArray(input) ? input : {};
|
||||
const features = new Set((Array.isArray(source.features) ? source.features : []).map(normalizeFeatureName).filter(Boolean));
|
||||
const readiness = createFeatureReadiness(features);
|
||||
const supportedJobs = collectSupportedJobTypes(source);
|
||||
const missingFeatures = Array.isArray(source.missingFeatures) && source.missingFeatures.length
|
||||
? source.missingFeatures.map(String)
|
||||
: collectMissingFeatures(readiness);
|
||||
@@ -380,6 +452,8 @@ export function normalizeAuthorityCapabilityState(input = {}, settings = {}) {
|
||||
storagePrimaryReady,
|
||||
triviumPrimaryReady,
|
||||
jobsReady,
|
||||
supportedJobTypes: supportedJobs.supportedJobTypes,
|
||||
supportedJobTypesKnown: supportedJobs.supportedJobTypesKnown,
|
||||
blobReady,
|
||||
features: Array.from(features).sort(),
|
||||
missingFeatures,
|
||||
@@ -396,6 +470,7 @@ export function normalizeAuthorityCapabilityState(input = {}, settings = {}) {
|
||||
export function normalizeAuthorityProbeResponse(payload = {}, context = {}) {
|
||||
const settings = normalizeAuthoritySettings(context.settings || {});
|
||||
const features = collectAuthorityFeatures(payload);
|
||||
const supportedJobs = collectSupportedJobTypes(payload);
|
||||
const readiness = createFeatureReadiness(features);
|
||||
const missingFeatures = collectMissingFeatures(readiness);
|
||||
const sessionReady = payload?.sessionReady ?? payload?.session?.ready ?? payload?.session?.active ?? true;
|
||||
@@ -408,6 +483,8 @@ export function normalizeAuthorityProbeResponse(payload = {}, context = {}) {
|
||||
sessionReady: Boolean(sessionReady),
|
||||
permissionReady: Boolean(permissionReady),
|
||||
features: Array.from(features),
|
||||
supportedJobTypes: supportedJobs.supportedJobTypes,
|
||||
supportedJobTypesKnown: supportedJobs.supportedJobTypesKnown,
|
||||
missingFeatures,
|
||||
reason: missingFeatures.length ? "missing-required-features" : "ok",
|
||||
endpoint: context.endpoint || "",
|
||||
@@ -519,6 +596,7 @@ export async function probeAuthorityCapabilities(options = {}) {
|
||||
payload = {};
|
||||
}
|
||||
const features = collectAuthorityFeatures(payload);
|
||||
const supportedJobs = collectSupportedJobTypes(payload);
|
||||
const readiness = createFeatureReadiness(features);
|
||||
const missingFeatures = collectMissingFeatures(readiness);
|
||||
const healthy = payload?.healthy ?? payload?.ok ?? true;
|
||||
@@ -544,6 +622,8 @@ export async function probeAuthorityCapabilities(options = {}) {
|
||||
sessionReady: Boolean(sessionReady),
|
||||
permissionReady: Boolean(permissionReady),
|
||||
features: Array.from(features),
|
||||
supportedJobTypes: supportedJobs.supportedJobTypes,
|
||||
supportedJobTypesKnown: supportedJobs.supportedJobTypesKnown,
|
||||
missingFeatures,
|
||||
reason,
|
||||
lastError: dataPlaneLastError,
|
||||
|
||||
@@ -3,7 +3,9 @@ import assert from "node:assert/strict";
|
||||
import {
|
||||
buildAuthorityProbeUrls,
|
||||
collectAuthorityFeatures,
|
||||
createDefaultAuthorityCapabilityState,
|
||||
normalizeAuthorityCapabilityState,
|
||||
normalizeAuthorityProbeResponse,
|
||||
normalizeAuthoritySettings,
|
||||
probeAuthorityCapabilities,
|
||||
} from "../runtime/authority-capabilities.js";
|
||||
@@ -174,4 +176,132 @@ const relativeUnavailable = await probeAuthorityCapabilities({
|
||||
assert.equal(relativeUnavailable.reason, "relative-url-unavailable");
|
||||
assert.equal(relativeUnavailable.serverPrimaryReady, false);
|
||||
|
||||
// Regression: Authority capability normalization records explicit supported job types from probe payloads.
|
||||
// When a probe payload provides jobs.supportedTypes, normalizeAuthorityCapabilityState should surface
|
||||
// them as supportedJobTypes and set supportedJobTypesKnown = true.
|
||||
const explicitJobTypesState = normalizeAuthorityCapabilityState(
|
||||
{
|
||||
installed: true,
|
||||
healthy: true,
|
||||
features: ["sql", "trivium", "jobs", "transfers.fs"],
|
||||
jobs: { supportedTypes: ["authority.vector.rebuild", "authority.cache.invalidate"] },
|
||||
},
|
||||
defaultSettings,
|
||||
);
|
||||
assert.equal(explicitJobTypesState.supportedJobTypesKnown, true);
|
||||
assert.deepEqual(explicitJobTypesState.supportedJobTypes, [
|
||||
"authority.cache.invalidate",
|
||||
"authority.vector.rebuild",
|
||||
]);
|
||||
|
||||
// Regression: Current Authority builtin job list is known and excludes authority.vector.rebuild.
|
||||
// When the probe payload reports a restricted job type list that omits authority.vector.rebuild,
|
||||
// supportedJobTypes should NOT contain it and supportedJobTypesKnown should be true.
|
||||
const restrictedJobTypesState = normalizeAuthorityCapabilityState(
|
||||
{
|
||||
installed: true,
|
||||
healthy: true,
|
||||
features: ["sql", "trivium", "jobs", "transfers.fs"],
|
||||
jobs: {
|
||||
builtinTypes: ["delay", "sql.backup", "trivium.flush", "fs.import-jsonl"],
|
||||
registry: {
|
||||
jobTypes: ["delay", "sql.backup", "trivium.flush", "fs.import-jsonl"],
|
||||
entries: [{ type: "delay" }],
|
||||
},
|
||||
},
|
||||
},
|
||||
defaultSettings,
|
||||
);
|
||||
assert.equal(restrictedJobTypesState.supportedJobTypesKnown, true);
|
||||
assert.equal(
|
||||
restrictedJobTypesState.supportedJobTypes.includes("authority.vector.rebuild"),
|
||||
false,
|
||||
);
|
||||
|
||||
const authorityProbeJobTypesState = normalizeAuthorityProbeResponse(
|
||||
{
|
||||
healthy: true,
|
||||
features: {
|
||||
sql: { queryPage: true },
|
||||
trivium: { upsert: true },
|
||||
jobs: {
|
||||
background: true,
|
||||
builtinTypes: ["delay", "sql.backup", "trivium.flush", "fs.import-jsonl"],
|
||||
},
|
||||
transfers: { fs: true },
|
||||
},
|
||||
jobs: {
|
||||
builtinTypes: ["delay", "sql.backup", "trivium.flush", "fs.import-jsonl"],
|
||||
registry: {
|
||||
jobTypes: ["delay", "sql.backup", "trivium.flush", "fs.import-jsonl"],
|
||||
entries: [{ type: "fs.import-jsonl" }],
|
||||
},
|
||||
},
|
||||
core: {
|
||||
health: {
|
||||
jobRegistrySummary: {
|
||||
jobTypes: ["delay", "sql.backup", "trivium.flush", "fs.import-jsonl"],
|
||||
entries: [{ type: "trivium.flush" }],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{ settings: defaultSettings, nowMs: 4000 },
|
||||
);
|
||||
assert.equal(authorityProbeJobTypesState.supportedJobTypesKnown, true);
|
||||
assert.deepEqual(authorityProbeJobTypesState.supportedJobTypes, [
|
||||
"delay",
|
||||
"fs.import-jsonl",
|
||||
"sql.backup",
|
||||
"trivium.flush",
|
||||
]);
|
||||
assert.equal(
|
||||
authorityProbeJobTypesState.supportedJobTypes.includes("authority.vector.rebuild"),
|
||||
false,
|
||||
);
|
||||
|
||||
const renormalizedJobTypesState = normalizeAuthorityCapabilityState(
|
||||
authorityProbeJobTypesState,
|
||||
defaultSettings,
|
||||
);
|
||||
assert.equal(renormalizedJobTypesState.supportedJobTypesKnown, true);
|
||||
assert.deepEqual(renormalizedJobTypesState.supportedJobTypes, authorityProbeJobTypesState.supportedJobTypes);
|
||||
|
||||
const emptySupportedJobTypesProbeState = normalizeAuthorityProbeResponse(
|
||||
{
|
||||
healthy: true,
|
||||
features: {
|
||||
sql: { queryPage: true },
|
||||
trivium: { upsert: true },
|
||||
jobs: { background: true },
|
||||
transfers: { fs: true },
|
||||
},
|
||||
supportedJobTypes: [],
|
||||
},
|
||||
{ settings: defaultSettings, nowMs: 5000 },
|
||||
);
|
||||
assert.equal(emptySupportedJobTypesProbeState.supportedJobTypesKnown, true);
|
||||
assert.deepEqual(emptySupportedJobTypesProbeState.supportedJobTypes, []);
|
||||
|
||||
// Regression: Legacy probes with generic jobs.background but no explicit job type list keep
|
||||
// jobsReady === true and mark job type support as unknown (supportedJobTypesKnown === false).
|
||||
const legacyProbeState = normalizeAuthorityCapabilityState(
|
||||
{
|
||||
installed: true,
|
||||
healthy: true,
|
||||
features: ["sql", "trivium", "jobs", "transfers.fs"],
|
||||
},
|
||||
defaultSettings,
|
||||
);
|
||||
assert.equal(legacyProbeState.jobsReady, true);
|
||||
assert.equal(legacyProbeState.supportedJobTypesKnown, false);
|
||||
assert.deepEqual(legacyProbeState.supportedJobTypes, []);
|
||||
|
||||
const defaultCapabilityState = normalizeAuthorityCapabilityState(
|
||||
createDefaultAuthorityCapabilityState(),
|
||||
defaultSettings,
|
||||
);
|
||||
assert.equal(defaultCapabilityState.supportedJobTypesKnown, false);
|
||||
assert.deepEqual(defaultCapabilityState.supportedJobTypes, []);
|
||||
|
||||
console.log("authority-capabilities tests passed");
|
||||
|
||||
Reference in New Issue
Block a user