Skip to content

feat(workbench): configurable entity types (global default + per-KB override) - #200

Merged
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config
Jul 22, 2026
Merged

feat(workbench): configurable entity types (global default + per-KB override)#200
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config

Conversation

@KylinMountain

Copy link
Copy Markdown
Collaborator

Makes the entity-extraction vocabulary (entity_types) user-configurable — a global default plus a per-KB override — surfacing a setting the compiler already honored but that was previously only editable by hand-writing config.yaml.

Backend (92f8f41)

entity_types now flows through the config read/write API, layering global.yaml → KB config.yaml exactly like the other config scalars:

  • a KB list overrides the global list wholesale; an explicit null inherits; unset falls back to DEFAULT_ENTITY_TYPES (person/organization/place/product/work/event/other).
  • GLOBAL_SCALAR_KEYS gains entity_types (the value-not-None-wins layering + per-key sources tracking is type-agnostic, so it works for a list).
  • GET/PATCH /api/v1/kb/config and GET/PATCH /api/v1/config carry entity_types. Reads report the cleaned effective list (resolve_entity_types: lowercased, charset-restricted, deduped, "other" ensured) plus the raw global value for the inherited badge.
  • The compiler already consumed config["entity_types"] via resolve_entity_types; nothing there changed.

Frontend (9abd2bb)

  • EntityTypesEditor: a shared chips editor — Enter/comma to add, × to remove, "other" rendered as a fixed "always included" chip, IME-safe composition.
  • KB settings sheet: an EntityTypesRow with the same inherit/override Switch as the scalar rows — override on seeds + persists the KB's own list, off reverts via null; the inherited state shows the global/default list as a badge. Each chip change persists and adopts the server-cleaned response.
  • Global Settings (general tab): a global chips editor, order-sensitive diff into the save patch (joins the existing dirty/save-bar flow).
  • Both surfaces show a "changes affect future recompiles only; existing entity pages keep their type" note.

Semantics

  • Per-KB list replaces the global list (not merged) — same as a scalar override.
  • "other" is always ensured server-side (the coercion fallback), shown as non-removable.
  • Changing the vocabulary only affects future compiles; existing entity pages keep their type: until recompiled.

Verification

Backend pytest1240 passed, mypy/ruff clean; new tests cover KB override (cleaned + source kb) + null revert, global patch, and global-source inheritance. Frontend npm run build green (i18n guard: zh/en key sets identical across common/kbSettings/settings). Manually exercised on a running openkb-web.

Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG

… API
entity_types (the entity-extraction vocabulary) is now surfaced through the
config read/write API, layering global.yaml -> KB config.yaml like the other
scalars: a KB list overrides the global list wholesale, an explicit null
inherits, and unset falls back to DEFAULT_ENTITY_TYPES. The compiler already
consumed config["entity_types"] via resolve_entity_types; this just exposes it.
- GLOBAL_SCALAR_KEYS gains "entity_types" (layering + per-key `sources` tracking;
the value-not-None-wins rule is type-agnostic, so it works for a list).
- _KbConfigWritable / GlobalConfigValues / KbConfigResponse / GlobalConfigResponse
carry entity_types; read_kb_config/read_global_config report the cleaned
EFFECTIVE list (resolve_entity_types) plus the raw global value for the badge.
- PATCH /api/v1/kb/config and PATCH /api/v1/config accept entity_types.
Tests: KB override (cleaned + source 'kb') + null revert, global patch, global
inheritance; updated the global-defaults shape assertion. Frontend UI follows.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…r-KB override)
- EntityTypesEditor: shared controlled chips editor (Enter/comma to add, x to
remove; "other" is a fixed always-included chip; IME-safe composition).
- KbSettingsSheet: an EntityTypesRow with the same inherit/override Switch as the
scalar rows — turning override on seeds+persists the KB's own list, off reverts
via null; inherited state shows the global/default list as a badge. Each chip
change persists and adopts the server-cleaned response.
- Settings (general tab): a global entity-types chips editor, order-sensitive
diff into the save patch (joins the existing dirty/SaveBar flow).
- "changes affect future recompiles only" note on both surfaces.
New keys in common/kbSettings/settings (zh + en, identical sets). Build green
(i18n guard OK). Backend was committed in 92f8f41.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…y-list inherit, silent reads, set-diff
- config: define DEFAULT_ENTITY_TYPES before DEFAULT_CONFIG and add
`entity_types` to DEFAULT_CONFIG so the key layers like every other
GLOBAL_SCALAR_KEY and always appears in the effective config (#1).
- config: resolve_effective_config treats an empty entity_types list the
same as null → inherit, so a KB that cleared its override doesn't pin an
empty vocabulary (#2).
- config: resolve_entity_types(config, *, warn=True); config-read paths pass
warn=False so a plain GET doesn't spam coercion warnings (#4).
- api_config: both read paths call resolve_entity_types(..., warn=False).
- KbSettingsSheet: inherited badge shows the effective list, not
`globalValue ?? effective`; drop the now-unused globalValue prop (#3).
- Settings: global entity_types diff is order-insensitive — the vocabulary
is a set, so re-adding a removed type is not a change (#6).
Backend pytest 1240 passed; ruff/format/mypy clean; frontend build green.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
@KylinMountain
KylinMountain merged commit ff54396 into mainJul 22, 2026
4 checks passed
@KylinMountain
KylinMountain deleted the feat/workbench-entity-types-config branch July 22, 2026 03:44
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
feat(workbench): configurable entity types (global default + per-KB override) by KylinMountain · Pull Request #200 · VectifyAI/OpenKB · GitHub
Skip to content

feat(workbench): configurable entity types (global default + per-KB override) - #200

Merged
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config
Jul 22, 2026
Merged

feat(workbench): configurable entity types (global default + per-KB override)#200
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config

Conversation

@KylinMountain

Copy link
Copy Markdown
Collaborator

Makes the entity-extraction vocabulary (entity_types) user-configurable — a global default plus a per-KB override — surfacing a setting the compiler already honored but that was previously only editable by hand-writing config.yaml.

Backend (92f8f41)

entity_types now flows through the config read/write API, layering global.yaml → KB config.yaml exactly like the other config scalars:

  • a KB list overrides the global list wholesale; an explicit null inherits; unset falls back to DEFAULT_ENTITY_TYPES (person/organization/place/product/work/event/other).
  • GLOBAL_SCALAR_KEYS gains entity_types (the value-not-None-wins layering + per-key sources tracking is type-agnostic, so it works for a list).
  • GET/PATCH /api/v1/kb/config and GET/PATCH /api/v1/config carry entity_types. Reads report the cleaned effective list (resolve_entity_types: lowercased, charset-restricted, deduped, "other" ensured) plus the raw global value for the inherited badge.
  • The compiler already consumed config["entity_types"] via resolve_entity_types; nothing there changed.

Frontend (9abd2bb)

  • EntityTypesEditor: a shared chips editor — Enter/comma to add, × to remove, "other" rendered as a fixed "always included" chip, IME-safe composition.
  • KB settings sheet: an EntityTypesRow with the same inherit/override Switch as the scalar rows — override on seeds + persists the KB's own list, off reverts via null; the inherited state shows the global/default list as a badge. Each chip change persists and adopts the server-cleaned response.
  • Global Settings (general tab): a global chips editor, order-sensitive diff into the save patch (joins the existing dirty/save-bar flow).
  • Both surfaces show a "changes affect future recompiles only; existing entity pages keep their type" note.

Semantics

  • Per-KB list replaces the global list (not merged) — same as a scalar override.
  • "other" is always ensured server-side (the coercion fallback), shown as non-removable.
  • Changing the vocabulary only affects future compiles; existing entity pages keep their type: until recompiled.

Verification

Backend pytest1240 passed, mypy/ruff clean; new tests cover KB override (cleaned + source kb) + null revert, global patch, and global-source inheritance. Frontend npm run build green (i18n guard: zh/en key sets identical across common/kbSettings/settings). Manually exercised on a running openkb-web.

Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG

… API
entity_types (the entity-extraction vocabulary) is now surfaced through the
config read/write API, layering global.yaml -> KB config.yaml like the other
scalars: a KB list overrides the global list wholesale, an explicit null
inherits, and unset falls back to DEFAULT_ENTITY_TYPES. The compiler already
consumed config["entity_types"] via resolve_entity_types; this just exposes it.
- GLOBAL_SCALAR_KEYS gains "entity_types" (layering + per-key `sources` tracking;
the value-not-None-wins rule is type-agnostic, so it works for a list).
- _KbConfigWritable / GlobalConfigValues / KbConfigResponse / GlobalConfigResponse
carry entity_types; read_kb_config/read_global_config report the cleaned
EFFECTIVE list (resolve_entity_types) plus the raw global value for the badge.
- PATCH /api/v1/kb/config and PATCH /api/v1/config accept entity_types.
Tests: KB override (cleaned + source 'kb') + null revert, global patch, global
inheritance; updated the global-defaults shape assertion. Frontend UI follows.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…r-KB override)
- EntityTypesEditor: shared controlled chips editor (Enter/comma to add, x to
remove; "other" is a fixed always-included chip; IME-safe composition).
- KbSettingsSheet: an EntityTypesRow with the same inherit/override Switch as the
scalar rows — turning override on seeds+persists the KB's own list, off reverts
via null; inherited state shows the global/default list as a badge. Each chip
change persists and adopts the server-cleaned response.
- Settings (general tab): a global entity-types chips editor, order-sensitive
diff into the save patch (joins the existing dirty/SaveBar flow).
- "changes affect future recompiles only" note on both surfaces.
New keys in common/kbSettings/settings (zh + en, identical sets). Build green
(i18n guard OK). Backend was committed in 92f8f41.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…y-list inherit, silent reads, set-diff
- config: define DEFAULT_ENTITY_TYPES before DEFAULT_CONFIG and add
`entity_types` to DEFAULT_CONFIG so the key layers like every other
GLOBAL_SCALAR_KEY and always appears in the effective config (#1).
- config: resolve_effective_config treats an empty entity_types list the
same as null → inherit, so a KB that cleared its override doesn't pin an
empty vocabulary (#2).
- config: resolve_entity_types(config, *, warn=True); config-read paths pass
warn=False so a plain GET doesn't spam coercion warnings (#4).
- api_config: both read paths call resolve_entity_types(..., warn=False).
- KbSettingsSheet: inherited badge shows the effective list, not
`globalValue ?? effective`; drop the now-unused globalValue prop (#3).
- Settings: global entity_types diff is order-insensitive — the vocabulary
is a set, so re-adding a removed type is not a change (#6).
Backend pytest 1240 passed; ruff/format/mypy clean; frontend build green.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
@KylinMountain
KylinMountain merged commit ff54396 into mainJul 22, 2026
4 checks passed
@KylinMountain
KylinMountain deleted the feat/workbench-entity-types-config branch July 22, 2026 03:44
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(workbench): configurable entity types (global default + per-KB override) by KylinMountain · Pull Request #200 · VectifyAI/OpenKB · GitHub
Skip to content

feat(workbench): configurable entity types (global default + per-KB override) - #200

Merged
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config
Jul 22, 2026
Merged

feat(workbench): configurable entity types (global default + per-KB override)#200
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config

Conversation

@KylinMountain

Copy link
Copy Markdown
Collaborator

Makes the entity-extraction vocabulary (entity_types) user-configurable — a global default plus a per-KB override — surfacing a setting the compiler already honored but that was previously only editable by hand-writing config.yaml.

Backend (92f8f41)

entity_types now flows through the config read/write API, layering global.yaml → KB config.yaml exactly like the other config scalars:

  • a KB list overrides the global list wholesale; an explicit null inherits; unset falls back to DEFAULT_ENTITY_TYPES (person/organization/place/product/work/event/other).
  • GLOBAL_SCALAR_KEYS gains entity_types (the value-not-None-wins layering + per-key sources tracking is type-agnostic, so it works for a list).
  • GET/PATCH /api/v1/kb/config and GET/PATCH /api/v1/config carry entity_types. Reads report the cleaned effective list (resolve_entity_types: lowercased, charset-restricted, deduped, "other" ensured) plus the raw global value for the inherited badge.
  • The compiler already consumed config["entity_types"] via resolve_entity_types; nothing there changed.

Frontend (9abd2bb)

  • EntityTypesEditor: a shared chips editor — Enter/comma to add, × to remove, "other" rendered as a fixed "always included" chip, IME-safe composition.
  • KB settings sheet: an EntityTypesRow with the same inherit/override Switch as the scalar rows — override on seeds + persists the KB's own list, off reverts via null; the inherited state shows the global/default list as a badge. Each chip change persists and adopts the server-cleaned response.
  • Global Settings (general tab): a global chips editor, order-sensitive diff into the save patch (joins the existing dirty/save-bar flow).
  • Both surfaces show a "changes affect future recompiles only; existing entity pages keep their type" note.

Semantics

  • Per-KB list replaces the global list (not merged) — same as a scalar override.
  • "other" is always ensured server-side (the coercion fallback), shown as non-removable.
  • Changing the vocabulary only affects future compiles; existing entity pages keep their type: until recompiled.

Verification

Backend pytest1240 passed, mypy/ruff clean; new tests cover KB override (cleaned + source kb) + null revert, global patch, and global-source inheritance. Frontend npm run build green (i18n guard: zh/en key sets identical across common/kbSettings/settings). Manually exercised on a running openkb-web.

Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG

… API
entity_types (the entity-extraction vocabulary) is now surfaced through the
config read/write API, layering global.yaml -> KB config.yaml like the other
scalars: a KB list overrides the global list wholesale, an explicit null
inherits, and unset falls back to DEFAULT_ENTITY_TYPES. The compiler already
consumed config["entity_types"] via resolve_entity_types; this just exposes it.
- GLOBAL_SCALAR_KEYS gains "entity_types" (layering + per-key `sources` tracking;
the value-not-None-wins rule is type-agnostic, so it works for a list).
- _KbConfigWritable / GlobalConfigValues / KbConfigResponse / GlobalConfigResponse
carry entity_types; read_kb_config/read_global_config report the cleaned
EFFECTIVE list (resolve_entity_types) plus the raw global value for the badge.
- PATCH /api/v1/kb/config and PATCH /api/v1/config accept entity_types.
Tests: KB override (cleaned + source 'kb') + null revert, global patch, global
inheritance; updated the global-defaults shape assertion. Frontend UI follows.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…r-KB override)
- EntityTypesEditor: shared controlled chips editor (Enter/comma to add, x to
remove; "other" is a fixed always-included chip; IME-safe composition).
- KbSettingsSheet: an EntityTypesRow with the same inherit/override Switch as the
scalar rows — turning override on seeds+persists the KB's own list, off reverts
via null; inherited state shows the global/default list as a badge. Each chip
change persists and adopts the server-cleaned response.
- Settings (general tab): a global entity-types chips editor, order-sensitive
diff into the save patch (joins the existing dirty/SaveBar flow).
- "changes affect future recompiles only" note on both surfaces.
New keys in common/kbSettings/settings (zh + en, identical sets). Build green
(i18n guard OK). Backend was committed in 92f8f41.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…y-list inherit, silent reads, set-diff
- config: define DEFAULT_ENTITY_TYPES before DEFAULT_CONFIG and add
`entity_types` to DEFAULT_CONFIG so the key layers like every other
GLOBAL_SCALAR_KEY and always appears in the effective config (#1).
- config: resolve_effective_config treats an empty entity_types list the
same as null → inherit, so a KB that cleared its override doesn't pin an
empty vocabulary (#2).
- config: resolve_entity_types(config, *, warn=True); config-read paths pass
warn=False so a plain GET doesn't spam coercion warnings (#4).
- api_config: both read paths call resolve_entity_types(..., warn=False).
- KbSettingsSheet: inherited badge shows the effective list, not
`globalValue ?? effective`; drop the now-unused globalValue prop (#3).
- Settings: global entity_types diff is order-insensitive — the vocabulary
is a set, so re-adding a removed type is not a change (#6).
Backend pytest 1240 passed; ruff/format/mypy clean; frontend build green.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
@KylinMountain
KylinMountain merged commit ff54396 into mainJul 22, 2026
4 checks passed
@KylinMountain
KylinMountain deleted the feat/workbench-entity-types-config branch July 22, 2026 03:44
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(workbench): configurable entity types (global default + per-KB override) by KylinMountain · Pull Request #200 · VectifyAI/OpenKB · GitHub
Skip to content

feat(workbench): configurable entity types (global default + per-KB override) - #200

Merged
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config
Jul 22, 2026
Merged

feat(workbench): configurable entity types (global default + per-KB override)#200
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config

Conversation

@KylinMountain

Copy link
Copy Markdown
Collaborator

Makes the entity-extraction vocabulary (entity_types) user-configurable — a global default plus a per-KB override — surfacing a setting the compiler already honored but that was previously only editable by hand-writing config.yaml.

Backend (92f8f41)

entity_types now flows through the config read/write API, layering global.yaml → KB config.yaml exactly like the other config scalars:

  • a KB list overrides the global list wholesale; an explicit null inherits; unset falls back to DEFAULT_ENTITY_TYPES (person/organization/place/product/work/event/other).
  • GLOBAL_SCALAR_KEYS gains entity_types (the value-not-None-wins layering + per-key sources tracking is type-agnostic, so it works for a list).
  • GET/PATCH /api/v1/kb/config and GET/PATCH /api/v1/config carry entity_types. Reads report the cleaned effective list (resolve_entity_types: lowercased, charset-restricted, deduped, "other" ensured) plus the raw global value for the inherited badge.
  • The compiler already consumed config["entity_types"] via resolve_entity_types; nothing there changed.

Frontend (9abd2bb)

  • EntityTypesEditor: a shared chips editor — Enter/comma to add, × to remove, "other" rendered as a fixed "always included" chip, IME-safe composition.
  • KB settings sheet: an EntityTypesRow with the same inherit/override Switch as the scalar rows — override on seeds + persists the KB's own list, off reverts via null; the inherited state shows the global/default list as a badge. Each chip change persists and adopts the server-cleaned response.
  • Global Settings (general tab): a global chips editor, order-sensitive diff into the save patch (joins the existing dirty/save-bar flow).
  • Both surfaces show a "changes affect future recompiles only; existing entity pages keep their type" note.

Semantics

  • Per-KB list replaces the global list (not merged) — same as a scalar override.
  • "other" is always ensured server-side (the coercion fallback), shown as non-removable.
  • Changing the vocabulary only affects future compiles; existing entity pages keep their type: until recompiled.

Verification

Backend pytest1240 passed, mypy/ruff clean; new tests cover KB override (cleaned + source kb) + null revert, global patch, and global-source inheritance. Frontend npm run build green (i18n guard: zh/en key sets identical across common/kbSettings/settings). Manually exercised on a running openkb-web.

Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG

… API
entity_types (the entity-extraction vocabulary) is now surfaced through the
config read/write API, layering global.yaml -> KB config.yaml like the other
scalars: a KB list overrides the global list wholesale, an explicit null
inherits, and unset falls back to DEFAULT_ENTITY_TYPES. The compiler already
consumed config["entity_types"] via resolve_entity_types; this just exposes it.
- GLOBAL_SCALAR_KEYS gains "entity_types" (layering + per-key `sources` tracking;
the value-not-None-wins rule is type-agnostic, so it works for a list).
- _KbConfigWritable / GlobalConfigValues / KbConfigResponse / GlobalConfigResponse
carry entity_types; read_kb_config/read_global_config report the cleaned
EFFECTIVE list (resolve_entity_types) plus the raw global value for the badge.
- PATCH /api/v1/kb/config and PATCH /api/v1/config accept entity_types.
Tests: KB override (cleaned + source 'kb') + null revert, global patch, global
inheritance; updated the global-defaults shape assertion. Frontend UI follows.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…r-KB override)
- EntityTypesEditor: shared controlled chips editor (Enter/comma to add, x to
remove; "other" is a fixed always-included chip; IME-safe composition).
- KbSettingsSheet: an EntityTypesRow with the same inherit/override Switch as the
scalar rows — turning override on seeds+persists the KB's own list, off reverts
via null; inherited state shows the global/default list as a badge. Each chip
change persists and adopts the server-cleaned response.
- Settings (general tab): a global entity-types chips editor, order-sensitive
diff into the save patch (joins the existing dirty/SaveBar flow).
- "changes affect future recompiles only" note on both surfaces.
New keys in common/kbSettings/settings (zh + en, identical sets). Build green
(i18n guard OK). Backend was committed in 92f8f41.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…y-list inherit, silent reads, set-diff
- config: define DEFAULT_ENTITY_TYPES before DEFAULT_CONFIG and add
`entity_types` to DEFAULT_CONFIG so the key layers like every other
GLOBAL_SCALAR_KEY and always appears in the effective config (#1).
- config: resolve_effective_config treats an empty entity_types list the
same as null → inherit, so a KB that cleared its override doesn't pin an
empty vocabulary (#2).
- config: resolve_entity_types(config, *, warn=True); config-read paths pass
warn=False so a plain GET doesn't spam coercion warnings (#4).
- api_config: both read paths call resolve_entity_types(..., warn=False).
- KbSettingsSheet: inherited badge shows the effective list, not
`globalValue ?? effective`; drop the now-unused globalValue prop (#3).
- Settings: global entity_types diff is order-insensitive — the vocabulary
is a set, so re-adding a removed type is not a change (#6).
Backend pytest 1240 passed; ruff/format/mypy clean; frontend build green.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
@KylinMountain
KylinMountain merged commit ff54396 into mainJul 22, 2026
4 checks passed
@KylinMountain
KylinMountain deleted the feat/workbench-entity-types-config branch July 22, 2026 03:44
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' feat(workbench): configurable entity types (global default + per-KB override) by KylinMountain · Pull Request #200 · VectifyAI/OpenKB · GitHub
Skip to content

feat(workbench): configurable entity types (global default + per-KB override) - #200

Merged
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config
Jul 22, 2026
Merged

feat(workbench): configurable entity types (global default + per-KB override)#200
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config

Conversation

@KylinMountain

Copy link
Copy Markdown
Collaborator

Makes the entity-extraction vocabulary (entity_types) user-configurable — a global default plus a per-KB override — surfacing a setting the compiler already honored but that was previously only editable by hand-writing config.yaml.

Backend (92f8f41)

entity_types now flows through the config read/write API, layering global.yaml → KB config.yaml exactly like the other config scalars:

  • a KB list overrides the global list wholesale; an explicit null inherits; unset falls back to DEFAULT_ENTITY_TYPES (person/organization/place/product/work/event/other).
  • GLOBAL_SCALAR_KEYS gains entity_types (the value-not-None-wins layering + per-key sources tracking is type-agnostic, so it works for a list).
  • GET/PATCH /api/v1/kb/config and GET/PATCH /api/v1/config carry entity_types. Reads report the cleaned effective list (resolve_entity_types: lowercased, charset-restricted, deduped, "other" ensured) plus the raw global value for the inherited badge.
  • The compiler already consumed config["entity_types"] via resolve_entity_types; nothing there changed.

Frontend (9abd2bb)

  • EntityTypesEditor: a shared chips editor — Enter/comma to add, × to remove, "other" rendered as a fixed "always included" chip, IME-safe composition.
  • KB settings sheet: an EntityTypesRow with the same inherit/override Switch as the scalar rows — override on seeds + persists the KB's own list, off reverts via null; the inherited state shows the global/default list as a badge. Each chip change persists and adopts the server-cleaned response.
  • Global Settings (general tab): a global chips editor, order-sensitive diff into the save patch (joins the existing dirty/save-bar flow).
  • Both surfaces show a "changes affect future recompiles only; existing entity pages keep their type" note.

Semantics

  • Per-KB list replaces the global list (not merged) — same as a scalar override.
  • "other" is always ensured server-side (the coercion fallback), shown as non-removable.
  • Changing the vocabulary only affects future compiles; existing entity pages keep their type: until recompiled.

Verification

Backend pytest1240 passed, mypy/ruff clean; new tests cover KB override (cleaned + source kb) + null revert, global patch, and global-source inheritance. Frontend npm run build green (i18n guard: zh/en key sets identical across common/kbSettings/settings). Manually exercised on a running openkb-web.

Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG

… API
entity_types (the entity-extraction vocabulary) is now surfaced through the
config read/write API, layering global.yaml -> KB config.yaml like the other
scalars: a KB list overrides the global list wholesale, an explicit null
inherits, and unset falls back to DEFAULT_ENTITY_TYPES. The compiler already
consumed config["entity_types"] via resolve_entity_types; this just exposes it.
- GLOBAL_SCALAR_KEYS gains "entity_types" (layering + per-key `sources` tracking;
the value-not-None-wins rule is type-agnostic, so it works for a list).
- _KbConfigWritable / GlobalConfigValues / KbConfigResponse / GlobalConfigResponse
carry entity_types; read_kb_config/read_global_config report the cleaned
EFFECTIVE list (resolve_entity_types) plus the raw global value for the badge.
- PATCH /api/v1/kb/config and PATCH /api/v1/config accept entity_types.
Tests: KB override (cleaned + source 'kb') + null revert, global patch, global
inheritance; updated the global-defaults shape assertion. Frontend UI follows.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…r-KB override)
- EntityTypesEditor: shared controlled chips editor (Enter/comma to add, x to
remove; "other" is a fixed always-included chip; IME-safe composition).
- KbSettingsSheet: an EntityTypesRow with the same inherit/override Switch as the
scalar rows — turning override on seeds+persists the KB's own list, off reverts
via null; inherited state shows the global/default list as a badge. Each chip
change persists and adopts the server-cleaned response.
- Settings (general tab): a global entity-types chips editor, order-sensitive
diff into the save patch (joins the existing dirty/SaveBar flow).
- "changes affect future recompiles only" note on both surfaces.
New keys in common/kbSettings/settings (zh + en, identical sets). Build green
(i18n guard OK). Backend was committed in 92f8f41.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…y-list inherit, silent reads, set-diff
- config: define DEFAULT_ENTITY_TYPES before DEFAULT_CONFIG and add
`entity_types` to DEFAULT_CONFIG so the key layers like every other
GLOBAL_SCALAR_KEY and always appears in the effective config (#1).
- config: resolve_effective_config treats an empty entity_types list the
same as null → inherit, so a KB that cleared its override doesn't pin an
empty vocabulary (#2).
- config: resolve_entity_types(config, *, warn=True); config-read paths pass
warn=False so a plain GET doesn't spam coercion warnings (#4).
- api_config: both read paths call resolve_entity_types(..., warn=False).
- KbSettingsSheet: inherited badge shows the effective list, not
`globalValue ?? effective`; drop the now-unused globalValue prop (#3).
- Settings: global entity_types diff is order-insensitive — the vocabulary
is a set, so re-adding a removed type is not a change (#6).
Backend pytest 1240 passed; ruff/format/mypy clean; frontend build green.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
@KylinMountain
KylinMountain merged commit ff54396 into mainJul 22, 2026
4 checks passed
@KylinMountain
KylinMountain deleted the feat/workbench-entity-types-config branch July 22, 2026 03:44
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(workbench): configurable entity types (global default + per-KB override) by KylinMountain · Pull Request #200 · VectifyAI/OpenKB · GitHub
Skip to content

feat(workbench): configurable entity types (global default + per-KB override) - #200

Merged
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config
Jul 22, 2026
Merged

feat(workbench): configurable entity types (global default + per-KB override)#200
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config

Conversation

@KylinMountain

Copy link
Copy Markdown
Collaborator

Makes the entity-extraction vocabulary (entity_types) user-configurable — a global default plus a per-KB override — surfacing a setting the compiler already honored but that was previously only editable by hand-writing config.yaml.

Backend (92f8f41)

entity_types now flows through the config read/write API, layering global.yaml → KB config.yaml exactly like the other config scalars:

  • a KB list overrides the global list wholesale; an explicit null inherits; unset falls back to DEFAULT_ENTITY_TYPES (person/organization/place/product/work/event/other).
  • GLOBAL_SCALAR_KEYS gains entity_types (the value-not-None-wins layering + per-key sources tracking is type-agnostic, so it works for a list).
  • GET/PATCH /api/v1/kb/config and GET/PATCH /api/v1/config carry entity_types. Reads report the cleaned effective list (resolve_entity_types: lowercased, charset-restricted, deduped, "other" ensured) plus the raw global value for the inherited badge.
  • The compiler already consumed config["entity_types"] via resolve_entity_types; nothing there changed.

Frontend (9abd2bb)

  • EntityTypesEditor: a shared chips editor — Enter/comma to add, × to remove, "other" rendered as a fixed "always included" chip, IME-safe composition.
  • KB settings sheet: an EntityTypesRow with the same inherit/override Switch as the scalar rows — override on seeds + persists the KB's own list, off reverts via null; the inherited state shows the global/default list as a badge. Each chip change persists and adopts the server-cleaned response.
  • Global Settings (general tab): a global chips editor, order-sensitive diff into the save patch (joins the existing dirty/save-bar flow).
  • Both surfaces show a "changes affect future recompiles only; existing entity pages keep their type" note.

Semantics

  • Per-KB list replaces the global list (not merged) — same as a scalar override.
  • "other" is always ensured server-side (the coercion fallback), shown as non-removable.
  • Changing the vocabulary only affects future compiles; existing entity pages keep their type: until recompiled.

Verification

Backend pytest1240 passed, mypy/ruff clean; new tests cover KB override (cleaned + source kb) + null revert, global patch, and global-source inheritance. Frontend npm run build green (i18n guard: zh/en key sets identical across common/kbSettings/settings). Manually exercised on a running openkb-web.

Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG

… API
entity_types (the entity-extraction vocabulary) is now surfaced through the
config read/write API, layering global.yaml -> KB config.yaml like the other
scalars: a KB list overrides the global list wholesale, an explicit null
inherits, and unset falls back to DEFAULT_ENTITY_TYPES. The compiler already
consumed config["entity_types"] via resolve_entity_types; this just exposes it.
- GLOBAL_SCALAR_KEYS gains "entity_types" (layering + per-key `sources` tracking;
the value-not-None-wins rule is type-agnostic, so it works for a list).
- _KbConfigWritable / GlobalConfigValues / KbConfigResponse / GlobalConfigResponse
carry entity_types; read_kb_config/read_global_config report the cleaned
EFFECTIVE list (resolve_entity_types) plus the raw global value for the badge.
- PATCH /api/v1/kb/config and PATCH /api/v1/config accept entity_types.
Tests: KB override (cleaned + source 'kb') + null revert, global patch, global
inheritance; updated the global-defaults shape assertion. Frontend UI follows.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…r-KB override)
- EntityTypesEditor: shared controlled chips editor (Enter/comma to add, x to
remove; "other" is a fixed always-included chip; IME-safe composition).
- KbSettingsSheet: an EntityTypesRow with the same inherit/override Switch as the
scalar rows — turning override on seeds+persists the KB's own list, off reverts
via null; inherited state shows the global/default list as a badge. Each chip
change persists and adopts the server-cleaned response.
- Settings (general tab): a global entity-types chips editor, order-sensitive
diff into the save patch (joins the existing dirty/SaveBar flow).
- "changes affect future recompiles only" note on both surfaces.
New keys in common/kbSettings/settings (zh + en, identical sets). Build green
(i18n guard OK). Backend was committed in 92f8f41.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…y-list inherit, silent reads, set-diff
- config: define DEFAULT_ENTITY_TYPES before DEFAULT_CONFIG and add
`entity_types` to DEFAULT_CONFIG so the key layers like every other
GLOBAL_SCALAR_KEY and always appears in the effective config (#1).
- config: resolve_effective_config treats an empty entity_types list the
same as null → inherit, so a KB that cleared its override doesn't pin an
empty vocabulary (#2).
- config: resolve_entity_types(config, *, warn=True); config-read paths pass
warn=False so a plain GET doesn't spam coercion warnings (#4).
- api_config: both read paths call resolve_entity_types(..., warn=False).
- KbSettingsSheet: inherited badge shows the effective list, not
`globalValue ?? effective`; drop the now-unused globalValue prop (#3).
- Settings: global entity_types diff is order-insensitive — the vocabulary
is a set, so re-adding a removed type is not a change (#6).
Backend pytest 1240 passed; ruff/format/mypy clean; frontend build green.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
@KylinMountain
KylinMountain merged commit ff54396 into mainJul 22, 2026
4 checks passed
@KylinMountain
KylinMountain deleted the feat/workbench-entity-types-config branch July 22, 2026 03:44
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(workbench): configurable entity types (global default + per-KB override) by KylinMountain · Pull Request #200 · VectifyAI/OpenKB · GitHub
Skip to content

feat(workbench): configurable entity types (global default + per-KB override) - #200

Merged
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config
Jul 22, 2026
Merged

feat(workbench): configurable entity types (global default + per-KB override)#200
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config

Conversation

@KylinMountain

Copy link
Copy Markdown
Collaborator

Makes the entity-extraction vocabulary (entity_types) user-configurable — a global default plus a per-KB override — surfacing a setting the compiler already honored but that was previously only editable by hand-writing config.yaml.

Backend (92f8f41)

entity_types now flows through the config read/write API, layering global.yaml → KB config.yaml exactly like the other config scalars:

  • a KB list overrides the global list wholesale; an explicit null inherits; unset falls back to DEFAULT_ENTITY_TYPES (person/organization/place/product/work/event/other).
  • GLOBAL_SCALAR_KEYS gains entity_types (the value-not-None-wins layering + per-key sources tracking is type-agnostic, so it works for a list).
  • GET/PATCH /api/v1/kb/config and GET/PATCH /api/v1/config carry entity_types. Reads report the cleaned effective list (resolve_entity_types: lowercased, charset-restricted, deduped, "other" ensured) plus the raw global value for the inherited badge.
  • The compiler already consumed config["entity_types"] via resolve_entity_types; nothing there changed.

Frontend (9abd2bb)

  • EntityTypesEditor: a shared chips editor — Enter/comma to add, × to remove, "other" rendered as a fixed "always included" chip, IME-safe composition.
  • KB settings sheet: an EntityTypesRow with the same inherit/override Switch as the scalar rows — override on seeds + persists the KB's own list, off reverts via null; the inherited state shows the global/default list as a badge. Each chip change persists and adopts the server-cleaned response.
  • Global Settings (general tab): a global chips editor, order-sensitive diff into the save patch (joins the existing dirty/save-bar flow).
  • Both surfaces show a "changes affect future recompiles only; existing entity pages keep their type" note.

Semantics

  • Per-KB list replaces the global list (not merged) — same as a scalar override.
  • "other" is always ensured server-side (the coercion fallback), shown as non-removable.
  • Changing the vocabulary only affects future compiles; existing entity pages keep their type: until recompiled.

Verification

Backend pytest1240 passed, mypy/ruff clean; new tests cover KB override (cleaned + source kb) + null revert, global patch, and global-source inheritance. Frontend npm run build green (i18n guard: zh/en key sets identical across common/kbSettings/settings). Manually exercised on a running openkb-web.

Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG

… API
entity_types (the entity-extraction vocabulary) is now surfaced through the
config read/write API, layering global.yaml -> KB config.yaml like the other
scalars: a KB list overrides the global list wholesale, an explicit null
inherits, and unset falls back to DEFAULT_ENTITY_TYPES. The compiler already
consumed config["entity_types"] via resolve_entity_types; this just exposes it.
- GLOBAL_SCALAR_KEYS gains "entity_types" (layering + per-key `sources` tracking;
the value-not-None-wins rule is type-agnostic, so it works for a list).
- _KbConfigWritable / GlobalConfigValues / KbConfigResponse / GlobalConfigResponse
carry entity_types; read_kb_config/read_global_config report the cleaned
EFFECTIVE list (resolve_entity_types) plus the raw global value for the badge.
- PATCH /api/v1/kb/config and PATCH /api/v1/config accept entity_types.
Tests: KB override (cleaned + source 'kb') + null revert, global patch, global
inheritance; updated the global-defaults shape assertion. Frontend UI follows.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…r-KB override)
- EntityTypesEditor: shared controlled chips editor (Enter/comma to add, x to
remove; "other" is a fixed always-included chip; IME-safe composition).
- KbSettingsSheet: an EntityTypesRow with the same inherit/override Switch as the
scalar rows — turning override on seeds+persists the KB's own list, off reverts
via null; inherited state shows the global/default list as a badge. Each chip
change persists and adopts the server-cleaned response.
- Settings (general tab): a global entity-types chips editor, order-sensitive
diff into the save patch (joins the existing dirty/SaveBar flow).
- "changes affect future recompiles only" note on both surfaces.
New keys in common/kbSettings/settings (zh + en, identical sets). Build green
(i18n guard OK). Backend was committed in 92f8f41.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…y-list inherit, silent reads, set-diff
- config: define DEFAULT_ENTITY_TYPES before DEFAULT_CONFIG and add
`entity_types` to DEFAULT_CONFIG so the key layers like every other
GLOBAL_SCALAR_KEY and always appears in the effective config (#1).
- config: resolve_effective_config treats an empty entity_types list the
same as null → inherit, so a KB that cleared its override doesn't pin an
empty vocabulary (#2).
- config: resolve_entity_types(config, *, warn=True); config-read paths pass
warn=False so a plain GET doesn't spam coercion warnings (#4).
- api_config: both read paths call resolve_entity_types(..., warn=False).
- KbSettingsSheet: inherited badge shows the effective list, not
`globalValue ?? effective`; drop the now-unused globalValue prop (#3).
- Settings: global entity_types diff is order-insensitive — the vocabulary
is a set, so re-adding a removed type is not a change (#6).
Backend pytest 1240 passed; ruff/format/mypy clean; frontend build green.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
@KylinMountain
KylinMountain merged commit ff54396 into mainJul 22, 2026
4 checks passed
@KylinMountain
KylinMountain deleted the feat/workbench-entity-types-config branch July 22, 2026 03:44
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); feat(workbench): configurable entity types (global default + per-KB override) by KylinMountain · Pull Request #200 · VectifyAI/OpenKB · GitHub
Skip to content

feat(workbench): configurable entity types (global default + per-KB override) - #200

Merged
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config
Jul 22, 2026
Merged

feat(workbench): configurable entity types (global default + per-KB override)#200
KylinMountain merged 3 commits into
mainfrom
feat/workbench-entity-types-config

Conversation

@KylinMountain

Copy link
Copy Markdown
Collaborator

Makes the entity-extraction vocabulary (entity_types) user-configurable — a global default plus a per-KB override — surfacing a setting the compiler already honored but that was previously only editable by hand-writing config.yaml.

Backend (92f8f41)

entity_types now flows through the config read/write API, layering global.yaml → KB config.yaml exactly like the other config scalars:

  • a KB list overrides the global list wholesale; an explicit null inherits; unset falls back to DEFAULT_ENTITY_TYPES (person/organization/place/product/work/event/other).
  • GLOBAL_SCALAR_KEYS gains entity_types (the value-not-None-wins layering + per-key sources tracking is type-agnostic, so it works for a list).
  • GET/PATCH /api/v1/kb/config and GET/PATCH /api/v1/config carry entity_types. Reads report the cleaned effective list (resolve_entity_types: lowercased, charset-restricted, deduped, "other" ensured) plus the raw global value for the inherited badge.
  • The compiler already consumed config["entity_types"] via resolve_entity_types; nothing there changed.

Frontend (9abd2bb)

  • EntityTypesEditor: a shared chips editor — Enter/comma to add, × to remove, "other" rendered as a fixed "always included" chip, IME-safe composition.
  • KB settings sheet: an EntityTypesRow with the same inherit/override Switch as the scalar rows — override on seeds + persists the KB's own list, off reverts via null; the inherited state shows the global/default list as a badge. Each chip change persists and adopts the server-cleaned response.
  • Global Settings (general tab): a global chips editor, order-sensitive diff into the save patch (joins the existing dirty/save-bar flow).
  • Both surfaces show a "changes affect future recompiles only; existing entity pages keep their type" note.

Semantics

  • Per-KB list replaces the global list (not merged) — same as a scalar override.
  • "other" is always ensured server-side (the coercion fallback), shown as non-removable.
  • Changing the vocabulary only affects future compiles; existing entity pages keep their type: until recompiled.

Verification

Backend pytest1240 passed, mypy/ruff clean; new tests cover KB override (cleaned + source kb) + null revert, global patch, and global-source inheritance. Frontend npm run build green (i18n guard: zh/en key sets identical across common/kbSettings/settings). Manually exercised on a running openkb-web.

Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG

… API
entity_types (the entity-extraction vocabulary) is now surfaced through the
config read/write API, layering global.yaml -> KB config.yaml like the other
scalars: a KB list overrides the global list wholesale, an explicit null
inherits, and unset falls back to DEFAULT_ENTITY_TYPES. The compiler already
consumed config["entity_types"] via resolve_entity_types; this just exposes it.
- GLOBAL_SCALAR_KEYS gains "entity_types" (layering + per-key `sources` tracking;
the value-not-None-wins rule is type-agnostic, so it works for a list).
- _KbConfigWritable / GlobalConfigValues / KbConfigResponse / GlobalConfigResponse
carry entity_types; read_kb_config/read_global_config report the cleaned
EFFECTIVE list (resolve_entity_types) plus the raw global value for the badge.
- PATCH /api/v1/kb/config and PATCH /api/v1/config accept entity_types.
Tests: KB override (cleaned + source 'kb') + null revert, global patch, global
inheritance; updated the global-defaults shape assertion. Frontend UI follows.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…r-KB override)
- EntityTypesEditor: shared controlled chips editor (Enter/comma to add, x to
remove; "other" is a fixed always-included chip; IME-safe composition).
- KbSettingsSheet: an EntityTypesRow with the same inherit/override Switch as the
scalar rows — turning override on seeds+persists the KB's own list, off reverts
via null; inherited state shows the global/default list as a badge. Each chip
change persists and adopts the server-cleaned response.
- Settings (general tab): a global entity-types chips editor, order-sensitive
diff into the save patch (joins the existing dirty/SaveBar flow).
- "changes affect future recompiles only" note on both surfaces.
New keys in common/kbSettings/settings (zh + en, identical sets). Build green
(i18n guard OK). Backend was committed in 92f8f41.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
…y-list inherit, silent reads, set-diff
- config: define DEFAULT_ENTITY_TYPES before DEFAULT_CONFIG and add
`entity_types` to DEFAULT_CONFIG so the key layers like every other
GLOBAL_SCALAR_KEY and always appears in the effective config (#1).
- config: resolve_effective_config treats an empty entity_types list the
same as null → inherit, so a KB that cleared its override doesn't pin an
empty vocabulary (#2).
- config: resolve_entity_types(config, *, warn=True); config-read paths pass
warn=False so a plain GET doesn't spam coercion warnings (#4).
- api_config: both read paths call resolve_entity_types(..., warn=False).
- KbSettingsSheet: inherited badge shows the effective list, not
`globalValue ?? effective`; drop the now-unused globalValue prop (#3).
- Settings: global entity_types diff is order-insensitive — the vocabulary
is a set, so re-adding a removed type is not a change (#6).
Backend pytest 1240 passed; ruff/format/mypy clean; frontend build green.
Claude-Session: https://claude.ai/code/session_01XMxbhmAkxxVV8CFWCZDBaG
@KylinMountain
KylinMountain merged commit ff54396 into mainJul 22, 2026
4 checks passed
@KylinMountain
KylinMountain deleted the feat/workbench-entity-types-config branch July 22, 2026 03:44
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KylinMountain