Guide 03

Extensibility architecture

These guides are written in English. · Building with an AI assistant?

Point your LLM at the docs so it understands them faster — it can also explain or translate the guides for you. Load the full documentation as a single file, or add any page's Markdown by appending .md to its URL. Works with Cursor (Add Docs), Claude, ChatGPT, Copilot and other LLMs.

Your extension  ──codes against──▶  @kbbridge/genexus-sdk  ──implemented by──▶  KB Editor
(registers providers)               (PatternExtensionAPI,                       (parses .gxPattern,
                                     IPattern* interfaces,                        renders tree,
                                     PatternInstanceElement)                      calls your providers)

Your extension depends only on the SDK contract (vendored, MIT, no runtime deps), never on KB Editor internals. KB Editor hands you the API object at runtime.

Activation & registration

  1. VS Code activates your extension. Your package.json declares "extensionDependencies": ["kbbridge.genexus-visual-editor"], so KB Editor is present.
  2. You obtain the API and register providers per pattern type:
    const kb = vscode.extensions.getExtension('kbbridge.genexus-visual-editor');
    const api = await kb.activate();   // resolves KB Editor's exported API
    api.patternAPI.registerCustomTypeSupport('WorkWith', customTypes);
    api.patternAPI.registerEditorHelper('WorkWith', editorHelper);
    

    Tolerate activation ordering. extensionDependencies should make KB Editor activate first, but on some setups it doesn't — your extension may run before KB Editor has populated its exports, so api.patternAPI is momentarily missing. Don't give up on the first try: retry acquiring it for a few seconds (the starter and Work With activate() ship an acquirePatternAPI helper that does exactly this).

  3. You dispose (unregister) on deactivate.

One extension can register several pattern types.

How KB Editor calls you

  • For a custom(<Id>) property → getTypeEditor(Id) then getValues(context).
  • When rendering a node → customShowElement(element, context) (caption/icon) and getCommands(element) (context commands).
  • When the user runs a command → the command's exec().

Context objects carry the current node, property, values, pattern type, instance name, file path, and (optionally) a KB object cache.

Graceful degradation

Missing provider ⇒ KB Editor falls back: plain text for custom types, default captions, no commands. Provider callbacks must fail soft (return empty / {handled:false}), never throw.

One package or two?

For a single pattern, one package is enough. If you ship many patterns and want to share code, you can split into a shared helper library + a patterns extension. That is an optimization, not a requirement.

Deeper, build-it version: each project's ai/ARCHITECTURE.md and ai/SDK-REFERENCE.md.

Next: The extensibility mechanisms.