@makaio/framework 1.0.0-dev-1779046984397
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/LICENSE +21 -0
- package/README.md +363 -0
- package/dist/account-identity-Ce1Bwrqi.mjs +1 -0
- package/dist/adapter-CbyjCE2d.mjs +1 -0
- package/dist/adapters/acp-client/index.d.mts +209 -0
- package/dist/adapters/acp-client/index.mjs +1 -0
- package/dist/adapters/config/index.d.mts +429 -0
- package/dist/adapters/config/index.mjs +1 -0
- package/dist/adapters/index.d.mts +4175 -0
- package/dist/adapters/index.mjs +11 -0
- package/dist/adapters/node.d.mts +263 -0
- package/dist/adapters/node.mjs +4 -0
- package/dist/adapters/stream-session/index.d.mts +1384 -0
- package/dist/adapters/stream-session/index.mjs +1 -0
- package/dist/adapters/stream-session/testing/index.d.mts +29 -0
- package/dist/adapters/stream-session/testing/index.mjs +1 -0
- package/dist/base-orchestrator-9z8TuA5a.d.mts +772 -0
- package/dist/bus/index.d.mts +3331 -0
- package/dist/bus/index.mjs +1 -0
- package/dist/bus-B1seC4M_.mjs +2 -0
- package/dist/capability-service-tnpR_TaB.mjs +1 -0
- package/dist/chunk-Dc06z0qk.mjs +1 -0
- package/dist/chunk-cpUYaJdV.mjs +1 -0
- package/dist/cleanEnvForAdapter-DvcIGXTG.mjs +1 -0
- package/dist/client-Dh4x4GQN.mjs +1 -0
- package/dist/clients/index.d.mts +2786 -0
- package/dist/clients/index.mjs +1 -0
- package/dist/clients-namespace-B0xAPZ6J.d.mts +332 -0
- package/dist/config-namespace-DLSs83zr.d.mts +638 -0
- package/dist/config-namespace-MJT8P0Ud.mjs +1 -0
- package/dist/contracts/adapter/index.d.mts +3 -0
- package/dist/contracts/adapter/index.mjs +1 -0
- package/dist/contracts/adapter/schemas/session-lineage.d.mts +2 -0
- package/dist/contracts/adapter/schemas/session-lineage.mjs +1 -0
- package/dist/contracts/client/index.d.mts +3 -0
- package/dist/contracts/client/index.mjs +1 -0
- package/dist/contracts/common/index.d.mts +2 -0
- package/dist/contracts/common/index.mjs +1 -0
- package/dist/contracts/config/index.d.mts +455 -0
- package/dist/contracts/config/index.mjs +1 -0
- package/dist/contracts/extension/index.d.mts +3 -0
- package/dist/contracts/extension/index.mjs +1 -0
- package/dist/contracts/harness/index.d.mts +2 -0
- package/dist/contracts/harness/index.mjs +1 -0
- package/dist/contracts/host/index.d.mts +2 -0
- package/dist/contracts/host/index.mjs +1 -0
- package/dist/contracts/index.d.mts +12665 -0
- package/dist/contracts/index.mjs +1 -0
- package/dist/contracts/model-registry/index.d.mts +2 -0
- package/dist/contracts/model-registry/index.mjs +1 -0
- package/dist/contracts/native-session-supervisor/index.d.mts +2 -0
- package/dist/contracts/native-session-supervisor/index.mjs +1 -0
- package/dist/contracts/platform/index.d.mts +2 -0
- package/dist/contracts/platform/index.mjs +1 -0
- package/dist/contracts/provider/index.d.mts +3 -0
- package/dist/contracts/provider/index.mjs +1 -0
- package/dist/contracts/session/index.d.mts +3 -0
- package/dist/contracts/session/index.mjs +1 -0
- package/dist/contracts/shared/index.d.mts +2 -0
- package/dist/contracts/shared/index.mjs +1 -0
- package/dist/contracts/skill/index.d.mts +2 -0
- package/dist/contracts/skill/index.mjs +1 -0
- package/dist/contracts/toast/index.d.mts +198 -0
- package/dist/contracts/toast/index.mjs +1 -0
- package/dist/contracts/variant/index.d.mts +2 -0
- package/dist/contracts/variant/index.mjs +1 -0
- package/dist/core/index.d.mts +1001 -0
- package/dist/core/index.mjs +1 -0
- package/dist/credential-ref-DLCsoKVZ.mjs +1 -0
- package/dist/cursor-storage-DOQdvo9j.mjs +1 -0
- package/dist/definition-DkYy1PZz.mjs +1 -0
- package/dist/definition-DtUNiGom.d.mts +158 -0
- package/dist/definition-DxvZ9e22.d.mts +376 -0
- package/dist/drizzle-CWVVw7Er.mjs +1 -0
- package/dist/execution-target-BW_uiBVe.mjs +1 -0
- package/dist/extension-COqwS-2Q.mjs +1 -0
- package/dist/extension-Cbrl4YGX.mjs +1 -0
- package/dist/extension-namespace-zaGKi6Qj.mjs +1 -0
- package/dist/handlers-iGKUJ380.mjs +41 -0
- package/dist/harness-CEq1Zkf9.mjs +1 -0
- package/dist/hooks/index.d.mts +423 -0
- package/dist/hooks/index.mjs +1 -0
- package/dist/host-CXAUGGN0.mjs +1 -0
- package/dist/identity-B_A0mE63.mjs +1 -0
- package/dist/index-6lyShOoU.d.mts +225 -0
- package/dist/index-7sXlairn2.d.mts +43 -0
- package/dist/index-BAKM2GMH2.d.mts +535 -0
- package/dist/index-BB419vv-.d.mts +3897 -0
- package/dist/index-BJOfdtbw.d.mts +729 -0
- package/dist/index-BXP9GK5q.d.mts +1075 -0
- package/dist/index-BdPwu6c0.d.mts +1730 -0
- package/dist/index-BePI0ckL.d.mts +40 -0
- package/dist/index-Bigx81Kr.d.mts +37 -0
- package/dist/index-BnNqbx2I.d.mts +134 -0
- package/dist/index-Bv15sNLn.d.mts +389 -0
- package/dist/index-C-myW_aK.d.mts +412 -0
- package/dist/index-C9F3Fc1A.d.mts +2938 -0
- package/dist/index-CNxS4Tlu.d.mts +1 -0
- package/dist/index-CVA0m1g9.d.mts +995 -0
- package/dist/index-C_kS2aqV2.d.mts +438 -0
- package/dist/index-Ch3ph52M2.d.mts +40 -0
- package/dist/index-CnZOKNjU.d.mts +89 -0
- package/dist/index-D1T-PPqF.d.mts +67 -0
- package/dist/index-D7T8XCku.d.mts +341 -0
- package/dist/index-DBQtpFLE.d.mts +4843 -0
- package/dist/index-DEw90pa2.d.mts +183 -0
- package/dist/index-DQRsGXb5.d.mts +109 -0
- package/dist/index-Dd5s4MSm.d.mts +72 -0
- package/dist/index-DubqLGH8.d.mts +1002 -0
- package/dist/index-ESSDWIB7.d.mts +11 -0
- package/dist/index-N5K1NOYs.d.mts +184 -0
- package/dist/index-PdUSmPT2.d.mts +180 -0
- package/dist/index-SzSiyG61.d.mts +117 -0
- package/dist/index-T0471kWA.d.mts +6760 -0
- package/dist/index-WKjrpcA_.d.mts +218 -0
- package/dist/index-hapw9_En.d.mts +13592 -0
- package/dist/index-iID2R9G1.d.mts +1490 -0
- package/dist/kernel/cli/index.d.mts +141 -0
- package/dist/kernel/cli/index.mjs +1 -0
- package/dist/kernel/cli/schemas.d.mts +63 -0
- package/dist/kernel/cli/schemas.mjs +1 -0
- package/dist/kernel/extension/index.d.mts +2 -0
- package/dist/kernel/extension/index.mjs +1 -0
- package/dist/kernel/index.d.mts +296 -0
- package/dist/kernel/index.mjs +1 -0
- package/dist/kernel/namespace/index.d.mts +2 -0
- package/dist/kernel/namespace/index.mjs +1 -0
- package/dist/kernel/observability/index.d.mts +2 -0
- package/dist/kernel/observability/index.mjs +1 -0
- package/dist/kernel/providers/index.d.mts +2 -0
- package/dist/kernel/providers/index.mjs +1 -0
- package/dist/kernel/window/index.d.mts +2 -0
- package/dist/kernel/window/index.mjs +1 -0
- package/dist/model-registry-BNzpR6TU.mjs +1 -0
- package/dist/model-registry-CIscwC52.mjs +1 -0
- package/dist/namespace-0yuzAKlr.mjs +1 -0
- package/dist/namespace-8cNguvIp.mjs +1 -0
- package/dist/namespace-BK2erxpV.d.mts +921 -0
- package/dist/namespace-Bmc7AW4J2.mjs +1 -0
- package/dist/namespace-C2ufjgaQ.d.mts +767 -0
- package/dist/namespace-C54Oj025.d.mts +159 -0
- package/dist/namespace-CCDEOwmW.d.mts +1313 -0
- package/dist/namespace-CfEWMXBx.mjs +1 -0
- package/dist/namespace-CkLUtc0g.d.mts +580 -0
- package/dist/namespace-D5Wrt7YU.mjs +1 -0
- package/dist/namespace-DZcuLwEA.d.mts +51 -0
- package/dist/namespace-Db-p67Rg.mjs +1 -0
- package/dist/namespace-FWx6HxaW.d.mts +611 -0
- package/dist/namespace-GLGGcWPH.d.mts +43 -0
- package/dist/namespace-N0dfwSg6.mjs +1 -0
- package/dist/namespace-O5SNY-LV.d.mts +2226 -0
- package/dist/namespace-ZbthBQVt.d.mts +142 -0
- package/dist/namespace-bq4Prtzn.d.mts +2046 -0
- package/dist/namespace-pNcSglBS.mjs +1 -0
- package/dist/namespace-ptv-pw_g.d.mts +3019 -0
- package/dist/namespace-xkvVw3hf2.d.mts +189 -0
- package/dist/native-session-supervisor-L-UIaEfd.mjs +1 -0
- package/dist/node/bus-server/index.d.mts +178 -0
- package/dist/node/bus-server/index.mjs +1 -0
- package/dist/node/bus-server/server-lifecycle.d.mts +2 -0
- package/dist/node/bus-server/server-lifecycle.mjs +1 -0
- package/dist/node/machine-identity/index.d.mts +85 -0
- package/dist/node/machine-identity/index.mjs +3 -0
- package/dist/node/transports/index.d.mts +1752 -0
- package/dist/node/transports/index.mjs +2 -0
- package/dist/orchestrator-shared-DrjtTXYh.d.mts +249 -0
- package/dist/orchestrator-shared-Wv1GI2mW.mjs +1 -0
- package/dist/platform-BbSLVg5b.mjs +1 -0
- package/dist/profile-4StaDQW0.mjs +1 -0
- package/dist/provider-context-CNRQ4d5m.mjs +1 -0
- package/dist/providers/index.d.mts +135 -0
- package/dist/providers/index.mjs +1 -0
- package/dist/providers-Cr4Za8a1.mjs +1 -0
- package/dist/providers-namespace-CDwxY_DV.d.mts +583 -0
- package/dist/schema-BwzXEtT2.d.mts +837 -0
- package/dist/schema-CAw_BqaG.mjs +1 -0
- package/dist/schema-introspection-D61TT_7b.mjs +1 -0
- package/dist/schema-uSGW-6oM.mjs +1 -0
- package/dist/schemas-BXstpWVp.mjs +1 -0
- package/dist/schemas-BdMU-gew.d.mts +160 -0
- package/dist/schemas-C40ZAJ33.mjs +1 -0
- package/dist/schemas-C5xtVqdb.d.mts +46 -0
- package/dist/schemas-CGZy_rU6.d.mts +13 -0
- package/dist/schemas-CLxtoKFy.mjs +1 -0
- package/dist/schemas-Co_sVhzz.mjs +1 -0
- package/dist/schemas-D9108Iv1.d.mts +182 -0
- package/dist/schemas-DENVYyds.d.mts +463 -0
- package/dist/schemas-DbWs_hj8.d.mts +174 -0
- package/dist/schemas-Di0XnnMX.d.mts +73 -0
- package/dist/schemas-KMA1efQg.d.mts +944 -0
- package/dist/schemas-qmn5SWPU.d.mts +312 -0
- package/dist/schemas-sshQEF3l.d.mts +237 -0
- package/dist/server-lifecycle-Cf_SZ27k.d.mts +160 -0
- package/dist/server-lifecycle-DbFwlrTW.mjs +1 -0
- package/dist/service-base/index.d.mts +98 -0
- package/dist/service-base/index.mjs +1 -0
- package/dist/services/adapter-runtime/index.d.mts +4 -0
- package/dist/services/adapter-runtime/index.mjs +1 -0
- package/dist/services/adapter-runtime/namespace.d.mts +2 -0
- package/dist/services/adapter-runtime/namespace.mjs +1 -0
- package/dist/services/adapter-runtime/schemas.d.mts +2 -0
- package/dist/services/adapter-runtime/schemas.mjs +1 -0
- package/dist/services/adapter-subsystem/index.d.mts +3 -0
- package/dist/services/adapter-subsystem/index.mjs +1 -0
- package/dist/services/adapter-subsystem/namespace.d.mts +2 -0
- package/dist/services/adapter-subsystem/namespace.mjs +1 -0
- package/dist/services/agent-runtime/index.d.mts +3 -0
- package/dist/services/agent-runtime/index.mjs +1 -0
- package/dist/services/agent-runtime/namespace.d.mts +2 -0
- package/dist/services/agent-runtime/namespace.mjs +1 -0
- package/dist/services/agent-runtime/schemas.d.mts +2 -0
- package/dist/services/agent-runtime/schemas.mjs +1 -0
- package/dist/services/capability/index.d.mts +2 -0
- package/dist/services/capability/index.mjs +1 -0
- package/dist/services/cli-detection/namespace.d.mts +56 -0
- package/dist/services/cli-detection/namespace.mjs +1 -0
- package/dist/services/codebase/index.d.mts +3 -0
- package/dist/services/codebase/index.mjs +1 -0
- package/dist/services/codebase/namespace.d.mts +2 -0
- package/dist/services/codebase/namespace.mjs +1 -0
- package/dist/services/codebase/schemas.d.mts +2 -0
- package/dist/services/codebase/schemas.mjs +1 -0
- package/dist/services/compression/index.d.mts +3 -0
- package/dist/services/compression/index.mjs +1 -0
- package/dist/services/compression/namespace.d.mts +2 -0
- package/dist/services/compression/namespace.mjs +1 -0
- package/dist/services/compression/schemas.d.mts +2 -0
- package/dist/services/compression/schemas.mjs +1 -0
- package/dist/services/context-rules/index.d.mts +412 -0
- package/dist/services/context-rules/index.mjs +1 -0
- package/dist/services/credential-change/index.d.mts +17 -0
- package/dist/services/credential-change/index.mjs +1 -0
- package/dist/services/definition/index.d.mts +2 -0
- package/dist/services/definition/index.mjs +1 -0
- package/dist/services/definition/namespace.d.mts +71 -0
- package/dist/services/definition/namespace.mjs +1 -0
- package/dist/services/definition/schemas.d.mts +38 -0
- package/dist/services/definition/schemas.mjs +1 -0
- package/dist/services/dialog/namespace.d.mts +105 -0
- package/dist/services/dialog/namespace.mjs +1 -0
- package/dist/services/dialog/schemas.d.mts +109 -0
- package/dist/services/dialog/schemas.mjs +1 -0
- package/dist/services/execution-target/index.d.mts +4 -0
- package/dist/services/execution-target/index.mjs +1 -0
- package/dist/services/execution-target/namespace.d.mts +2 -0
- package/dist/services/execution-target/namespace.mjs +1 -0
- package/dist/services/execution-target/schemas.d.mts +2 -0
- package/dist/services/execution-target/schemas.mjs +1 -0
- package/dist/services/filesystem/namespace.d.mts +432 -0
- package/dist/services/filesystem/namespace.mjs +1 -0
- package/dist/services/filesystem/schemas.d.mts +240 -0
- package/dist/services/filesystem/schemas.mjs +1 -0
- package/dist/services/harness/index.d.mts +861 -0
- package/dist/services/harness/index.mjs +1 -0
- package/dist/services/harness/storage/schema.d.mts +424 -0
- package/dist/services/harness/storage/schema.mjs +1 -0
- package/dist/services/index.d.mts +5703 -0
- package/dist/services/index.mjs +1 -0
- package/dist/services/local-notification/index.d.mts +25 -0
- package/dist/services/local-notification/index.mjs +1 -0
- package/dist/services/local-notification/namespace.d.mts +73 -0
- package/dist/services/local-notification/namespace.mjs +1 -0
- package/dist/services/local-notification/schemas.d.mts +88 -0
- package/dist/services/local-notification/schemas.mjs +1 -0
- package/dist/services/log-import/browser.d.mts +3 -0
- package/dist/services/log-import/browser.mjs +1 -0
- package/dist/services/log-import/index.d.mts +275 -0
- package/dist/services/log-import/index.mjs +2 -0
- package/dist/services/log-import/log-import.d.mts +3 -0
- package/dist/services/log-import/log-import.mjs +1 -0
- package/dist/services/log-import/namespace.d.mts +327 -0
- package/dist/services/log-import/namespace.mjs +1 -0
- package/dist/services/log-import/schemas.d.mts +217 -0
- package/dist/services/log-import/schemas.mjs +1 -0
- package/dist/services/model-registry/index.d.mts +2 -0
- package/dist/services/model-registry/index.mjs +1 -0
- package/dist/services/preferences/index.d.mts +3 -0
- package/dist/services/preferences/index.mjs +1 -0
- package/dist/services/preferences/schemas.d.mts +2 -0
- package/dist/services/preferences/schemas.mjs +1 -0
- package/dist/services/preferences/storage-namespace.d.mts +3 -0
- package/dist/services/preferences/storage-namespace.mjs +1 -0
- package/dist/services/provider-context/index.d.mts +2 -0
- package/dist/services/provider-context/index.mjs +1 -0
- package/dist/services/provider-runtime/index.d.mts +136 -0
- package/dist/services/provider-runtime/index.mjs +1 -0
- package/dist/services/session/handlers/index.d.mts +2 -0
- package/dist/services/session/handlers/index.mjs +1 -0
- package/dist/services/session/index.d.mts +10 -0
- package/dist/services/session/index.mjs +1 -0
- package/dist/services/session/messages/namespace.d.mts +2 -0
- package/dist/services/session/messages/namespace.mjs +1 -0
- package/dist/services/session/orchestrator-testing/index.d.mts +2 -0
- package/dist/services/session/orchestrator-testing/index.mjs +1 -0
- package/dist/services/session/session-events/namespace.d.mts +2 -0
- package/dist/services/session/session-events/namespace.mjs +1 -0
- package/dist/services/session/storage/namespace.d.mts +2 -0
- package/dist/services/session/storage/namespace.mjs +1 -0
- package/dist/services/session/storage/schema.d.mts +2 -0
- package/dist/services/session/storage/schema.mjs +1 -0
- package/dist/services/session/testing/index.d.mts +35 -0
- package/dist/services/session/testing/index.mjs +52 -0
- package/dist/services/session/testing/orchestrator-shared.d.mts +2 -0
- package/dist/services/session/testing/orchestrator-shared.mjs +1 -0
- package/dist/services/session/turns/namespace.d.mts +2 -0
- package/dist/services/session/turns/namespace.mjs +1 -0
- package/dist/services/session-editor/index.d.mts +119 -0
- package/dist/services/session-editor/index.mjs +1 -0
- package/dist/services/settings/index.d.mts +47 -0
- package/dist/services/settings/index.mjs +1 -0
- package/dist/services/settings/namespace.d.mts +662 -0
- package/dist/services/settings/namespace.mjs +1 -0
- package/dist/services/settings/storage/clients-namespace.d.mts +2 -0
- package/dist/services/settings/storage/clients-namespace.mjs +1 -0
- package/dist/services/settings/storage/extension-configs/namespace.d.mts +184 -0
- package/dist/services/settings/storage/extension-configs/namespace.mjs +1 -0
- package/dist/services/settings/storage/index.d.mts +4 -0
- package/dist/services/settings/storage/index.mjs +1 -0
- package/dist/services/settings/storage/providers-namespace.d.mts +2 -0
- package/dist/services/settings/storage/providers-namespace.mjs +1 -0
- package/dist/services/tool-approval/index.d.mts +2 -0
- package/dist/services/tool-approval/index.mjs +1 -0
- package/dist/services/tools/index.d.mts +2 -0
- package/dist/services/tools/index.mjs +1 -0
- package/dist/services/tray-menu/index.d.mts +4 -0
- package/dist/services/tray-menu/index.mjs +1 -0
- package/dist/services/tray-menu/namespace.d.mts +2 -0
- package/dist/services/tray-menu/namespace.mjs +1 -0
- package/dist/services/tray-menu/schemas.d.mts +2 -0
- package/dist/services/tray-menu/schemas.mjs +1 -0
- package/dist/services/turn/index.d.mts +2 -0
- package/dist/services/turn/index.mjs +1 -0
- package/dist/services/turn/namespace.d.mts +2 -0
- package/dist/services/turn/namespace.mjs +1 -0
- package/dist/services/turn/schemas.d.mts +335 -0
- package/dist/services/turn/schemas.mjs +1 -0
- package/dist/services/worker/index.d.mts +3 -0
- package/dist/services/worker/index.mjs +1 -0
- package/dist/services/worker/namespace.d.mts +2 -0
- package/dist/services/worker/namespace.mjs +1 -0
- package/dist/services/worker/schemas.d.mts +2 -0
- package/dist/services/worker/schemas.mjs +1 -0
- package/dist/session-Do6lDZM4.mjs +123 -0
- package/dist/session-lineage-Eev4uo4I.d.mts +65 -0
- package/dist/session-piI1R5rP.mjs +1 -0
- package/dist/shared-DxHLl9UP.mjs +1 -0
- package/dist/shared-schemas-BgQv_tnu.mjs +1 -0
- package/dist/skill-CB5h-ZFQ.mjs +1 -0
- package/dist/storage/drizzle/client.d.mts +78 -0
- package/dist/storage/drizzle/client.mjs +1 -0
- package/dist/storage/drizzle/index.d.mts +98 -0
- package/dist/storage/drizzle/index.mjs +1 -0
- package/dist/storage/handlers/drizzle/index.d.mts +2 -0
- package/dist/storage/handlers/drizzle/index.mjs +1 -0
- package/dist/storage/handlers/index.d.mts +33 -0
- package/dist/storage/handlers/index.mjs +1 -0
- package/dist/storage/index.d.mts +192 -0
- package/dist/storage/index.mjs +1 -0
- package/dist/storage-namespace-ADwyijoe.mjs +1 -0
- package/dist/storage-namespace-DAm8iWEj.d.mts +221 -0
- package/dist/storage-namespace-definition-CHu2k14q.mjs +1 -0
- package/dist/storage-namespace-definition-CJgqyXH1.d.mts +17 -0
- package/dist/style.css +3782 -0
- package/dist/testing/drizzle-harness.d.mts +130 -0
- package/dist/testing/drizzle-harness.mjs +1 -0
- package/dist/testing/index.d.mts +106 -0
- package/dist/testing/index.mjs +1 -0
- package/dist/tool-approval-service-BcBSUZCO.mjs +1 -0
- package/dist/tools/index.d.mts +825 -0
- package/dist/tools/index.mjs +1 -0
- package/dist/tools/testing/index.d.mts +53 -0
- package/dist/tools/testing/index.mjs +1 -0
- package/dist/tools-CDSgj0ee.mjs +1 -0
- package/dist/tray-menu-service-CTXC1Elg.mjs +1 -0
- package/dist/types-6WxLfoM3.d.mts +31 -0
- package/dist/types-BjToUrHp.d.mts +6619 -0
- package/dist/types-CD1LJwPc.d.mts +1009 -0
- package/dist/types-Cvrj2ogm.d.mts +305 -0
- package/dist/types-DYF5LxZY.d.mts +233 -0
- package/dist/types-t295YC6T.d.mts +262 -0
- package/dist/types-vNpkAe4Y.d.mts +128 -0
- package/dist/ui-components/index.d.mts +2342 -0
- package/dist/ui-components/index.mjs +8 -0
- package/dist/ui-config-CXmbsqZV.mjs +1 -0
- package/dist/ui-hooks/index.d.mts +1805 -0
- package/dist/ui-hooks/index.mjs +1 -0
- package/dist/ui-kernel/index.d.mts +2793 -0
- package/dist/ui-kernel/index.mjs +1 -0
- package/dist/ui-kernel/pages/namespace.d.mts +88 -0
- package/dist/ui-kernel/pages/namespace.mjs +1 -0
- package/dist/ui-kernel/pages/schemas.d.mts +2 -0
- package/dist/ui-kernel/pages/schemas.mjs +1 -0
- package/dist/ui-views/index.d.mts +487 -0
- package/dist/ui-views/index.mjs +30 -0
- package/dist/utils/health-probe.d.mts +26 -0
- package/dist/utils/health-probe.mjs +1 -0
- package/dist/utils/index.d.mts +227 -0
- package/dist/utils/index.mjs +2 -0
- package/dist/utils/keychain.d.mts +31 -0
- package/dist/utils/keychain.mjs +1 -0
- package/dist/utils/resolve-package-root.d.mts +12 -0
- package/dist/utils/resolve-package-root.mjs +1 -0
- package/dist/utils/workspace-root.d.mts +27 -0
- package/dist/utils/workspace-root.mjs +2 -0
- package/dist/variant-D5kSrL3m.mjs +1 -0
- package/dist/version-CjS20oXi.mjs +1 -0
- package/dist/visibility-CZu8ooOA.mjs +1 -0
- package/dist/window-registry-CUftmDr3.mjs +1 -0
- package/dist/window-registry-C_IJmY8_.d.mts +130 -0
- package/package.json +346 -0
|
@@ -0,0 +1,3331 @@
|
|
|
1
|
+
import * as _$zod from "zod";
|
|
2
|
+
import { ZodType, z } from "zod";
|
|
3
|
+
import { Paths, Simplify, UnknownRecord } from "type-fest";
|
|
4
|
+
import * as _$zod_v4_core0 from "zod/v4/core";
|
|
5
|
+
|
|
6
|
+
//#region packages/makaio-core/src/types/message.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Host-agnostic principal attached by a trusted local transport.
|
|
9
|
+
*
|
|
10
|
+
* The framework treats this as opaque metadata. Host code decides what
|
|
11
|
+
* principal kinds and claims mean.
|
|
12
|
+
*/
|
|
13
|
+
interface PrincipalContext {
|
|
14
|
+
/** Principal kind, such as `user`, `device`, `machine`, or host-defined values. */
|
|
15
|
+
readonly kind: string;
|
|
16
|
+
/** Optional stable principal identifier in the principal namespace. */
|
|
17
|
+
readonly id?: string;
|
|
18
|
+
/** Optional opaque claims supplied by the authenticating transport or host policy. */
|
|
19
|
+
readonly claims?: Readonly<Record<string, unknown>>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Authenticated peer metadata supplied by a transport connection.
|
|
23
|
+
*/
|
|
24
|
+
interface TransportPeerContext {
|
|
25
|
+
/** Peer kind, such as `browser`, `machine`, `worker`, or host-defined values. */
|
|
26
|
+
readonly kind: string;
|
|
27
|
+
/** Optional transport-level peer identifier. */
|
|
28
|
+
readonly id?: string;
|
|
29
|
+
/** Whether the receiving transport authenticated the peer. */
|
|
30
|
+
readonly authenticated?: boolean;
|
|
31
|
+
/** Whether the receiving transport established encrypted payload transport. */
|
|
32
|
+
readonly encrypted?: boolean;
|
|
33
|
+
/** Optional opaque peer claims. */
|
|
34
|
+
readonly claims?: Readonly<Record<string, unknown>>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Trusted context derived locally by the receiving transport.
|
|
38
|
+
*
|
|
39
|
+
* This context is never serialized into `BusMessage`; each receiving node must
|
|
40
|
+
* derive its own context from its own transport/session state.
|
|
41
|
+
*/
|
|
42
|
+
interface TransportReceiveContext {
|
|
43
|
+
/** Registered bus transport name that received the message. */
|
|
44
|
+
readonly transportName: string;
|
|
45
|
+
/** Optional connection/session identifier local to the transport. */
|
|
46
|
+
readonly connectionId?: string;
|
|
47
|
+
/** Optional authenticated transport peer. */
|
|
48
|
+
readonly peer?: TransportPeerContext;
|
|
49
|
+
/** Optional host-agnostic principal resolved for this connection. */
|
|
50
|
+
readonly principal?: PrincipalContext;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Base message context interface for both events and requests.
|
|
54
|
+
*
|
|
55
|
+
* Provides common metadata for tracking and correlation:
|
|
56
|
+
* - `messageId`: Unique identifier for this specific message
|
|
57
|
+
* - `correlationId`: Optional identifier linking related operations
|
|
58
|
+
*/
|
|
59
|
+
interface BaseMessageContext {
|
|
60
|
+
/**
|
|
61
|
+
* Unique identifier for this specific message.
|
|
62
|
+
* Auto-generated if not provided.
|
|
63
|
+
*
|
|
64
|
+
* Used for:
|
|
65
|
+
* - Message deduplication
|
|
66
|
+
* - Idempotency checks
|
|
67
|
+
* - Tracking individual messages in logs
|
|
68
|
+
*/
|
|
69
|
+
messageId: string;
|
|
70
|
+
/**
|
|
71
|
+
* Optional identifier linking related operations.
|
|
72
|
+
* Propagated through chains of requests/events.
|
|
73
|
+
*
|
|
74
|
+
* Used for:
|
|
75
|
+
* - Distributed tracing
|
|
76
|
+
* - Causality tracking
|
|
77
|
+
* - Following a workflow through the system
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* // Initial request generates correlationId
|
|
81
|
+
* const result = await request(
|
|
82
|
+
* UserSubjects.getUser,
|
|
83
|
+
* { userId: '42' },
|
|
84
|
+
* { correlationId: 'user-action-123' }
|
|
85
|
+
* );
|
|
86
|
+
*
|
|
87
|
+
* // Handler propagates correlationId to downstream operations
|
|
88
|
+
* await emit(
|
|
89
|
+
* UserSubjects.userLoaded,
|
|
90
|
+
* { user: result },
|
|
91
|
+
* { correlationId: context.correlationId }
|
|
92
|
+
* );
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
correlationId?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Trusted context supplied by the local receiving transport.
|
|
98
|
+
*
|
|
99
|
+
* Undefined for local calls and for transports that do not supply connection
|
|
100
|
+
* context. Never trust similarly named fields in payloads or wire messages.
|
|
101
|
+
*/
|
|
102
|
+
transport?: TransportReceiveContext;
|
|
103
|
+
isRequest: boolean;
|
|
104
|
+
}
|
|
105
|
+
type EventMessagePayload<Payload extends UnknownRecord = UnknownRecord> = Payload & {
|
|
106
|
+
request?: never;
|
|
107
|
+
response?: never;
|
|
108
|
+
};
|
|
109
|
+
type RequestMessagePayload<Request extends UnknownRecord = UnknownRecord, Response extends UnknownRecord = UnknownRecord> = {
|
|
110
|
+
request: Request;
|
|
111
|
+
response: Response;
|
|
112
|
+
};
|
|
113
|
+
type MessagePayload = RequestMessagePayload | EventMessagePayload;
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region packages/makaio-core/src/types/context.d.ts
|
|
116
|
+
/**
|
|
117
|
+
* Context object passed to event handlers when using wildcard patterns.
|
|
118
|
+
*
|
|
119
|
+
* Provides:
|
|
120
|
+
* - `isRequest`: Always false (discriminator for type narrowing)
|
|
121
|
+
* - `payload`: The event payload
|
|
122
|
+
* - Message tracking fields from BaseMessage (messageId, correlationId)
|
|
123
|
+
*/
|
|
124
|
+
interface EventContext<Payload> extends BaseMessageContext {
|
|
125
|
+
/** Discriminator - always false for events */
|
|
126
|
+
isRequest: false;
|
|
127
|
+
/** The event payload */
|
|
128
|
+
payload: Payload;
|
|
129
|
+
/** The event subject */
|
|
130
|
+
subject: string;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Context object passed to request handlers.
|
|
134
|
+
*
|
|
135
|
+
* Provides:
|
|
136
|
+
* - `isRequest`: Always true (discriminator for type narrowing)
|
|
137
|
+
* - `payload`: The request payload
|
|
138
|
+
* - `setResult`: Function to set the response value
|
|
139
|
+
* - `next`: Function to call the next handler in the middleware chain
|
|
140
|
+
* - `replacePayload`: Function to transform the payload for subsequent handlers
|
|
141
|
+
* - `identify`: Optional function to identify the handler for broadcast aggregation
|
|
142
|
+
* - Message tracking fields from BaseMessage (messageId, correlationId)
|
|
143
|
+
*/
|
|
144
|
+
interface RequestContext<Payload, Response> extends BaseMessageContext {
|
|
145
|
+
/** Discriminator - always true for requests */
|
|
146
|
+
isRequest: true;
|
|
147
|
+
/** The request payload */
|
|
148
|
+
payload: Payload;
|
|
149
|
+
/** Set the response value (ends the handler chain) */
|
|
150
|
+
setResult: (result: Response) => void;
|
|
151
|
+
/**
|
|
152
|
+
* Read the current result value.
|
|
153
|
+
*
|
|
154
|
+
* Returns the value set by `setResult()` in this handler or by a downstream
|
|
155
|
+
* handler after `await next()`. Undefined until a result has been set.
|
|
156
|
+
*/
|
|
157
|
+
readonly result: Response | undefined;
|
|
158
|
+
/**
|
|
159
|
+
* Shallow-merge additional fields into the current result.
|
|
160
|
+
*
|
|
161
|
+
* Only valid for object-typed responses. In the request path the operation
|
|
162
|
+
* uses spread (immutable); in broadcast mode it uses `Object.assign`
|
|
163
|
+
* (in-place mutation) so the already-pushed result reference stays current.
|
|
164
|
+
* If no result has been set yet, starts from an empty object.
|
|
165
|
+
* @param extension - Fields to merge into the current result
|
|
166
|
+
*/
|
|
167
|
+
extendResult: (extension: [Response] extends [Record<string, unknown>] ? Partial<Response> : never) => void;
|
|
168
|
+
/**
|
|
169
|
+
* Call the next handler in the middleware chain.
|
|
170
|
+
* If no more handlers exist, throws NoHandlerError.
|
|
171
|
+
*/
|
|
172
|
+
next: () => Promise<void>;
|
|
173
|
+
/**
|
|
174
|
+
* Replace the payload with a new value.
|
|
175
|
+
* Subsequent handlers in the middleware chain will receive the new payload.
|
|
176
|
+
* Useful for hooks that need to inject context before the main handler runs.
|
|
177
|
+
*/
|
|
178
|
+
replacePayload: (newPayload: Payload) => void;
|
|
179
|
+
/**
|
|
180
|
+
* Identify this handler for broadcast aggregation.
|
|
181
|
+
* Only present when called via broadcast() - call before setResult().
|
|
182
|
+
* @param nodeId - Unique identifier for this handler/node
|
|
183
|
+
*/
|
|
184
|
+
identify?: (nodeId: string) => void;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Unified context for wildcard handlers that can match both events and requests.
|
|
188
|
+
* Use the `isRequest` discriminator to narrow the type.
|
|
189
|
+
* @example
|
|
190
|
+
* ```typescript
|
|
191
|
+
* MakaioBus.on('adapter.*', (context) => {
|
|
192
|
+
* if (context.isRequest) {
|
|
193
|
+
* // TypeScript knows this is RequestContext
|
|
194
|
+
* context.setResult({ handled: true });
|
|
195
|
+
* } else {
|
|
196
|
+
* // TypeScript knows this is EventContext
|
|
197
|
+
* console.debug('Event:', context.payload);
|
|
198
|
+
* }
|
|
199
|
+
* });
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
type WildcardContext<Payload = unknown, Response = unknown> = EventContext<Payload> | RequestContext<Payload, Response>;
|
|
203
|
+
//#endregion
|
|
204
|
+
//#region packages/makaio-core/src/types/filter.d.ts
|
|
205
|
+
type Primitive = string | number | boolean | null;
|
|
206
|
+
/**
|
|
207
|
+
* Filter operators for payload field matching.
|
|
208
|
+
* @example
|
|
209
|
+
* ```typescript
|
|
210
|
+
* // Equality (implicit)
|
|
211
|
+
* { agentId: 'agent-123' }
|
|
212
|
+
*
|
|
213
|
+
* // Membership
|
|
214
|
+
* { status: { $in: ['active', 'pending'] } }
|
|
215
|
+
*
|
|
216
|
+
* // Not equal
|
|
217
|
+
* { type: { $ne: 'internal' } }
|
|
218
|
+
*
|
|
219
|
+
* // Presence check
|
|
220
|
+
* { error: { $exists: false } }
|
|
221
|
+
*
|
|
222
|
+
* // String prefix/suffix matching
|
|
223
|
+
* { path: { $startsWith: '.git/' } }
|
|
224
|
+
* { file: { $endsWith: '.ts' } }
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
type FilterOperator<T extends Primitive = Primitive> = T | {
|
|
228
|
+
$in: T[];
|
|
229
|
+
} | {
|
|
230
|
+
$ne: T;
|
|
231
|
+
} | {
|
|
232
|
+
$exists: boolean;
|
|
233
|
+
} | {
|
|
234
|
+
$startsWith: string;
|
|
235
|
+
} | {
|
|
236
|
+
$endsWith: string;
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* Untyped payload filter - accepts any string keys.
|
|
240
|
+
* Use TypedPayloadFilter<T> for type-safe filters.
|
|
241
|
+
*/
|
|
242
|
+
type PayloadFilter = Record<string, FilterOperator>;
|
|
243
|
+
/**
|
|
244
|
+
* Type-safe payload filter constrained to valid paths of a payload type.
|
|
245
|
+
*
|
|
246
|
+
* Uses type-fest's `Paths` to support dotted path notation for nested fields.
|
|
247
|
+
* @example
|
|
248
|
+
* ```typescript
|
|
249
|
+
* interface McpPayload {
|
|
250
|
+
* agentId: string;
|
|
251
|
+
* raw: { msg: { type: string } };
|
|
252
|
+
* }
|
|
253
|
+
*
|
|
254
|
+
* // Type-safe - validates both top-level and nested paths
|
|
255
|
+
* const filter: TypedPayloadFilter<McpPayload> = {
|
|
256
|
+
* agentId: 'agent-123',
|
|
257
|
+
* 'raw.msg.type': 'session_configured', // ✅ valid path
|
|
258
|
+
* 'raw.msg.typo': 'x', // ❌ type error
|
|
259
|
+
* };
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
type TypedPayloadFilter<T> = { [K in Paths<T> & string]?: FilterOperator };
|
|
263
|
+
//#endregion
|
|
264
|
+
//#region packages/makaio-core/src/types/schema.d.ts
|
|
265
|
+
/**
|
|
266
|
+
* Schema definition for event subjects (fire-and-forget).
|
|
267
|
+
* Events have only a payload schema, no response.
|
|
268
|
+
* The payload is now separate from the context, so no restrictions needed.
|
|
269
|
+
*/
|
|
270
|
+
type EventSchema = z.ZodType;
|
|
271
|
+
/**
|
|
272
|
+
* Schema definition for request subjects (request-response).
|
|
273
|
+
* Requests have both a request payload schema and a response schema.
|
|
274
|
+
*/
|
|
275
|
+
type RequestSchema<Request extends ZodType = ZodType, Response extends ZodType = ZodType> = {
|
|
276
|
+
request: Request;
|
|
277
|
+
response: Response;
|
|
278
|
+
};
|
|
279
|
+
/**
|
|
280
|
+
* Wrapper to mark a subject as local-only (never sent to transports).
|
|
281
|
+
*
|
|
282
|
+
* Use `localSubject()` from `@makaio/bus-core` to create these.
|
|
283
|
+
* @example
|
|
284
|
+
* ```typescript
|
|
285
|
+
* import { localSubject } from '@makaio/framework/bus';
|
|
286
|
+
*
|
|
287
|
+
* const WidgetSchemas = {
|
|
288
|
+
* register: localSubject(widgetDefinitionSchema), // local event
|
|
289
|
+
* unregister: localSubject(z.object({ widgetId: z.string() })),
|
|
290
|
+
* };
|
|
291
|
+
* ```
|
|
292
|
+
*/
|
|
293
|
+
type LocalSubjectSchema<T extends EventSchema | RequestSchema = EventSchema | RequestSchema> = {
|
|
294
|
+
readonly __local: true;
|
|
295
|
+
readonly schema: T;
|
|
296
|
+
};
|
|
297
|
+
/**
|
|
298
|
+
* Wrapper to mark a subject as channel-only (encrypted point-to-point).
|
|
299
|
+
*
|
|
300
|
+
* Channel subjects are rejected by public bus methods and are only
|
|
301
|
+
* routable through the DirectChannel encrypted transport. Use
|
|
302
|
+
* `channelSubject()` from `@makaio/bus-core` to create these.
|
|
303
|
+
* @example
|
|
304
|
+
* ```typescript
|
|
305
|
+
* import { channelSubject } from '@makaio/framework/bus';
|
|
306
|
+
*
|
|
307
|
+
* const DirectSchemas = {
|
|
308
|
+
* message: channelSubject(z.object({ text: z.string() })),
|
|
309
|
+
* ping: channelSubject({
|
|
310
|
+
* request: z.object({ ts: z.number() }),
|
|
311
|
+
* response: z.object({ ts: z.number() }),
|
|
312
|
+
* }),
|
|
313
|
+
* };
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
316
|
+
type ChannelSubjectSchema<T extends EventSchema | RequestSchema = EventSchema | RequestSchema> = {
|
|
317
|
+
readonly __channel: true;
|
|
318
|
+
readonly schema: T;
|
|
319
|
+
};
|
|
320
|
+
/**
|
|
321
|
+
* Base schema types (unwrapped).
|
|
322
|
+
*/
|
|
323
|
+
type BaseSubjectSchema = EventSchema | RequestSchema;
|
|
324
|
+
/**
|
|
325
|
+
* Union of all subject schema types (including local and channel wrappers).
|
|
326
|
+
*/
|
|
327
|
+
type SubjectSchema = BaseSubjectSchema | LocalSubjectSchema | ChannelSubjectSchema;
|
|
328
|
+
type SchemaRecord = Record<string, SubjectSchema>;
|
|
329
|
+
//#endregion
|
|
330
|
+
//#region packages/makaio-core/src/types/type-helpers.d.ts
|
|
331
|
+
/**
|
|
332
|
+
* Unwrap LocalSubjectSchema or ChannelSubjectSchema wrappers if present.
|
|
333
|
+
* Returns the inner schema for wrapped subjects, or the schema as-is otherwise.
|
|
334
|
+
*/
|
|
335
|
+
type UnwrapSchema<S> = S extends {
|
|
336
|
+
readonly __local: true;
|
|
337
|
+
readonly schema: infer Inner;
|
|
338
|
+
} ? Inner : S extends {
|
|
339
|
+
readonly __channel: true;
|
|
340
|
+
readonly schema: infer Inner;
|
|
341
|
+
} ? Inner : S;
|
|
342
|
+
/**
|
|
343
|
+
* Infer payload type from schema (handles EventSchema, RequestSchema,
|
|
344
|
+
* LocalSubjectSchema, and ChannelSubjectSchema).
|
|
345
|
+
*
|
|
346
|
+
* For requests:
|
|
347
|
+
* - Uses z.input for request (what callers pass before validation/defaults)
|
|
348
|
+
* - Uses z.infer for response (what handlers return after processing)
|
|
349
|
+
*
|
|
350
|
+
* This allows schemas with .default() to have optional fields in the caller API
|
|
351
|
+
* while the response type reflects the validated output.
|
|
352
|
+
*
|
|
353
|
+
* LocalSubjectSchema and ChannelSubjectSchema wrappers are automatically
|
|
354
|
+
* unwrapped before inference.
|
|
355
|
+
*
|
|
356
|
+
* Idempotent: Returns already-inferred types as-is.
|
|
357
|
+
*/
|
|
358
|
+
type InferSchemaPayload<S extends SubjectSchema> = InferSchemaPayloadInner<UnwrapSchema<S>>;
|
|
359
|
+
type InferSchemaPayloadInner<S> = S extends {
|
|
360
|
+
request: infer Req extends z.ZodType;
|
|
361
|
+
response: infer Res extends z.ZodType;
|
|
362
|
+
} ? {
|
|
363
|
+
request: z.input<Req>;
|
|
364
|
+
response: z.infer<Res>;
|
|
365
|
+
} : S extends z.ZodType ? Simplify<z.infer<S>> : unknown;
|
|
366
|
+
/**
|
|
367
|
+
* Compute all subject meta from the original schema in one place.
|
|
368
|
+
*
|
|
369
|
+
* Resolves payload, locality, channel membership, request/event discriminator,
|
|
370
|
+
* and namespace from a raw SubjectSchema.
|
|
371
|
+
* @typeParam S - The subject schema type
|
|
372
|
+
* @typeParam Ns - The namespace string
|
|
373
|
+
*/
|
|
374
|
+
type InferSubjectMeta<S extends SubjectSchema, Ns extends string> = {
|
|
375
|
+
/** True when the subject is a request-response pair, false for events. */isRequest: UnwrapSchema<S> extends {
|
|
376
|
+
request: z.ZodType;
|
|
377
|
+
response: z.ZodType;
|
|
378
|
+
} ? true : false; /** True when the subject is wrapped with `localSubject()`. */
|
|
379
|
+
local: S extends LocalSubjectSchema ? true : false; /** True when the subject is wrapped with `channelSubject()`. */
|
|
380
|
+
channel: S extends ChannelSubjectSchema ? true : false; /** Inferred payload type (request/response pair or event payload). */
|
|
381
|
+
payload: InferSchemaPayload<S>; /** The namespace this subject belongs to. */
|
|
382
|
+
namespace: Ns;
|
|
383
|
+
};
|
|
384
|
+
//#endregion
|
|
385
|
+
//#region packages/makaio-core/src/types/subjects.d.ts
|
|
386
|
+
type SubjectRecord<SubjectKeys extends string = string, Payload extends MessagePayload = MessagePayload> = Record<SubjectKeys, Payload>;
|
|
387
|
+
type SubjectRecordFromSchemaRecord<SchemaRecord extends Record<string, SubjectSchema>> = { [K in keyof SchemaRecord & string]: Simplify<InferSchemaPayload<SchemaRecord[K]>> };
|
|
388
|
+
type SubjectDefinitionMeta<Subject extends SubjectRecord = SubjectRecord<'default'>, K extends keyof Subject = keyof Subject, Namespace extends string = string> = {
|
|
389
|
+
isRequest: Subject extends SubjectRecord<'default'> ? boolean : Subject[K] extends RequestMessagePayload ? true : false;
|
|
390
|
+
payload: K extends string ? Subject[K] : unknown;
|
|
391
|
+
namespace: Namespace;
|
|
392
|
+
/**
|
|
393
|
+
* If true, this subject is local-only and will never be sent to transports.
|
|
394
|
+
* Use for subjects whose payloads contain non-serializable data (e.g., React components).
|
|
395
|
+
*/
|
|
396
|
+
local: boolean;
|
|
397
|
+
/**
|
|
398
|
+
* If true, this subject is channel-only and is only routable through the
|
|
399
|
+
* DirectChannel encrypted point-to-point transport.
|
|
400
|
+
*/
|
|
401
|
+
channel: boolean;
|
|
402
|
+
};
|
|
403
|
+
type SubjectDefinition<Subject extends SubjectRecord = SubjectRecord, SubjectKey extends keyof Subject = keyof Subject, Namespace extends string = string> = {
|
|
404
|
+
$meta: SubjectDefinitionMeta<Subject, SubjectKey, Namespace>;
|
|
405
|
+
subject: SubjectKey;
|
|
406
|
+
};
|
|
407
|
+
type ScopedSubjectDefinition<Namespace extends string = string> = SubjectDefinition<SubjectRecord, keyof SubjectRecord, Namespace>;
|
|
408
|
+
/**
|
|
409
|
+
* Extract the filterable payload from a MessagePayload.
|
|
410
|
+
* For requests, returns the request part (what we filter on).
|
|
411
|
+
* For events, returns the payload as-is.
|
|
412
|
+
*/
|
|
413
|
+
type FilterablePayload<P> = P extends RequestMessagePayload ? P['request'] : P;
|
|
414
|
+
/**
|
|
415
|
+
* Union of all filterable payloads from a SubjectRecord.
|
|
416
|
+
*/
|
|
417
|
+
type FilterablePayloadsUnion<Subjects extends SubjectRecord> = FilterablePayload<Subjects[keyof Subjects]>;
|
|
418
|
+
/**
|
|
419
|
+
* Extract keys from ANY member of a union type (distributive).
|
|
420
|
+
*
|
|
421
|
+
* For `{ a: 1, b: 2 } | { a: 1, c: 3 }`, returns `'a' | 'b' | 'c'`.
|
|
422
|
+
*/
|
|
423
|
+
type KeysOfUnion<T> = T extends unknown ? keyof T : never;
|
|
424
|
+
/**
|
|
425
|
+
* Extract value type for a key from union members that have it.
|
|
426
|
+
*/
|
|
427
|
+
type ValueOfKey<T, K extends PropertyKey> = T extends { [P in K]: infer V } ? V : never;
|
|
428
|
+
/**
|
|
429
|
+
* Build an object type with ALL keys from ANY union member.
|
|
430
|
+
*
|
|
431
|
+
* For `{ type: 'a', id: string } | { type: 'b', name: string }`:
|
|
432
|
+
* Result = `{ type: 'a' | 'b', id: string, name: string }`
|
|
433
|
+
*
|
|
434
|
+
* Allows filtering by any key that exists in any payload.
|
|
435
|
+
*/
|
|
436
|
+
type AllPropertiesOfUnion<T> = { [K in KeysOfUnion<T>]: ValueOfKey<T, K> };
|
|
437
|
+
/**
|
|
438
|
+
* Union of all filterable payload properties from a SubjectRecord.
|
|
439
|
+
*
|
|
440
|
+
* Collects ALL keys from ANY payload, allowing filtering by any field.
|
|
441
|
+
* Events without a filtered key simply won't match.
|
|
442
|
+
* @example
|
|
443
|
+
* ```typescript
|
|
444
|
+
* // Given subjects with payloads:
|
|
445
|
+
* // - 'event': { agentId: string, foo: number }
|
|
446
|
+
* // - 'request': { sessionId: string }
|
|
447
|
+
*
|
|
448
|
+
* // FilterablePayloadUnion = { agentId: string, foo: number, sessionId: string }
|
|
449
|
+
*
|
|
450
|
+
* // Filter can use any key from any payload
|
|
451
|
+
* bus.withFilter({ agentId: 'x' }); // ✅ matches events with agentId
|
|
452
|
+
* bus.withFilter({ sessionId: 'y' }); // ✅ matches requests with sessionId
|
|
453
|
+
* ```
|
|
454
|
+
*/
|
|
455
|
+
type FilterablePayloadIntersection<Subjects extends SubjectRecord> = Simplify<AllPropertiesOfUnion<FilterablePayloadsUnion<Subjects>>>;
|
|
456
|
+
//#endregion
|
|
457
|
+
//#region packages/makaio-core/src/types/wildcards.d.ts
|
|
458
|
+
type WildcardSubject = '*';
|
|
459
|
+
type WildcardSubjectDefinition<Namespace extends string = string> = SubjectDefinition<Record<'*', MessagePayload>, WildcardSubject, Namespace>;
|
|
460
|
+
//#endregion
|
|
461
|
+
//#region packages/makaio-core/src/types/handler-types.d.ts
|
|
462
|
+
type EventHandler<T> = (context: EventContext<T>) => void | Promise<void>;
|
|
463
|
+
type RequestHandler<Payload, Response> = (context: RequestContext<Payload, Response>) => void | Promise<void>;
|
|
464
|
+
/**
|
|
465
|
+
* Context provided to __onAny handlers for debugging/testing.
|
|
466
|
+
* Captures all message metadata regardless of type (event/request/broadcast).
|
|
467
|
+
*/
|
|
468
|
+
interface AnyMessageContext {
|
|
469
|
+
type: 'event' | 'request' | 'broadcast';
|
|
470
|
+
subject: string;
|
|
471
|
+
namespace: string;
|
|
472
|
+
payload: unknown;
|
|
473
|
+
messageId: string;
|
|
474
|
+
correlationId?: string;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Handler for __onAny - receives all messages (events and requests) across all namespaces.
|
|
478
|
+
* Used for debugging and testing only.
|
|
479
|
+
*/
|
|
480
|
+
type AnyHandler = (context: AnyMessageContext) => void | Promise<void>;
|
|
481
|
+
/**
|
|
482
|
+
* Special handler for wildcards that match both events and requests.
|
|
483
|
+
* @public
|
|
484
|
+
*/
|
|
485
|
+
type WildcardUnifiedHandler = (context: WildcardContext<unknown, unknown>) => void | Promise<void>;
|
|
486
|
+
/**
|
|
487
|
+
* Resolve the appropriate handler type for a subject pattern (exact or wildcard).
|
|
488
|
+
*
|
|
489
|
+
* Handles all subscription patterns:
|
|
490
|
+
* - Event wildcards (`adapter.*`) → `(payload: unknown) => void | Promise<void>`
|
|
491
|
+
* - Request wildcards (`adapter.*`) → `(context: RequestContext<unknown, unknown>) => void | Promise<void>`
|
|
492
|
+
* - Exact request subjects → `RequestHandler<TPayload, TReturnValue>`
|
|
493
|
+
* - Exact event subjects → `EventHandler<TPayload>`
|
|
494
|
+
*
|
|
495
|
+
* This is the primary type used by the `on()` method to resolve handler signatures.
|
|
496
|
+
* @example
|
|
497
|
+
* ```typescript
|
|
498
|
+
* // Event wildcard - unknown payload
|
|
499
|
+
* type Handler1 = HandlerForPattern<'adapter.*'>;
|
|
500
|
+
* // (payload: unknown) => void | Promise<void>
|
|
501
|
+
*
|
|
502
|
+
* // Exact event subject - typed payload
|
|
503
|
+
* type Handler2 = HandlerForPattern<'adapter.log'>;
|
|
504
|
+
* // EventHandler<{ message: string, level: string }>
|
|
505
|
+
*
|
|
506
|
+
* // Request wildcard - unknown context
|
|
507
|
+
* type Handler3 = HandlerForPattern<'adapter.*'>;
|
|
508
|
+
* // (context: RequestContext<unknown, unknown>) => void | Promise<void>
|
|
509
|
+
*
|
|
510
|
+
* // Exact request subject - typed context
|
|
511
|
+
* type Handler4 = HandlerForPattern<'adapter.getCapabilities'>;
|
|
512
|
+
* // RequestHandler<{ adapterName: string }, { capabilities: string[] }>
|
|
513
|
+
* ```
|
|
514
|
+
*/
|
|
515
|
+
/**
|
|
516
|
+
* Resolve the handler type for a SubjectDefinition.
|
|
517
|
+
*
|
|
518
|
+
* Uses indexed access (`T['$meta']['payload']`) instead of nested `extends` with `infer`
|
|
519
|
+
* to ensure proper type resolution when T is a generic type parameter.
|
|
520
|
+
*/
|
|
521
|
+
type HandlerForSubjectDefinition<T extends SubjectDefinition> = T['subject'] extends WildcardSubject ? WildcardUnifiedHandler : T['$meta']['payload'] extends RequestMessagePayload<infer Request, infer Response> ? RequestHandler<Request, Response> : T['$meta']['payload'] extends EventMessagePayload<infer Payload> ? EventHandler<Payload> : never;
|
|
522
|
+
/**
|
|
523
|
+
* Extract context type for once() promise return value.
|
|
524
|
+
*
|
|
525
|
+
* Uses the same pattern as HandlerForSubjectDefinition for consistency.
|
|
526
|
+
*/
|
|
527
|
+
type ContextForSubjectDefinition<T extends SubjectDefinition> = T['subject'] extends WildcardSubject ? WildcardContext<unknown, unknown> : T['$meta']['payload'] extends RequestMessagePayload<infer Request, infer Response> ? RequestContext<Request, Response> : T['$meta']['payload'] extends EventMessagePayload<infer Payload> ? EventContext<Payload> : never;
|
|
528
|
+
//#endregion
|
|
529
|
+
//#region packages/makaio-core/src/types/result.d.ts
|
|
530
|
+
/**
|
|
531
|
+
* Result types for optional request handling.
|
|
532
|
+
*
|
|
533
|
+
* Used by requestOptional to distinguish between "handler returned data"
|
|
534
|
+
* and "no handler was registered".
|
|
535
|
+
*/
|
|
536
|
+
/**
|
|
537
|
+
* Discriminated union for optional request results.
|
|
538
|
+
*
|
|
539
|
+
* - `handled: true` - A handler was found and returned data
|
|
540
|
+
* - `handled: false` - No handler was registered for the subject
|
|
541
|
+
* @example
|
|
542
|
+
* ```typescript
|
|
543
|
+
* const result = await bus.requestOptional(Subjects.getData, { id: '123' });
|
|
544
|
+
* if (result.handled) {
|
|
545
|
+
* console.debug('Got data:', result.data);
|
|
546
|
+
* } else {
|
|
547
|
+
* console.debug('No handler registered for getData');
|
|
548
|
+
* }
|
|
549
|
+
* ```
|
|
550
|
+
*/
|
|
551
|
+
type OptionalResult<T> = {
|
|
552
|
+
handled: true;
|
|
553
|
+
data: T;
|
|
554
|
+
} | {
|
|
555
|
+
handled: false;
|
|
556
|
+
};
|
|
557
|
+
//#endregion
|
|
558
|
+
//#region packages/makaio-core/src/subject-helpers/nest-subject-definitions.d.ts
|
|
559
|
+
/**
|
|
560
|
+
* Recursively nests a flat record of dotted keys into a hierarchical object type.
|
|
561
|
+
*
|
|
562
|
+
* ```
|
|
563
|
+
* { 'assistant.text': SubjectDef, 'agent.tool.started': SubjectDef }
|
|
564
|
+
* → { assistant: { text: SubjectDef }, agent: { tool: { started: SubjectDef } } }
|
|
565
|
+
* ```
|
|
566
|
+
*
|
|
567
|
+
* Used to expose registered subjects as a nested accessor tree (e.g.
|
|
568
|
+
* `BootSubjects.service.ready`) without requiring callers to deal with
|
|
569
|
+
* flat dotted-key strings at the type level.
|
|
570
|
+
*/
|
|
571
|
+
type NestedSubjectDefinitions<T extends Record<string, unknown> = Record<string, SubjectDefinition>> = { [K in ExtractPrefixes<keyof T & string>]: NestByPrefix<T, K> };
|
|
572
|
+
type ExtractPrefixes<Keys extends string> = Keys extends `${infer Prefix}.${string}` ? Prefix : Keys;
|
|
573
|
+
type StripPrefixMap<T, Prefix extends string> = { [K in keyof T as K extends `${Prefix}.${infer Rest}` ? Rest : never]: T[K] };
|
|
574
|
+
type NestByPrefix<T extends Record<string, unknown>, Prefix extends string> = Prefix extends keyof T ? T[Prefix] : NestedSubjectDefinitions<StripPrefixMap<T, Prefix>>;
|
|
575
|
+
/**
|
|
576
|
+
* Maps a flat schema record to a flat subject-definition record, attaching the
|
|
577
|
+
* correct `$meta` (namespace, isRequest, local, channel) and `subject` key for
|
|
578
|
+
* each entry.
|
|
579
|
+
*
|
|
580
|
+
* Intermediate type used by {@link nestSubjectDefinitions} before nesting.
|
|
581
|
+
* @typeParam Domain - Namespace domain string (e.g. `'boot'`)
|
|
582
|
+
* @typeParam Schemas - Flat record of raw Zod schemas keyed by dotted subject names
|
|
583
|
+
*/
|
|
584
|
+
type FlatSubjectDefinitions<Domain extends string, Schemas extends Record<string, SubjectSchema>> = { [K in keyof Schemas & string]: {
|
|
585
|
+
$meta: InferSubjectMeta<Schemas[K], Domain>;
|
|
586
|
+
subject: K;
|
|
587
|
+
} };
|
|
588
|
+
/**
|
|
589
|
+
* Fully-nested subject accessor tree returned by `registerNamespace`.
|
|
590
|
+
*
|
|
591
|
+
* Combines the {@link NestedSubjectDefinitions} hierarchy with a `$all`
|
|
592
|
+
* wildcard that matches every subject in the namespace. Consumers use this
|
|
593
|
+
* type to write `SomeNamespace.subjects.foo.bar` instead of raw strings.
|
|
594
|
+
* @typeParam RecordOfSubjectDefinitions - Flat record of subject definitions
|
|
595
|
+
* @typeParam Domain - Namespace domain string used for `$all` wildcard typing
|
|
596
|
+
*/
|
|
597
|
+
type BusSubjects<RecordOfSubjectDefinitions extends Record<string, unknown> = Record<string, SubjectDefinition>, Domain extends string = string> = NestedSubjectDefinitions<RecordOfSubjectDefinitions> & {
|
|
598
|
+
$all: WildcardSubjectDefinition<Domain>;
|
|
599
|
+
};
|
|
600
|
+
/**
|
|
601
|
+
* Gets the fully qualified subject name in namespace.subject format.
|
|
602
|
+
* @param subject - The subject definition to format
|
|
603
|
+
* @returns The full subject string in the format "namespace.subject"
|
|
604
|
+
*/
|
|
605
|
+
declare function getFullSubjectForSubjectDefinition(subject: SubjectDefinition): string;
|
|
606
|
+
//#endregion
|
|
607
|
+
//#region packages/makaio-core/src/subject-helpers/is-request-schema.d.ts
|
|
608
|
+
/**
|
|
609
|
+
* Type guard to check if a schema is a request schema.
|
|
610
|
+
* @param schema - The schema to check
|
|
611
|
+
* @returns True if the schema is a RequestSchema, false otherwise
|
|
612
|
+
*/
|
|
613
|
+
declare function isRequestSchema(schema: SubjectSchema): schema is RequestSchema;
|
|
614
|
+
//#endregion
|
|
615
|
+
//#region packages/makaio-core/src/subject-helpers/is-local-schema.d.ts
|
|
616
|
+
/**
|
|
617
|
+
* Create a local-only subject schema wrapper.
|
|
618
|
+
*
|
|
619
|
+
* Local subjects are never sent to transports (SharedWorker, WebSocket, etc.).
|
|
620
|
+
* Use this for subjects whose payloads contain non-serializable data like
|
|
621
|
+
* React components or functions.
|
|
622
|
+
* @param schema - The event or request schema to mark as local
|
|
623
|
+
* @returns A LocalSubjectSchema wrapper
|
|
624
|
+
* @example
|
|
625
|
+
* ```typescript
|
|
626
|
+
* import { localSubject } from '@makaio/framework/core';
|
|
627
|
+
*
|
|
628
|
+
* const WidgetSchemas = {
|
|
629
|
+
* // Local event - contains React component, can't be serialized
|
|
630
|
+
* register: localSubject(widgetDefinitionSchema),
|
|
631
|
+
*
|
|
632
|
+
* // Local request - response contains functions
|
|
633
|
+
* getRenderer: localSubject({
|
|
634
|
+
* request: z.object({ widgetId: z.string() }),
|
|
635
|
+
* response: z.object({ render: z.function() }),
|
|
636
|
+
* }),
|
|
637
|
+
* };
|
|
638
|
+
* ```
|
|
639
|
+
*/
|
|
640
|
+
declare function localSubject<T extends EventSchema | RequestSchema>(schema: T): LocalSubjectSchema<T>;
|
|
641
|
+
//#endregion
|
|
642
|
+
//#region packages/makaio-core/src/subject-helpers/is-channel-schema.d.ts
|
|
643
|
+
/**
|
|
644
|
+
* Create a channel-only subject schema wrapper.
|
|
645
|
+
*
|
|
646
|
+
* Channel subjects are rejected by public bus methods and are only
|
|
647
|
+
* routable through the DirectChannel encrypted point-to-point transport.
|
|
648
|
+
* Use this for subjects that must never travel over the public bus.
|
|
649
|
+
* @param schema - The event or request schema to mark as channel-only
|
|
650
|
+
* @returns A ChannelSubjectSchema wrapper
|
|
651
|
+
* @example
|
|
652
|
+
* ```typescript
|
|
653
|
+
* import { channelSubject } from '@makaio/framework/core';
|
|
654
|
+
*
|
|
655
|
+
* const DirectSchemas = {
|
|
656
|
+
* // Channel event - encrypted, point-to-point only
|
|
657
|
+
* message: channelSubject(z.object({ text: z.string() })),
|
|
658
|
+
*
|
|
659
|
+
* // Channel request - encrypted request-response pair
|
|
660
|
+
* ping: channelSubject({
|
|
661
|
+
* request: z.object({ ts: z.number() }),
|
|
662
|
+
* response: z.object({ ts: z.number() }),
|
|
663
|
+
* }),
|
|
664
|
+
* };
|
|
665
|
+
* ```
|
|
666
|
+
*/
|
|
667
|
+
declare function channelSubject<T extends EventSchema | RequestSchema>(schema: T): ChannelSubjectSchema<T>;
|
|
668
|
+
//#endregion
|
|
669
|
+
//#region packages/makaio-core/src/bus-namespace-definition.d.ts
|
|
670
|
+
/**
|
|
671
|
+
* Report passed to the {@link NamespaceRegistrationOptions} `onSchemaViolation` callback
|
|
672
|
+
* when lenient validation detects a schema mismatch.
|
|
673
|
+
*
|
|
674
|
+
* Canonical owner: `@makaio/core`. `@makaio/bus-core` imports this type from core.
|
|
675
|
+
*/
|
|
676
|
+
interface SchemaViolationReport {
|
|
677
|
+
/** Fully-qualified subject key (e.g., `"adapter:claude-code.sdk.event"`) */
|
|
678
|
+
subject: string;
|
|
679
|
+
/** Raw payload that failed validation */
|
|
680
|
+
payload: unknown;
|
|
681
|
+
/** Individual Zod issues from the failed parse */
|
|
682
|
+
issues: unknown[];
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Options controlling runtime schema validation for a registered bus namespace.
|
|
686
|
+
*
|
|
687
|
+
* - `strict` (default) — throw `ValidationError` on schema mismatch
|
|
688
|
+
* - `lenient` — invoke `onSchemaViolation` callback, then deliver the event anyway
|
|
689
|
+
* - `skip` — no validation at all (for cross-Zod-version scenarios, e.g., SDK bundles Zod v3)
|
|
690
|
+
*
|
|
691
|
+
* Canonical owner: `@makaio/core`. `@makaio/bus-core` imports this type from core,
|
|
692
|
+
* not the other way around. Single source of truth — no mirroring.
|
|
693
|
+
*/
|
|
694
|
+
type NamespaceRegistrationOptions = {
|
|
695
|
+
busValidationMode?: 'strict';
|
|
696
|
+
} | {
|
|
697
|
+
busValidationMode: 'lenient';
|
|
698
|
+
onSchemaViolation: (report: SchemaViolationReport) => void;
|
|
699
|
+
} | {
|
|
700
|
+
busValidationMode: 'skip';
|
|
701
|
+
};
|
|
702
|
+
/**
|
|
703
|
+
* A declarative bus namespace definition.
|
|
704
|
+
*
|
|
705
|
+
* Created by {@link createBusNamespace}. Carries typed subject tokens for
|
|
706
|
+
* immediate use in bus operations, plus the original schemas for deferred
|
|
707
|
+
* registration at boot time via `MakaioBus.registerNamespace()`.
|
|
708
|
+
*
|
|
709
|
+
* Does not include `scopedBus()` — that method requires a bus instance and
|
|
710
|
+
* is available on the `BusNamespace` object returned by `registerNamespace()`.
|
|
711
|
+
* @typeParam Domain - Namespace domain string (e.g. `'adapter'`, `'session'`)
|
|
712
|
+
* @typeParam Schemas - Schema record mapping subject keys to Zod schemas
|
|
713
|
+
*/
|
|
714
|
+
interface BusNamespaceDefinition<Domain extends string = string, Schemas extends Record<string, SubjectSchema> = Record<string, SubjectSchema>> {
|
|
715
|
+
/** Namespace domain string (e.g., `'adapter'`, `'session'`) */
|
|
716
|
+
readonly name: Domain;
|
|
717
|
+
/**
|
|
718
|
+
* Typed subject tokens for bus operations — no registration needed to use
|
|
719
|
+
* these for `bus.on()`, `bus.emit()`, or `bus.request()`.
|
|
720
|
+
*/
|
|
721
|
+
readonly subjects: BusSubjects<FlatSubjectDefinitions<Domain, Schemas>, Domain>;
|
|
722
|
+
/** Original Zod schemas — carried for deferred registration */
|
|
723
|
+
readonly schemas: Schemas;
|
|
724
|
+
/** Registration options (validation mode, violation callback) */
|
|
725
|
+
readonly options?: NamespaceRegistrationOptions;
|
|
726
|
+
/**
|
|
727
|
+
* Phantom field for type inference of filterable payload shape.
|
|
728
|
+
*
|
|
729
|
+
* Never set at runtime. Exists solely so TypeScript can infer the
|
|
730
|
+
* `FilterPayload` type parameter from the schema record without an
|
|
731
|
+
* explicit annotation at every callsite.
|
|
732
|
+
* @internal
|
|
733
|
+
*/
|
|
734
|
+
readonly __filterPayload?: FilterablePayloadIntersection<SubjectRecordFromSchemaRecord<Schemas>>;
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Namespace definition shape required for runtime registration.
|
|
738
|
+
*
|
|
739
|
+
* Structurally derived from {@link BusNamespaceDefinition} with the typed
|
|
740
|
+
* subject tree erased to `unknown`. Composition-root catalogs and extension
|
|
741
|
+
* manifests only need the namespace name, schemas, options, and the runtime
|
|
742
|
+
* subject tokens; keeping this structural type separate lets those catalogs
|
|
743
|
+
* contain heterogeneous namespace definitions without widening every subject
|
|
744
|
+
* tree to an unsafe index signature.
|
|
745
|
+
*/
|
|
746
|
+
type RegistrableBusNamespaceDefinition = Omit<BusNamespaceDefinition, 'subjects' | '__filterPayload'> & {
|
|
747
|
+
/** Runtime subject token tree created by `createBusNamespace`. */readonly subjects: unknown;
|
|
748
|
+
};
|
|
749
|
+
//#endregion
|
|
750
|
+
//#region packages/makaio-core/src/errors/index.d.ts
|
|
751
|
+
/**
|
|
752
|
+
* Base error class for all Makaio-related errors.
|
|
753
|
+
*/
|
|
754
|
+
declare class MakaioError extends Error {
|
|
755
|
+
readonly subject?: string | undefined;
|
|
756
|
+
constructor(message: string, subject?: string | undefined);
|
|
757
|
+
}
|
|
758
|
+
//#endregion
|
|
759
|
+
//#region packages/bus-core/src/extend-subject.d.ts
|
|
760
|
+
/**
|
|
761
|
+
* Additional fields to add to a request subject's request and/or response schemas.
|
|
762
|
+
* Omit either key to leave that side unchanged.
|
|
763
|
+
*/
|
|
764
|
+
interface RequestSubjectExtension {
|
|
765
|
+
request?: Record<string, z.ZodType>;
|
|
766
|
+
response?: Record<string, z.ZodType>;
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Additional fields to add to an event subject's payload schema.
|
|
770
|
+
*/
|
|
771
|
+
type EventSubjectExtension = Record<string, z.ZodType>;
|
|
772
|
+
/**
|
|
773
|
+
* Infers the correct extension shape based on whether the subject is a request or event.
|
|
774
|
+
*/
|
|
775
|
+
type SubjectExtension<SD extends SubjectDefinition> = SD['$meta']['isRequest'] extends true ? RequestSubjectExtension : EventSubjectExtension;
|
|
776
|
+
type ExtendWithInput<Original, Ext extends Record<string, z.ZodType>> = Omit<Original, keyof Ext> & { [K in keyof Ext as undefined extends z.input<Ext[K]> ? never : K]: z.input<Ext[K]> } & { [K in keyof Ext as undefined extends z.input<Ext[K]> ? K : never]?: z.input<Ext[K]> };
|
|
777
|
+
type ExtendWithInfer<Original, Ext extends Record<string, z.ZodType>> = Omit<Original, keyof Ext> & { [K in keyof Ext as undefined extends z.infer<Ext[K]> ? never : K]: z.infer<Ext[K]> } & { [K in keyof Ext as undefined extends z.infer<Ext[K]> ? K : never]?: z.infer<Ext[K]> };
|
|
778
|
+
type ExtendedRequestPayload<OrigPayload, Ext extends RequestSubjectExtension> = {
|
|
779
|
+
request: Ext['request'] extends Record<string, z.ZodType> ? ExtendWithInput<OrigPayload extends {
|
|
780
|
+
request: infer R;
|
|
781
|
+
} ? R : never, Ext['request']> : OrigPayload extends {
|
|
782
|
+
request: infer R;
|
|
783
|
+
} ? R : never;
|
|
784
|
+
response: Ext['response'] extends Record<string, z.ZodType> ? ExtendWithInfer<OrigPayload extends {
|
|
785
|
+
response: infer R;
|
|
786
|
+
} ? R : never, Ext['response']> : OrigPayload extends {
|
|
787
|
+
response: infer R;
|
|
788
|
+
} ? R : never;
|
|
789
|
+
};
|
|
790
|
+
/**
|
|
791
|
+
* A SubjectDefinition with overridden `$meta.payload` — preserves all other metadata.
|
|
792
|
+
*/
|
|
793
|
+
type ExtendedSubjectDefinition<SD extends SubjectDefinition, Ext extends SubjectExtension<SD>> = {
|
|
794
|
+
subject: SD['subject'];
|
|
795
|
+
$meta: {
|
|
796
|
+
namespace: SD['$meta']['namespace'];
|
|
797
|
+
isRequest: SD['$meta']['isRequest'];
|
|
798
|
+
local: SD['$meta']['local'];
|
|
799
|
+
channel: SD['$meta']['channel'];
|
|
800
|
+
payload: SD['$meta']['isRequest'] extends true ? Ext extends RequestSubjectExtension ? ExtendedRequestPayload<SD['$meta']['payload'], Ext> : SD['$meta']['payload'] : Ext extends Record<string, z.ZodType> ? ExtendWithInfer<SD['$meta']['payload'], Ext> : SD['$meta']['payload'];
|
|
801
|
+
};
|
|
802
|
+
};
|
|
803
|
+
/**
|
|
804
|
+
* Pure declaration of a subject extension.
|
|
805
|
+
*
|
|
806
|
+
* This keeps TypeScript's widened subject inference available to importers
|
|
807
|
+
* without mutating the runtime namespace registry at module import time.
|
|
808
|
+
* The owning package must call {@link DefinedSubjectExtension.register} during
|
|
809
|
+
* its activation lifecycle, after the base namespace has been registered.
|
|
810
|
+
*/
|
|
811
|
+
interface DefinedSubjectExtension<SD extends SubjectDefinition, Ext extends SubjectExtension<SD>> {
|
|
812
|
+
/** Subject definition with widened payload inference. */
|
|
813
|
+
readonly subject: ExtendedSubjectDefinition<SD, Ext>;
|
|
814
|
+
/**
|
|
815
|
+
* Register the extension against the runtime bus namespace registry.
|
|
816
|
+
* @param bus - Bus instance whose namespace registry receives the extension.
|
|
817
|
+
* @returns The same subject definition with widened payload inference.
|
|
818
|
+
*/
|
|
819
|
+
register(bus: Pick<IMakaioBus, 'extendSubject'>): ExtendedSubjectDefinition<SD, Ext>;
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Declare a subject extension without registering it immediately.
|
|
823
|
+
*
|
|
824
|
+
* Use this for product or extension modules that export typed subjects but
|
|
825
|
+
* cannot safely mutate the namespace registry at import time. Registration
|
|
826
|
+
* remains explicit via the returned `register()` method.
|
|
827
|
+
* @param subject - Base subject definition to widen.
|
|
828
|
+
* @param extension - Additional Zod fields for the subject payload.
|
|
829
|
+
* @returns A declaration containing the widened subject and activation-time registration hook.
|
|
830
|
+
*/
|
|
831
|
+
declare function defineSubjectExtension<SD extends SubjectDefinition, Ext extends SubjectExtension<SD>>(subject: SD, extension: Ext): DefinedSubjectExtension<SD, Ext>;
|
|
832
|
+
/**
|
|
833
|
+
* Extend a registered bus subject's schema with additional fields.
|
|
834
|
+
*
|
|
835
|
+
* Called on the bus context directly. Adds new fields to the Zod schema for
|
|
836
|
+
* dev-mode validation and widens the TypeScript payload type. Successive calls
|
|
837
|
+
* accumulate fields — two packages can independently extend the same subject
|
|
838
|
+
* with different field names. If two extensions add the same field name,
|
|
839
|
+
* the later call's definition wins (Zod `.extend()` semantics).
|
|
840
|
+
*
|
|
841
|
+
* The returned value is the same runtime object — only the TypeScript type widens.
|
|
842
|
+
* @param context - Bus context containing the namespace registry
|
|
843
|
+
* @param subject - The SubjectDefinition to extend
|
|
844
|
+
* @param extensions - Additional Zod fields to add
|
|
845
|
+
* @returns The same SubjectDefinition with wider TypeScript types
|
|
846
|
+
*/
|
|
847
|
+
declare function extendSubjectImpl<SD extends SubjectDefinition, Ext extends SubjectExtension<SD>>(context: MakaioBusContext, subject: SD, extensions: Ext): ExtendedSubjectDefinition<SD, Ext>;
|
|
848
|
+
//#endregion
|
|
849
|
+
//#region packages/bus-core/src/types/interceptor.d.ts
|
|
850
|
+
/**
|
|
851
|
+
* Context provided to interceptor handlers.
|
|
852
|
+
*
|
|
853
|
+
* Interceptors run BEFORE event handlers (not request handlers), allowing:
|
|
854
|
+
* - Payload transformation via `replacePayload()`
|
|
855
|
+
* - Event blocking via `stopPropagation()`
|
|
856
|
+
* - Sequential execution in priority order (highest first)
|
|
857
|
+
*
|
|
858
|
+
* Note: Interceptors only work with event subjects. For request/response
|
|
859
|
+
* flow interception, use middleware instead.
|
|
860
|
+
*/
|
|
861
|
+
interface InterceptorContext<P, S = string> {
|
|
862
|
+
readonly subject: S;
|
|
863
|
+
readonly payload: P;
|
|
864
|
+
readonly messageId: string;
|
|
865
|
+
readonly correlationId: string | undefined;
|
|
866
|
+
/**
|
|
867
|
+
* Stop propagation of this message.
|
|
868
|
+
* Subsequent interceptors and all handlers will NOT be called.
|
|
869
|
+
*/
|
|
870
|
+
stopPropagation(): void;
|
|
871
|
+
/**
|
|
872
|
+
* Replace the payload with a new value.
|
|
873
|
+
* Subsequent interceptors and handlers will receive the new payload.
|
|
874
|
+
*/
|
|
875
|
+
replacePayload(newPayload: P): void;
|
|
876
|
+
/**
|
|
877
|
+
* Explicitly continue to the next interceptor (optional).
|
|
878
|
+
* Continuation is implicit if neither stopPropagation() nor next() is called.
|
|
879
|
+
*/
|
|
880
|
+
next(): void;
|
|
881
|
+
}
|
|
882
|
+
/**
|
|
883
|
+
* Handler function for interceptors.
|
|
884
|
+
* Receives an InterceptorContext and may optionally return a Promise.
|
|
885
|
+
*/
|
|
886
|
+
type InterceptorHandler<P> = (ctx: InterceptorContext<P>) => void | Promise<void>;
|
|
887
|
+
/**
|
|
888
|
+
* Options for registering an interceptor.
|
|
889
|
+
*/
|
|
890
|
+
interface InterceptOptions {
|
|
891
|
+
/**
|
|
892
|
+
* Priority for interceptor execution order.
|
|
893
|
+
* Higher values run first. Default: 0
|
|
894
|
+
*/
|
|
895
|
+
priority?: number;
|
|
896
|
+
/**
|
|
897
|
+
* Optional filter to conditionally invoke this interceptor.
|
|
898
|
+
* Uses the same filter syntax as on() handlers.
|
|
899
|
+
*/
|
|
900
|
+
filter?: PayloadFilter;
|
|
901
|
+
}
|
|
902
|
+
/**
|
|
903
|
+
* Entry stored in the interceptor registry.
|
|
904
|
+
* Similar to HandlerEntry but specific to interceptors.
|
|
905
|
+
*/
|
|
906
|
+
interface InterceptorEntry<H> {
|
|
907
|
+
handler: H;
|
|
908
|
+
priority: number;
|
|
909
|
+
}
|
|
910
|
+
//#endregion
|
|
911
|
+
//#region packages/bus-core/src/methods/once.d.ts
|
|
912
|
+
/**
|
|
913
|
+
* Options for the Promise-based once() method.
|
|
914
|
+
*/
|
|
915
|
+
type OnceOptions<T extends SubjectDefinition> = {
|
|
916
|
+
/** Timeout in milliseconds - rejects promise if event not received within this time */timeoutMs?: number;
|
|
917
|
+
/**
|
|
918
|
+
* Declarative payload filter for smart-routing.
|
|
919
|
+
*
|
|
920
|
+
* Applied both locally and can be sent to transports for server-side filtering.
|
|
921
|
+
* Replaces the old function-based filter for serialization support.
|
|
922
|
+
* @example
|
|
923
|
+
* ```typescript
|
|
924
|
+
* await bus.once(Subjects.message, {
|
|
925
|
+
* filter: {
|
|
926
|
+
* agentId: 'agent-123',
|
|
927
|
+
* 'raw.msg.type': 'session_configured',
|
|
928
|
+
* }
|
|
929
|
+
* });
|
|
930
|
+
* ```
|
|
931
|
+
*/
|
|
932
|
+
filter?: TypedPayloadFilter<T['$meta']['payload']>; /** AbortSignal to cancel waiting */
|
|
933
|
+
signal?: AbortSignal;
|
|
934
|
+
};
|
|
935
|
+
/**
|
|
936
|
+
* Error thrown when `once()` rejects because its `AbortSignal` was
|
|
937
|
+
* triggered. Consumers that intentionally abort a pending listener can use
|
|
938
|
+
* `instanceof OnceAbortError` to distinguish the expected rejection from real
|
|
939
|
+
* failures.
|
|
940
|
+
*/
|
|
941
|
+
declare class OnceAbortError extends Error {
|
|
942
|
+
constructor();
|
|
943
|
+
}
|
|
944
|
+
//#endregion
|
|
945
|
+
//#region packages/bus-core/src/scoped-bus-base.d.ts
|
|
946
|
+
/**
|
|
947
|
+
* Minimal shared surface common to {@link ScopedBus} and {@link IFilteredBus}.
|
|
948
|
+
* @typeParam Namespace - The namespace domain string (e.g. `'adapter:codex-mcp'`)
|
|
949
|
+
*/
|
|
950
|
+
interface IScopedBusBase<Namespace extends string> {
|
|
951
|
+
readonly namespace: Namespace;
|
|
952
|
+
/**
|
|
953
|
+
* Register an event or request handler.
|
|
954
|
+
* @param subject - Subject definition to listen on
|
|
955
|
+
* @param handler - Handler function to invoke
|
|
956
|
+
* @param options - Optional subscription options (filter, priority, etc.)
|
|
957
|
+
* @returns Unsubscribe function
|
|
958
|
+
*/
|
|
959
|
+
on<Subject extends ScopedSubjectDefinition<Namespace>>(subject: Subject, handler: HandlerForSubjectDefinition<Subject>, options?: OnOptions): () => void;
|
|
960
|
+
/**
|
|
961
|
+
* Register an interceptor that runs BEFORE handlers.
|
|
962
|
+
* @param subject - Subject definition to intercept
|
|
963
|
+
* @param handler - Interceptor handler function
|
|
964
|
+
* @param options - Optional intercept options (filter, priority, etc.)
|
|
965
|
+
* @returns Unsubscribe function
|
|
966
|
+
*/
|
|
967
|
+
intercept<Subject extends ScopedSubjectDefinition<Namespace>>(subject: Subject, handler: InterceptorHandler<Subject['$meta']['payload']>, options?: InterceptOptions): () => void;
|
|
968
|
+
/**
|
|
969
|
+
* Register a one-time handler (callback version).
|
|
970
|
+
* @param subject - Subject definition to listen on once
|
|
971
|
+
* @param handler - Handler function invoked at most once
|
|
972
|
+
* @returns Unsubscribe function
|
|
973
|
+
*/
|
|
974
|
+
once<Subject extends ScopedSubjectDefinition<Namespace>>(subject: Subject, handler: HandlerForSubjectDefinition<Subject>): () => void;
|
|
975
|
+
/**
|
|
976
|
+
* Wait for an event (promise version).
|
|
977
|
+
* @param subject - Subject definition to await
|
|
978
|
+
* @param options - Optional filter and timeout options
|
|
979
|
+
* @returns Promise resolving to the event context
|
|
980
|
+
*/
|
|
981
|
+
once<Subject extends ScopedSubjectDefinition<Namespace>>(subject: Subject, options?: OnceOptions<Subject>): Promise<ContextForSubjectDefinition<Subject>>;
|
|
982
|
+
/**
|
|
983
|
+
* Emit an event.
|
|
984
|
+
* @param subject - Subject definition to emit on
|
|
985
|
+
* @param payload - Event payload matching the subject schema
|
|
986
|
+
* @returns Promise resolving when all handlers have been notified
|
|
987
|
+
*/
|
|
988
|
+
emit<Subject extends ScopedSubjectDefinition<Namespace>>(subject: Subject, payload: Subject['$meta']['payload']): Promise<void>;
|
|
989
|
+
/**
|
|
990
|
+
* Make a request (throws if no handler is registered).
|
|
991
|
+
* @param subject - Subject definition for the request
|
|
992
|
+
* @param payload - Request payload matching the subject schema
|
|
993
|
+
* @returns Promise resolving to the response payload
|
|
994
|
+
*/
|
|
995
|
+
request<Subject extends ScopedSubjectDefinition<Namespace>>(subject: Subject, payload: Subject['$meta']['payload']['request']): Promise<Subject['$meta']['payload']['response']>;
|
|
996
|
+
/**
|
|
997
|
+
* Make an optional request (returns `OptionalResult` instead of throwing
|
|
998
|
+
* when no handler is registered).
|
|
999
|
+
* @param subject - Subject definition for the request
|
|
1000
|
+
* @param payload - Request payload matching the subject schema
|
|
1001
|
+
* @returns Promise resolving to an `OptionalResult` wrapper
|
|
1002
|
+
*/
|
|
1003
|
+
requestOptional<Subject extends ScopedSubjectDefinition<Namespace>>(subject: Subject, payload: Subject['$meta']['payload']['request']): Promise<OptionalResult<Subject['$meta']['payload']['response']>>;
|
|
1004
|
+
}
|
|
1005
|
+
//#endregion
|
|
1006
|
+
//#region packages/bus-core/src/filtered-bus.d.ts
|
|
1007
|
+
/**
|
|
1008
|
+
* Filtered bus that applies a base filter to all subscriptions.
|
|
1009
|
+
*
|
|
1010
|
+
* Created via `ScopedBus.withFilter()` or `FilteredBus.withFilter()`.
|
|
1011
|
+
* @typeParam Namespace - The namespace domain string
|
|
1012
|
+
* @typeParam Subjects - SubjectRecord for payload types (unused, for type consistency)
|
|
1013
|
+
* @typeParam FilterPayload - Pre-computed filter payload type for type-safe withFilter
|
|
1014
|
+
*/
|
|
1015
|
+
interface IFilteredBus<Namespace extends string = string, Subjects = unknown, FilterPayload = unknown> extends IScopedBusBase<Namespace> {
|
|
1016
|
+
/**
|
|
1017
|
+
* Get the current base filter.
|
|
1018
|
+
*/
|
|
1019
|
+
getFilter(): PayloadFilter | undefined;
|
|
1020
|
+
/**
|
|
1021
|
+
* Create a new FilteredBus with additional filter conditions merged in.
|
|
1022
|
+
* Later filters override earlier ones for the same path.
|
|
1023
|
+
*
|
|
1024
|
+
* When FilterPayload is known, filter keys are automatically type-checked.
|
|
1025
|
+
* @param filter - Additional filter conditions to merge
|
|
1026
|
+
* @returns New FilteredBus with merged filter
|
|
1027
|
+
* @example
|
|
1028
|
+
* ```typescript
|
|
1029
|
+
* // Type-safe filtering - keys validated against FilterPayload
|
|
1030
|
+
* const agentBus = bus.withFilter({ agentId: 'agent-123' }); // ✅
|
|
1031
|
+
* const badBus = bus.withFilter({ unknownKey: 'x' }); // ❌ Error
|
|
1032
|
+
*
|
|
1033
|
+
* // Explicit type override
|
|
1034
|
+
* interface CustomPayload { agentId: string; status: string }
|
|
1035
|
+
* const strictBus = bus.withFilter<CustomPayload>({ agentId: 'agent-123' });
|
|
1036
|
+
* ```
|
|
1037
|
+
*/
|
|
1038
|
+
withFilter(filter: TypedPayloadFilter<FilterPayload>): IFilteredBus<Namespace, Subjects, FilterPayload>;
|
|
1039
|
+
}
|
|
1040
|
+
/**
|
|
1041
|
+
* Create a filtered bus instance.
|
|
1042
|
+
* @param context - Bus context
|
|
1043
|
+
* @param namespace - Namespace for validation
|
|
1044
|
+
* @param baseFilter - Base filter to apply to all subscriptions
|
|
1045
|
+
* @returns FilteredBus instance
|
|
1046
|
+
*/
|
|
1047
|
+
declare function createFilteredBus<Namespace extends string, Subjects = unknown, FilterPayload = unknown>(context: MakaioBusContext, namespace: Namespace, baseFilter?: PayloadFilter): IFilteredBus<Namespace, Subjects, FilterPayload>;
|
|
1048
|
+
//#endregion
|
|
1049
|
+
//#region packages/bus-core/src/scoped-bus.d.ts
|
|
1050
|
+
/**
|
|
1051
|
+
* Scoped bus with namespace isolation and type-safe filtering.
|
|
1052
|
+
* @typeParam Namespace - The namespace domain string (e.g., 'adapter:codex-mcp')
|
|
1053
|
+
* @typeParam Subjects - SubjectRecord for payload types (used by on/once/emit)
|
|
1054
|
+
* @typeParam FilterPayload - Pre-computed intersection of all filterable payloads.
|
|
1055
|
+
* When provided, withFilter constrains filter keys to this type.
|
|
1056
|
+
*/
|
|
1057
|
+
type ScopedBus<Namespace extends string, Subjects = SubjectRecord, FilterPayload = unknown> = IScopedBusBase<Namespace> & {
|
|
1058
|
+
/**
|
|
1059
|
+
* Create a filtered bus with a base payload filter.
|
|
1060
|
+
*
|
|
1061
|
+
* The filter is automatically applied to all `on()` and `once()` calls.
|
|
1062
|
+
*
|
|
1063
|
+
* When FilterPayload is known (via BusNamespace.scopedBus()), filter keys are
|
|
1064
|
+
* automatically constrained to the intersection of all subject payloads.
|
|
1065
|
+
* @param filter - Base filter to apply to all subscriptions
|
|
1066
|
+
* @returns FilteredBus with the specified filter
|
|
1067
|
+
* @example
|
|
1068
|
+
* ```typescript
|
|
1069
|
+
* // Type-safe filtering - keys auto-inferred from pre-computed FilterPayload
|
|
1070
|
+
* const scopedBus = await CodexMcpNamespace.scopedBus();
|
|
1071
|
+
* scopedBus.withFilter({ agentId: this.agentId }); // ✅ agentId validated
|
|
1072
|
+
* scopedBus.withFilter({ unknownKey: 'x' }); // ❌ Error - unknown key
|
|
1073
|
+
*
|
|
1074
|
+
* // Explicit type override still works
|
|
1075
|
+
* interface CustomPayload { agentId: string; sessionId: string }
|
|
1076
|
+
* scopedBus.withFilter<CustomPayload>({ agentId: 'x' });
|
|
1077
|
+
* ```
|
|
1078
|
+
*/
|
|
1079
|
+
withFilter(filter: TypedPayloadFilter<FilterPayload>): IFilteredBus<Namespace, Subjects, FilterPayload>;
|
|
1080
|
+
/**
|
|
1081
|
+
* Get the bus context for advanced use cases.
|
|
1082
|
+
*/
|
|
1083
|
+
getContext(): MakaioBusContext;
|
|
1084
|
+
};
|
|
1085
|
+
//#endregion
|
|
1086
|
+
//#region packages/bus-core/src/types/namespace.d.ts
|
|
1087
|
+
/**
|
|
1088
|
+
* A registered bus namespace with domain, subjects, and pre-computed filter payload type.
|
|
1089
|
+
* @typeParam Domain - The namespace domain string (e.g., 'adapter:codex-mcp')
|
|
1090
|
+
* @typeParam Subjects - The subject record mapping subject keys to payload types
|
|
1091
|
+
* @typeParam FilterPayload - Pre-computed intersection of all filterable payloads for type-safe withFilter
|
|
1092
|
+
* @typeParam Schemas - The original schema record; drives narrow literal types on subjects.$meta (e.g., local: false)
|
|
1093
|
+
*/
|
|
1094
|
+
type BusNamespace<Domain extends string = string, Subjects extends SubjectRecord | BusSubjects = SubjectRecord, FilterPayload = unknown, Schemas extends Record<string, SubjectSchema> = Record<string, SubjectSchema>> = {
|
|
1095
|
+
name: Domain;
|
|
1096
|
+
subjects: BusSubjects<FlatSubjectDefinitions<Domain, Schemas>, Domain>;
|
|
1097
|
+
scopedBus(context?: MakaioBusContext): Promise<ScopedBus<Domain, Subjects, FilterPayload>>;
|
|
1098
|
+
/**
|
|
1099
|
+
* Phantom property for type extraction. Never accessed at runtime.
|
|
1100
|
+
* Enables `ExtractFilterPayload<T>` to infer the FilterPayload type parameter
|
|
1101
|
+
* without relying on complex nested generic inference.
|
|
1102
|
+
*/
|
|
1103
|
+
readonly __filterPayload?: FilterPayload;
|
|
1104
|
+
};
|
|
1105
|
+
/**
|
|
1106
|
+
* Derive a ScopedBus type from a BusNamespace, preserving Domain, Subjects, and FilterPayload.
|
|
1107
|
+
* @example
|
|
1108
|
+
* ```typescript
|
|
1109
|
+
* const MyNamespace = MakaioBus.registerNamespace('myDomain', { ... });
|
|
1110
|
+
* export type MyBus = ScopedBusFor<typeof MyNamespace>;
|
|
1111
|
+
* // Equivalent to: ScopedBus<'myDomain', { ...subjects... }, FilterPayload>
|
|
1112
|
+
* ```
|
|
1113
|
+
*/
|
|
1114
|
+
type ScopedBusFor<T> = T extends BusNamespace<infer D, infer S, infer F, infer _Sc> ? ScopedBus<D, S extends SubjectRecord ? S : SubjectRecord, F> : never;
|
|
1115
|
+
//#endregion
|
|
1116
|
+
//#region packages/bus-core/src/registries/namespace-registry.d.ts
|
|
1117
|
+
/**
|
|
1118
|
+
* Callback invoked when a schema violation is detected in lenient mode.
|
|
1119
|
+
* @param report - Violation details including subject, payload, and Zod issues
|
|
1120
|
+
*/
|
|
1121
|
+
type SchemaViolationCallback = (report: SchemaViolationReport) => void;
|
|
1122
|
+
/**
|
|
1123
|
+
* Validation mode for a namespace's bus payloads.
|
|
1124
|
+
*
|
|
1125
|
+
* - `strict` — throw ValidationError on schema mismatch (default)
|
|
1126
|
+
* - `lenient` — invoke onSchemaViolation callback, then continue (event still delivered)
|
|
1127
|
+
* - `skip` — no validation at all (for Zod version conflicts, e.g., SDK bundles Zod v3)
|
|
1128
|
+
*/
|
|
1129
|
+
type BusValidationMode = 'strict' | 'lenient' | 'skip';
|
|
1130
|
+
/**
|
|
1131
|
+
* Resolved validation config for a namespace's bus payloads.
|
|
1132
|
+
*/
|
|
1133
|
+
interface ValidationConfig {
|
|
1134
|
+
/** Active validation mode */
|
|
1135
|
+
mode: BusValidationMode;
|
|
1136
|
+
/** Callback for lenient-mode violations (undefined for strict/skip) */
|
|
1137
|
+
onViolation?: SchemaViolationCallback;
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Runtime schema metadata for one registered bus subject.
|
|
1141
|
+
*/
|
|
1142
|
+
interface RegisteredSubjectSchema {
|
|
1143
|
+
/** Namespace passed to `registerNamespace()`. */
|
|
1144
|
+
namespace: string;
|
|
1145
|
+
/** Subject key inside the namespace's schema record. */
|
|
1146
|
+
subject: string;
|
|
1147
|
+
/** Fully-qualified subject key in `namespace.subject` form. */
|
|
1148
|
+
fullSubject: string;
|
|
1149
|
+
/** Unwrapped event or request schema used by runtime validation. */
|
|
1150
|
+
schema: BaseSubjectSchema;
|
|
1151
|
+
/** Whether the subject was registered through `localSubject()`. */
|
|
1152
|
+
local: boolean;
|
|
1153
|
+
/** Whether the subject was registered through `channelSubject()`. */
|
|
1154
|
+
channel: boolean;
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* Creates the namespace registry used by a bus context.
|
|
1158
|
+
*
|
|
1159
|
+
* Maintains a runtime map of registered namespaces and their subject schemas,
|
|
1160
|
+
* enabling schema lookup, request-subject detection, local-subject detection,
|
|
1161
|
+
* and validation configuration for namespaces that bundle incompatible Zod versions.
|
|
1162
|
+
* @returns Namespace registry with registerNamespace, getSchema, listRegisteredSubjects,
|
|
1163
|
+
* isRequestSubject, isLocalSubject, getValidationConfig, and (test-only) __resetNamespaces methods
|
|
1164
|
+
*/
|
|
1165
|
+
declare const createNamespaceRegistry: () => {
|
|
1166
|
+
/**
|
|
1167
|
+
* Register a namespace in the runtime registry.
|
|
1168
|
+
*
|
|
1169
|
+
* Accepts a {@link BusNamespaceDefinition} created by `createBusNamespace()` from
|
|
1170
|
+
* `@makaio/core`. The FilterPayload type parameter is computed eagerly from the
|
|
1171
|
+
* schemas, enabling type-safe filtering via `withFilter()`.
|
|
1172
|
+
* @param definition - Namespace definition created by `createBusNamespace()`
|
|
1173
|
+
* @returns The registered namespace with `scopedBus()` and pre-computed FilterPayload type
|
|
1174
|
+
*/
|
|
1175
|
+
registerNamespace<Domain extends string, Schemas extends Record<string, SubjectSchema>>(definition: BusNamespaceDefinition<Domain, Schemas>): BusNamespace<Domain, SubjectRecordFromSchemaRecord<Schemas>, FilterablePayloadIntersection<SubjectRecordFromSchemaRecord<Schemas>>, Schemas>;
|
|
1176
|
+
/**
|
|
1177
|
+
* Register multiple namespaces in a single call.
|
|
1178
|
+
*
|
|
1179
|
+
* Iterates `definitions` and calls `registerNamespace()` for each. Useful
|
|
1180
|
+
* at composition roots to register a catalog of namespace definitions in one
|
|
1181
|
+
* statement:
|
|
1182
|
+
*
|
|
1183
|
+
* ```typescript
|
|
1184
|
+
* MakaioBus.registerNamespaces(FrameworkContractNamespaces);
|
|
1185
|
+
* ```
|
|
1186
|
+
* @param definitions - Array of namespace definitions to register
|
|
1187
|
+
*/
|
|
1188
|
+
registerNamespaces(definitions: readonly RegistrableBusNamespaceDefinition[]): void;
|
|
1189
|
+
/**
|
|
1190
|
+
* Get the schema for a registered subject.
|
|
1191
|
+
* Returns the unwrapped schema (LocalSubjectSchema and ChannelSubjectSchema wrappers are removed during registration).
|
|
1192
|
+
* @param subject - Subject identifier (e.g., "adapter.getCapabilities")
|
|
1193
|
+
* @returns Schema if found, undefined otherwise
|
|
1194
|
+
*/
|
|
1195
|
+
getSchema(subject: string | SubjectDefinition): BaseSubjectSchema | undefined;
|
|
1196
|
+
/**
|
|
1197
|
+
* List all registered subjects with their runtime schema metadata.
|
|
1198
|
+
* @returns Registered subjects sorted by fully-qualified subject key
|
|
1199
|
+
*/
|
|
1200
|
+
listRegisteredSubjects(): RegisteredSubjectSchema[];
|
|
1201
|
+
/**
|
|
1202
|
+
* Check if a subject is registered as a request subject.
|
|
1203
|
+
* @param subject - Subject identifier
|
|
1204
|
+
* @returns True if subject exists and is a request schema
|
|
1205
|
+
*/
|
|
1206
|
+
isRequestSubject(subject: string): boolean;
|
|
1207
|
+
/**
|
|
1208
|
+
* Check if a subject was registered as a local-only subject.
|
|
1209
|
+
*
|
|
1210
|
+
* Local subjects must never be routed over transports. The `__local` flag
|
|
1211
|
+
* is stripped by `unwrapSchema`, so locality is tracked in a separate set
|
|
1212
|
+
* populated at registration time.
|
|
1213
|
+
* @param subject - Full subject identifier (e.g., "widget.register")
|
|
1214
|
+
* @returns True if the subject was wrapped with `localSubject()`
|
|
1215
|
+
*/
|
|
1216
|
+
isLocalSubject(subject: string): boolean;
|
|
1217
|
+
/**
|
|
1218
|
+
* Get the validation configuration for a subject.
|
|
1219
|
+
*
|
|
1220
|
+
* Looks up the namespace from the subject's prefix and returns
|
|
1221
|
+
* the registered mode and optional violation callback.
|
|
1222
|
+
* @param subject - Full subject identifier (e.g., "adapter:claude-code.sdk.event")
|
|
1223
|
+
* @returns Validation config, or `{ mode: 'strict' }` if none registered
|
|
1224
|
+
*/
|
|
1225
|
+
getValidationConfig(subject: string): ValidationConfig;
|
|
1226
|
+
/**
|
|
1227
|
+
* Additively extend a registered subject's schema with new fields.
|
|
1228
|
+
*
|
|
1229
|
+
* For request subjects, extends the request and/or response ZodObject via `.extend()`.
|
|
1230
|
+
* For event subjects, extends the event ZodObject directly.
|
|
1231
|
+
* Successive calls accumulate fields; if a later extension redefines an existing key, the later definition wins (Zod `.extend()` semantics).
|
|
1232
|
+
* @param fullSubjectKey - Fully-qualified key (e.g., "session.list")
|
|
1233
|
+
* @param additionalFields - For request subjects: `{ request?, response? }` each a record
|
|
1234
|
+
* of Zod field definitions. For event subjects: a flat record of Zod field definitions.
|
|
1235
|
+
* @throws Error if the subject is not registered or the existing schema is not a ZodObject
|
|
1236
|
+
*/
|
|
1237
|
+
extendSubjectSchema(fullSubjectKey: string, additionalFields: z.ZodRawShape | {
|
|
1238
|
+
request?: z.ZodRawShape;
|
|
1239
|
+
response?: z.ZodRawShape;
|
|
1240
|
+
}): void;
|
|
1241
|
+
/**
|
|
1242
|
+
* Reset all registered namespaces (for testing only).
|
|
1243
|
+
* @internal
|
|
1244
|
+
*/
|
|
1245
|
+
__resetNamespaces: (() => void) | undefined;
|
|
1246
|
+
};
|
|
1247
|
+
type NamespaceRegistry = ReturnType<typeof createNamespaceRegistry>;
|
|
1248
|
+
//#endregion
|
|
1249
|
+
//#region packages/bus-core/src/registries/transport-registry.d.ts
|
|
1250
|
+
interface BusTransportRegistry extends Record<string, BusTransport> {}
|
|
1251
|
+
type BusTransportKeys = keyof BusTransportRegistry;
|
|
1252
|
+
/**
|
|
1253
|
+
* Creates the transport registry used by a bus context.
|
|
1254
|
+
*
|
|
1255
|
+
* Manages connected transports, handles inbound message routing (events,
|
|
1256
|
+
* requests, broadcasts), and relays messages to other registered transports.
|
|
1257
|
+
* @param context - Bus context that owns this registry
|
|
1258
|
+
* @returns Transport registry with registerTransport, getTransport, all,
|
|
1259
|
+
* names, and getPendingReady methods
|
|
1260
|
+
*/
|
|
1261
|
+
/**
|
|
1262
|
+
* Callback interface for transport lifecycle event emission.
|
|
1263
|
+
*
|
|
1264
|
+
* Set on the transport registry by the bus after construction so that
|
|
1265
|
+
* connect/disconnect transitions emit `BusLifecycle.connected` /
|
|
1266
|
+
* `BusLifecycle.disconnected` automatically for every registered transport.
|
|
1267
|
+
*/
|
|
1268
|
+
interface TransportLifecycleEmitter {
|
|
1269
|
+
/**
|
|
1270
|
+
* Called when a transport establishes a connection.
|
|
1271
|
+
* @param transportName - Name of the connected transport.
|
|
1272
|
+
*/
|
|
1273
|
+
onConnected(transportName: string): void;
|
|
1274
|
+
/**
|
|
1275
|
+
* Called when a transport loses connection unexpectedly.
|
|
1276
|
+
* @param transportName - Name of the disconnected transport.
|
|
1277
|
+
*/
|
|
1278
|
+
onDisconnected(transportName: string): void;
|
|
1279
|
+
}
|
|
1280
|
+
declare const createTransportRegistry: (context: MakaioBusContext) => {
|
|
1281
|
+
registerTransport<K extends BusTransportKeys>(name: K, transport: BusTransportRegistry[K]): TransportRegistration;
|
|
1282
|
+
getTransport<K extends BusTransportKeys>(name: K): BusTransportRegistry[K] | undefined;
|
|
1283
|
+
all(): BusTransport[];
|
|
1284
|
+
names(): BusTransportKeys[];
|
|
1285
|
+
/**
|
|
1286
|
+
* Return all unresolved transport `ready` promises for dispatch-level gating.
|
|
1287
|
+
*
|
|
1288
|
+
* Use `Promise.all(registry.getPendingReady())` to await full initialization.
|
|
1289
|
+
* @returns Array of pending ready promises (empty when all transports are ready)
|
|
1290
|
+
*/
|
|
1291
|
+
getPendingReady(): Promise<void>[];
|
|
1292
|
+
/**
|
|
1293
|
+
* Set the lifecycle emitter used to publish `BusLifecycle.connected` /
|
|
1294
|
+
* `BusLifecycle.disconnected` events whenever a transport connects or
|
|
1295
|
+
* disconnects.
|
|
1296
|
+
*
|
|
1297
|
+
* Called once by the owning bus after construction. Subsequent transport
|
|
1298
|
+
* registrations automatically pick up the emitter through the closure.
|
|
1299
|
+
* @param emitter - Lifecycle emitter to install.
|
|
1300
|
+
*/
|
|
1301
|
+
setLifecycleEmitter(emitter: TransportLifecycleEmitter): void;
|
|
1302
|
+
};
|
|
1303
|
+
type TransportRegistry = ReturnType<typeof createTransportRegistry>;
|
|
1304
|
+
//#endregion
|
|
1305
|
+
//#region packages/bus-core/src/types/transports.d.ts
|
|
1306
|
+
/**
|
|
1307
|
+
* Subscribe message for client subscription management.
|
|
1308
|
+
*
|
|
1309
|
+
* Supports both subject-based filtering (wildcards) and payload-based filtering
|
|
1310
|
+
* (declarative filter specs). Both are applied server-side for smart-routing.
|
|
1311
|
+
*
|
|
1312
|
+
* Priority arrays enable cross-transport priority-based dispatch: the receiver
|
|
1313
|
+
* uses the arrays to populate its remote handler registry so that dispatch can
|
|
1314
|
+
* consider handler priorities across process boundaries.
|
|
1315
|
+
* @example
|
|
1316
|
+
* ```typescript
|
|
1317
|
+
* // Request handler with priorities
|
|
1318
|
+
* { type: 'subscribe', subjects: { 'ui.navigate': [100, 200] } }
|
|
1319
|
+
*
|
|
1320
|
+
* // Event-only handler (no priority-based dispatch)
|
|
1321
|
+
* { type: 'subscribe', subjects: { 'session.created': [] } }
|
|
1322
|
+
* ```
|
|
1323
|
+
*/
|
|
1324
|
+
interface BusSubscribeMessage {
|
|
1325
|
+
type: 'subscribe';
|
|
1326
|
+
/**
|
|
1327
|
+
* Subjects and their handler priorities.
|
|
1328
|
+
* Keys are subject patterns (can include wildcards like `'adapter.*'`).
|
|
1329
|
+
* Values are arrays of handler priorities registered for that subject.
|
|
1330
|
+
* An empty array indicates event-only handlers with no priority-based dispatch.
|
|
1331
|
+
*/
|
|
1332
|
+
subjects: Record<string, number[]>;
|
|
1333
|
+
/**
|
|
1334
|
+
* Optional payload filters per subject.
|
|
1335
|
+
* Key is the subject pattern, value is the filter to apply.
|
|
1336
|
+
* Messages are only forwarded if payload matches the filter.
|
|
1337
|
+
* @example
|
|
1338
|
+
* ```typescript
|
|
1339
|
+
* {
|
|
1340
|
+
* subjects: { 'mcp.event': [] },
|
|
1341
|
+
* filters: {
|
|
1342
|
+
* 'mcp.event': { agentId: 'agent-123' }
|
|
1343
|
+
* }
|
|
1344
|
+
* }
|
|
1345
|
+
* ```
|
|
1346
|
+
*/
|
|
1347
|
+
filters?: Record<string, PayloadFilter>;
|
|
1348
|
+
}
|
|
1349
|
+
/**
|
|
1350
|
+
* Unsubscribe message for client subscription management.
|
|
1351
|
+
*
|
|
1352
|
+
* Priority arrays enable ref-counted unsubscription: the receiver removes only
|
|
1353
|
+
* the listed handler priorities from its remote handler registry rather than
|
|
1354
|
+
* wiping the entire subject entry.
|
|
1355
|
+
*/
|
|
1356
|
+
interface BusUnsubscribeMessage {
|
|
1357
|
+
type: 'unsubscribe';
|
|
1358
|
+
/**
|
|
1359
|
+
* Subjects and the handler priorities being removed.
|
|
1360
|
+
* Keys are subject patterns.
|
|
1361
|
+
* Values are the specific priorities being unregistered (for ref-counting).
|
|
1362
|
+
* An empty array removes the subject entirely (no handlers remain).
|
|
1363
|
+
*/
|
|
1364
|
+
subjects: Record<string, number[]>;
|
|
1365
|
+
}
|
|
1366
|
+
/**
|
|
1367
|
+
* Subscribe-sync-complete handshake message.
|
|
1368
|
+
*
|
|
1369
|
+
* Sent by the bus to a newly registered transport after the current handler
|
|
1370
|
+
* subscriptions have been pushed. The recipient resolves its `ready` promise
|
|
1371
|
+
* upon receipt, signalling that priority-based request dispatch may safely
|
|
1372
|
+
* route through the transport.
|
|
1373
|
+
*/
|
|
1374
|
+
interface BusSubscribeSyncCompleteMessage {
|
|
1375
|
+
type: 'subscribe-sync-complete';
|
|
1376
|
+
}
|
|
1377
|
+
/**
|
|
1378
|
+
* Message types for transport wire protocol.
|
|
1379
|
+
*/
|
|
1380
|
+
type BusMessage = BusRequestMessage | BusResponseMessage | BusEventMessage | BusBroadcastMessage | BusBroadcastResponseMessage | BusHeartbeatMessage | BusSubscribeMessage | BusUnsubscribeMessage | BusSubscribeSyncCompleteMessage;
|
|
1381
|
+
/**
|
|
1382
|
+
* Handler invoked by transports when a bus message arrives.
|
|
1383
|
+
*
|
|
1384
|
+
* The optional receive context is trusted local metadata supplied by the
|
|
1385
|
+
* receiving transport. It must not be serialized or relayed to other nodes.
|
|
1386
|
+
*/
|
|
1387
|
+
type BusReceiveHandler = (message: BusMessage, context?: TransportReceiveContext) => Promise<void>;
|
|
1388
|
+
/**
|
|
1389
|
+
* Heartbeat message for connection keep-alive.
|
|
1390
|
+
*/
|
|
1391
|
+
interface BusHeartbeatMessage {
|
|
1392
|
+
type: 'heartbeat';
|
|
1393
|
+
timestamp: number;
|
|
1394
|
+
}
|
|
1395
|
+
/**
|
|
1396
|
+
* Request message sent over transport.
|
|
1397
|
+
*/
|
|
1398
|
+
interface BusRequestMessage {
|
|
1399
|
+
type: 'request';
|
|
1400
|
+
subject: string;
|
|
1401
|
+
namespace: string;
|
|
1402
|
+
payload: unknown;
|
|
1403
|
+
correlationId: string;
|
|
1404
|
+
messageId: string;
|
|
1405
|
+
/**
|
|
1406
|
+
* Caller-specified request timeout in milliseconds.
|
|
1407
|
+
*
|
|
1408
|
+
* Propagated across relay hops so intermediate transport registries use the
|
|
1409
|
+
* same timeout policy as the original caller.
|
|
1410
|
+
* A value of `0` means no automatic timeout.
|
|
1411
|
+
*/
|
|
1412
|
+
timeout?: number;
|
|
1413
|
+
/**
|
|
1414
|
+
* Priority cursor for cross-transport priority-based dispatch.
|
|
1415
|
+
*
|
|
1416
|
+
* When set, dispatch considers only handlers with a priority strictly below
|
|
1417
|
+
* this value, enabling the chain to continue from where a previous hop left off.
|
|
1418
|
+
* Omitted on the first dispatch hop (meaning start from the highest priority).
|
|
1419
|
+
*/
|
|
1420
|
+
priority?: number;
|
|
1421
|
+
/**
|
|
1422
|
+
* Absolute dispatch deadline as a Unix timestamp in milliseconds (`Date.now() + timeout`).
|
|
1423
|
+
*
|
|
1424
|
+
* Set on the first dispatch hop and propagated through all subsequent hops so
|
|
1425
|
+
* that each hop can compute its remaining time budget without relying on the
|
|
1426
|
+
* original timeout value alone.
|
|
1427
|
+
*/
|
|
1428
|
+
deadline?: number;
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Structured error payload for transport responses.
|
|
1432
|
+
*/
|
|
1433
|
+
interface BusTransportError {
|
|
1434
|
+
/** Human-readable error message */
|
|
1435
|
+
message: string;
|
|
1436
|
+
/** Error code for programmatic handling (e.g., 'IMPORT_CONFLICT') */
|
|
1437
|
+
code?: string;
|
|
1438
|
+
/**
|
|
1439
|
+
* Subject this error pertains to.
|
|
1440
|
+
* Preserved for {@link NoHandlerError} so that `isNoHandlerErrorForSubject`
|
|
1441
|
+
* can match without fragile message-string comparisons after a
|
|
1442
|
+
* serialize → deserialize round-trip.
|
|
1443
|
+
*/
|
|
1444
|
+
subject?: string;
|
|
1445
|
+
/** Additional error data (e.g., conflicts, orphans) */
|
|
1446
|
+
data?: Record<string, unknown>;
|
|
1447
|
+
}
|
|
1448
|
+
/**
|
|
1449
|
+
* Response message sent over transport.
|
|
1450
|
+
*/
|
|
1451
|
+
interface BusResponseMessage {
|
|
1452
|
+
type: 'response';
|
|
1453
|
+
correlationId: string;
|
|
1454
|
+
result?: unknown;
|
|
1455
|
+
error?: BusTransportError;
|
|
1456
|
+
}
|
|
1457
|
+
/**
|
|
1458
|
+
* Event message sent over transport.
|
|
1459
|
+
*/
|
|
1460
|
+
interface BusEventMessage {
|
|
1461
|
+
type: 'event';
|
|
1462
|
+
subject: string;
|
|
1463
|
+
namespace: string;
|
|
1464
|
+
payload: unknown;
|
|
1465
|
+
messageId: string;
|
|
1466
|
+
correlationId?: string;
|
|
1467
|
+
}
|
|
1468
|
+
/**
|
|
1469
|
+
* Broadcast request message sent over transport.
|
|
1470
|
+
*
|
|
1471
|
+
* Unlike regular requests (single response), broadcasts expect
|
|
1472
|
+
* multiple responses aggregated into an array.
|
|
1473
|
+
*/
|
|
1474
|
+
interface BusBroadcastMessage {
|
|
1475
|
+
type: 'broadcast';
|
|
1476
|
+
subject: string;
|
|
1477
|
+
namespace: string;
|
|
1478
|
+
payload: unknown;
|
|
1479
|
+
correlationId: string;
|
|
1480
|
+
messageId: string;
|
|
1481
|
+
/**
|
|
1482
|
+
* Caller-specified broadcast timeout in milliseconds.
|
|
1483
|
+
*
|
|
1484
|
+
* Propagated across relay hops so relayed broadcast collection preserves the
|
|
1485
|
+
* original caller timeout contract.
|
|
1486
|
+
* A value of `0` means no automatic timeout.
|
|
1487
|
+
*/
|
|
1488
|
+
timeout?: number;
|
|
1489
|
+
}
|
|
1490
|
+
/**
|
|
1491
|
+
* Broadcast response message sent over transport.
|
|
1492
|
+
*
|
|
1493
|
+
* Contains an array of results from all handlers that responded.
|
|
1494
|
+
*/
|
|
1495
|
+
interface BusBroadcastResponseMessage {
|
|
1496
|
+
type: 'broadcast-response';
|
|
1497
|
+
correlationId: string;
|
|
1498
|
+
results?: Array<{
|
|
1499
|
+
nodeId: string;
|
|
1500
|
+
payload: unknown;
|
|
1501
|
+
}>;
|
|
1502
|
+
error?: BusTransportError;
|
|
1503
|
+
}
|
|
1504
|
+
/**
|
|
1505
|
+
* Transport interface for bus communication.
|
|
1506
|
+
*
|
|
1507
|
+
* Transports handle serialization, wire protocol, and connection management
|
|
1508
|
+
* for cross-process communication.
|
|
1509
|
+
* @example
|
|
1510
|
+
* ```typescript
|
|
1511
|
+
* class WebSocketTransport implements BusTransport {
|
|
1512
|
+
* readonly name = 'websocket';
|
|
1513
|
+
*
|
|
1514
|
+
* async send(message: BusMessage): Promise<void> {
|
|
1515
|
+
* this.ws.send(JSON.stringify(message));
|
|
1516
|
+
* }
|
|
1517
|
+
*
|
|
1518
|
+
* onReceive(handler: BusReceiveHandler): () => void {
|
|
1519
|
+
* const listener = (data) => {
|
|
1520
|
+
* const message = JSON.parse(data) as BusMessage;
|
|
1521
|
+
* const context: TransportReceiveContext = { transportName: this.name };
|
|
1522
|
+
* void handler(message, context);
|
|
1523
|
+
* };
|
|
1524
|
+
* this.ws.on('message', listener);
|
|
1525
|
+
* return () => this.ws.off('message', listener);
|
|
1526
|
+
* }
|
|
1527
|
+
*
|
|
1528
|
+
* async connect(): Promise<void> {
|
|
1529
|
+
* await this.ws.connect();
|
|
1530
|
+
* }
|
|
1531
|
+
*
|
|
1532
|
+
* async disconnect(): Promise<void> {
|
|
1533
|
+
* await this.ws.close();
|
|
1534
|
+
* }
|
|
1535
|
+
* }
|
|
1536
|
+
* ```
|
|
1537
|
+
*/
|
|
1538
|
+
interface BusTransport {
|
|
1539
|
+
/**
|
|
1540
|
+
* Unique transport name used as the registry key.
|
|
1541
|
+
*
|
|
1542
|
+
* The name is used by `IMakaioBus.registerTransport()` to key the transport
|
|
1543
|
+
* in the internal registry. It must be unique within a single bus instance.
|
|
1544
|
+
* Implementations should declare this as a `readonly` literal or class field.
|
|
1545
|
+
* @example
|
|
1546
|
+
* ```typescript
|
|
1547
|
+
* class MyTransport implements BusTransport {
|
|
1548
|
+
* readonly name = 'my-transport';
|
|
1549
|
+
* }
|
|
1550
|
+
* ```
|
|
1551
|
+
*/
|
|
1552
|
+
name: string;
|
|
1553
|
+
/**
|
|
1554
|
+
* Send a message over the transport.
|
|
1555
|
+
*
|
|
1556
|
+
* **Behavior by message type:**
|
|
1557
|
+
* - **Requests** (`BusRequestMessage`): Returns the response payload from the handler.
|
|
1558
|
+
* Throws error if no clients available to handle request (server mode).
|
|
1559
|
+
* - **Events** (`BusEventMessage`): Returns delivery status boolean.
|
|
1560
|
+
* - `true`: Delivered to at least one recipient
|
|
1561
|
+
* - `false`: No recipients available (not an error)
|
|
1562
|
+
* - **Other messages** (heartbeat, subscribe, etc.): Returns `true` if sent successfully.
|
|
1563
|
+
*
|
|
1564
|
+
* **Error handling:**
|
|
1565
|
+
* - Throws when transport is disconnected
|
|
1566
|
+
* - Throws when sending requests with no connected clients (server mode only)
|
|
1567
|
+
* - Never throws for events - returns `false` instead
|
|
1568
|
+
*
|
|
1569
|
+
* **Timeout contract:**
|
|
1570
|
+
* The `timeout` value flows from the caller's `bus.request({ timeout })` option
|
|
1571
|
+
* through the dispatch layer to the transport's correlation tracker.
|
|
1572
|
+
* A value of `0` means no automatic timeout — the promise stays open until
|
|
1573
|
+
* resolved or rejected externally (e.g. by the caller's own AbortSignal).
|
|
1574
|
+
* @param message - Message to send
|
|
1575
|
+
* @param timeout - Correlation timeout in milliseconds; `0` means no automatic timeout
|
|
1576
|
+
* @returns Promise resolving to response payload (requests) or delivery status (events/other)
|
|
1577
|
+
* @example
|
|
1578
|
+
* ```typescript
|
|
1579
|
+
* // Request: type-safe response handling
|
|
1580
|
+
* const request: BusRequestMessage = {
|
|
1581
|
+
* type: 'request',
|
|
1582
|
+
* subject: 'user.get',
|
|
1583
|
+
* namespace: 'api',
|
|
1584
|
+
* payload: { id: 123 },
|
|
1585
|
+
* correlationId: 'req-1',
|
|
1586
|
+
* messageId: 'msg-1',
|
|
1587
|
+
* };
|
|
1588
|
+
* const response = await transport.send(request, 5000); // response: unknown
|
|
1589
|
+
*
|
|
1590
|
+
* // Event: delivery status
|
|
1591
|
+
* const event: BusEventMessage = {
|
|
1592
|
+
* type: 'event',
|
|
1593
|
+
* subject: 'user.created',
|
|
1594
|
+
* namespace: 'api',
|
|
1595
|
+
* payload: { id: 123 },
|
|
1596
|
+
* messageId: 'evt-1',
|
|
1597
|
+
* };
|
|
1598
|
+
* const delivered = await transport.send(event, 0); // delivered: boolean
|
|
1599
|
+
* if (!delivered) {
|
|
1600
|
+
* console.warn('Event not delivered - no subscribers');
|
|
1601
|
+
* }
|
|
1602
|
+
* ```
|
|
1603
|
+
*/
|
|
1604
|
+
send<TMessage extends BusMessage>(message: TMessage, timeout?: number): Promise<TMessage extends BusRequestMessage ? unknown : TMessage extends BusBroadcastMessage ? Array<{
|
|
1605
|
+
nodeId: string;
|
|
1606
|
+
payload: unknown;
|
|
1607
|
+
}> : boolean>;
|
|
1608
|
+
/**
|
|
1609
|
+
* Optional: cancel/cleanup pending correlation state for an in-flight request.
|
|
1610
|
+
*
|
|
1611
|
+
* Used when the caller aborts while the transport-level correlation promise is
|
|
1612
|
+
* still pending (e.g. timeout `0` + AbortSignal). Implementations should reject
|
|
1613
|
+
* and remove the correlation entry if present.
|
|
1614
|
+
* @param correlationId - Correlation ID to cancel
|
|
1615
|
+
* @param error - Optional cancellation error to propagate
|
|
1616
|
+
*/
|
|
1617
|
+
cancelRequest?(correlationId: string, error?: Error): void;
|
|
1618
|
+
/**
|
|
1619
|
+
* Register a handler for incoming messages.
|
|
1620
|
+
* @param handler - Handler function
|
|
1621
|
+
* @returns Unsubscribe function
|
|
1622
|
+
*/
|
|
1623
|
+
onReceive(handler: BusReceiveHandler): () => void;
|
|
1624
|
+
/**
|
|
1625
|
+
* Connect the transport.
|
|
1626
|
+
*/
|
|
1627
|
+
connect(): Promise<void>;
|
|
1628
|
+
/**
|
|
1629
|
+
* Disconnect the transport.
|
|
1630
|
+
*/
|
|
1631
|
+
disconnect(): Promise<void>;
|
|
1632
|
+
/**
|
|
1633
|
+
* Optional: Trigger an immediate reconnection attempt, bypassing any backoff wait.
|
|
1634
|
+
*
|
|
1635
|
+
* If the transport is currently waiting in an exponential-backoff delay, calling
|
|
1636
|
+
* this wakes it immediately so a new connection attempt starts without waiting.
|
|
1637
|
+
* If reconnection is disabled on the transport, a one-shot connect attempt is made.
|
|
1638
|
+
* No-op when the transport is already connected.
|
|
1639
|
+
* @returns Promise that resolves when the attempt is initiated or completes
|
|
1640
|
+
*/
|
|
1641
|
+
reconnect?(): Promise<void>;
|
|
1642
|
+
/**
|
|
1643
|
+
* Optional: Promise that resolves when the transport is fully operational
|
|
1644
|
+
* (end-to-end, including remote handler availability).
|
|
1645
|
+
*
|
|
1646
|
+
* Resolved after the bus has sent the initial subscribe sync to the transport
|
|
1647
|
+
* and the transport has received the {@link BusSubscribeSyncCompleteMessage}
|
|
1648
|
+
* handshake. Before this resolves, `remoteRequestHandlers` for this transport
|
|
1649
|
+
* may be incomplete and requests should not be routed through it.
|
|
1650
|
+
*
|
|
1651
|
+
* Transports that do not implement `ready` are considered immediately ready.
|
|
1652
|
+
* @remarks
|
|
1653
|
+
* Transports that do not implement `onNewReadySession` are single-use:
|
|
1654
|
+
* after `disconnect()` completes, a later `connect()` call has undefined
|
|
1655
|
+
* behavior. Reconnectable transports must call `onNewReadySession` each time
|
|
1656
|
+
* they create a new `ready` promise so the registry can update its gating.
|
|
1657
|
+
*/
|
|
1658
|
+
ready?: Promise<void>;
|
|
1659
|
+
/**
|
|
1660
|
+
* Optional callback set by the transport registry during registration.
|
|
1661
|
+
* Transports that support reconnection call this at the start of each
|
|
1662
|
+
* new session so the registry can track the new ready promise for
|
|
1663
|
+
* dispatch gating.
|
|
1664
|
+
* @param promise - The new ready promise for the current session
|
|
1665
|
+
*/
|
|
1666
|
+
onNewReadySession?: (promise: Promise<void>) => void;
|
|
1667
|
+
/**
|
|
1668
|
+
* Optional callback set by the transport registry during registration.
|
|
1669
|
+
* Called each time the transport establishes a connection (initial or reconnect),
|
|
1670
|
+
* after authentication and subscription replay are complete.
|
|
1671
|
+
*/
|
|
1672
|
+
onConnected?: () => void;
|
|
1673
|
+
/**
|
|
1674
|
+
* Optional callback set by the transport registry during registration.
|
|
1675
|
+
* Called when the transport loses its connection unexpectedly.
|
|
1676
|
+
* Not called on an explicit `disconnect()`.
|
|
1677
|
+
*/
|
|
1678
|
+
onDisconnected?: () => void;
|
|
1679
|
+
/**
|
|
1680
|
+
* Optional: Synchronous readiness check for transport-level gating.
|
|
1681
|
+
*
|
|
1682
|
+
* When implemented and returning `false`, the bus skips this transport
|
|
1683
|
+
* for outbound sends (requests, broadcasts, events). The transport
|
|
1684
|
+
* continues to receive inbound messages via `onReceive`.
|
|
1685
|
+
*
|
|
1686
|
+
* Complements the async `ready` promise: `isReady()` enables non-blocking
|
|
1687
|
+
* skip decisions in hot paths, while `ready` supports await-based flows.
|
|
1688
|
+
* @returns `true` if the transport can send messages, `false` otherwise
|
|
1689
|
+
*/
|
|
1690
|
+
isReady?(): boolean;
|
|
1691
|
+
/**
|
|
1692
|
+
* Optional: Report which subjects this transport is interested in.
|
|
1693
|
+
* Enables transport-level filtering for efficiency.
|
|
1694
|
+
*
|
|
1695
|
+
* If not implemented, the transport will receive all messages (broadcast mode).
|
|
1696
|
+
* If implemented, only messages matching the subscription patterns will be sent.
|
|
1697
|
+
*
|
|
1698
|
+
* Patterns can include wildcards (e.g., 'adapter.*' matches 'adapter.log', 'adapter.init', etc.)
|
|
1699
|
+
* @returns Set of subscription patterns (can include wildcards)
|
|
1700
|
+
*/
|
|
1701
|
+
getSubscriptions?(): Set<string>;
|
|
1702
|
+
/**
|
|
1703
|
+
* Subscribe to a subject for smart-routing.
|
|
1704
|
+
*
|
|
1705
|
+
* Transports use this to track which subjects have active handlers,
|
|
1706
|
+
* enabling targeted message delivery instead of broadcast.
|
|
1707
|
+
*
|
|
1708
|
+
* When `priorities` is provided the transport should include the priority
|
|
1709
|
+
* information in the next outbound subscribe wire message for this subject,
|
|
1710
|
+
* enabling cross-transport priority-based dispatch on the remote side.
|
|
1711
|
+
* Calling this method again with a new `priorities` array replaces the
|
|
1712
|
+
* previously advertised set for that subject (re-subscribe semantics).
|
|
1713
|
+
*
|
|
1714
|
+
* Transports that do not need subscription management (e.g. local-only
|
|
1715
|
+
* loopback transports) should provide a no-op implementation.
|
|
1716
|
+
* @param subject - Subject pattern to subscribe to (can include wildcards)
|
|
1717
|
+
* @param filter - Optional payload filter for fine-grained routing
|
|
1718
|
+
* @param priorities - Handler priorities registered for this subject; an empty
|
|
1719
|
+
* array signals event-only handlers that do not participate in priority dispatch
|
|
1720
|
+
*/
|
|
1721
|
+
subscribe(subject: string, filter?: PayloadFilter, priorities?: number[]): Promise<void>;
|
|
1722
|
+
/**
|
|
1723
|
+
* Unsubscribe from a subject.
|
|
1724
|
+
*
|
|
1725
|
+
* Called when the last handler for a subject is removed, allowing the
|
|
1726
|
+
* transport to stop routing messages for that subject.
|
|
1727
|
+
*
|
|
1728
|
+
* Transports that do not need subscription management should provide a
|
|
1729
|
+
* no-op implementation.
|
|
1730
|
+
* @param subject - Subject pattern to unsubscribe from
|
|
1731
|
+
*/
|
|
1732
|
+
unsubscribe(subject: string): Promise<void>;
|
|
1733
|
+
/**
|
|
1734
|
+
* Receive aggregated broadcast results from the transport registry.
|
|
1735
|
+
*
|
|
1736
|
+
* Called by the transport registry after executing local handlers and relaying
|
|
1737
|
+
* to other transports for a broadcast that arrived from this transport via
|
|
1738
|
+
* `onReceive`. Replaces the legacy `send({ type: 'broadcast-response' })`
|
|
1739
|
+
* side-channel when implemented.
|
|
1740
|
+
*
|
|
1741
|
+
* Transports that manage their own peer-level fan-out (e.g., ServerTransport
|
|
1742
|
+
* with multiple WebSocket clients) implement this to receive registry results
|
|
1743
|
+
* without abusing the `send()` contract.
|
|
1744
|
+
* @param correlationId - Correlation ID of the originating broadcast
|
|
1745
|
+
* @param results - Aggregated results from local handlers and relay transports
|
|
1746
|
+
* @param error - Optional structured error when broadcast processing failed;
|
|
1747
|
+
* results may be empty or partial in this case
|
|
1748
|
+
*/
|
|
1749
|
+
onBroadcastResults?(correlationId: string, results: ReadonlyArray<{
|
|
1750
|
+
nodeId: string;
|
|
1751
|
+
payload: unknown;
|
|
1752
|
+
}>, error?: BusTransportError): void;
|
|
1753
|
+
}
|
|
1754
|
+
//#endregion
|
|
1755
|
+
//#region packages/bus-core/src/methods/broadcast.d.ts
|
|
1756
|
+
/**
|
|
1757
|
+
* Result from a single handler in a broadcast.
|
|
1758
|
+
* @typeParam T - Response payload type
|
|
1759
|
+
*/
|
|
1760
|
+
interface BroadcastResult<T> {
|
|
1761
|
+
/** Handler identifier (set via ctx.identify() in handler, or 'anonymous' if not set) */
|
|
1762
|
+
nodeId: string;
|
|
1763
|
+
/** Response payload from the handler */
|
|
1764
|
+
payload: T;
|
|
1765
|
+
}
|
|
1766
|
+
/**
|
|
1767
|
+
* Extended request context for broadcast handlers.
|
|
1768
|
+
* Adds identify() method to tag responses with a node identifier.
|
|
1769
|
+
*/
|
|
1770
|
+
interface BroadcastContext<Request, Response> extends RequestContext<Request, Response> {
|
|
1771
|
+
/**
|
|
1772
|
+
* Identify this handler for broadcast aggregation.
|
|
1773
|
+
* Call before setResult() to tag the response with a nodeId.
|
|
1774
|
+
* @param nodeId - Unique identifier for this handler/node
|
|
1775
|
+
*/
|
|
1776
|
+
identify: (nodeId: string) => void;
|
|
1777
|
+
}
|
|
1778
|
+
//#endregion
|
|
1779
|
+
//#region packages/bus-core/src/types/options.d.ts
|
|
1780
|
+
/**
|
|
1781
|
+
* Default request timeout in milliseconds.
|
|
1782
|
+
*
|
|
1783
|
+
* Shared policy constant used when callers omit `RequestOptions.timeout`.
|
|
1784
|
+
*/
|
|
1785
|
+
declare const DEFAULT_REQUEST_TIMEOUT_MS = 60000;
|
|
1786
|
+
/**
|
|
1787
|
+
* Options for subscribing to events/requests via on().
|
|
1788
|
+
*/
|
|
1789
|
+
interface OnOptions {
|
|
1790
|
+
/**
|
|
1791
|
+
* Explicit handler registry target for wildcard subjects.
|
|
1792
|
+
*
|
|
1793
|
+
* Exact subjects derive their registry from the subject schema. Wildcard
|
|
1794
|
+
* subjects can match both events and requests, so callers that know their
|
|
1795
|
+
* intent can pin the registration to event-only or request-only. Omit this
|
|
1796
|
+
* option to preserve the historical ambiguous wildcard behavior.
|
|
1797
|
+
*/
|
|
1798
|
+
handlerKind?: 'event' | 'request' | 'both';
|
|
1799
|
+
/**
|
|
1800
|
+
* Declarative payload filter for smart-routing.
|
|
1801
|
+
*
|
|
1802
|
+
* Applied both locally (before handler invocation) and can be sent
|
|
1803
|
+
* to transports for server-side filtering.
|
|
1804
|
+
*
|
|
1805
|
+
* All conditions are ANDed together.
|
|
1806
|
+
* @example
|
|
1807
|
+
* ```typescript
|
|
1808
|
+
* bus.on(Subjects.message, handler, {
|
|
1809
|
+
* filter: {
|
|
1810
|
+
* agentId: 'agent-123',
|
|
1811
|
+
* status: { $in: ['active', 'pending'] },
|
|
1812
|
+
* }
|
|
1813
|
+
* });
|
|
1814
|
+
* ```
|
|
1815
|
+
*/
|
|
1816
|
+
filter?: PayloadFilter;
|
|
1817
|
+
/**
|
|
1818
|
+
* Handler priority for middleware-style ordering.
|
|
1819
|
+
*
|
|
1820
|
+
* Higher values run earlier. Default is 0.
|
|
1821
|
+
* Handlers with equal priority preserve registration order.
|
|
1822
|
+
* @example
|
|
1823
|
+
* ```typescript
|
|
1824
|
+
* // Authentication runs first (highest priority)
|
|
1825
|
+
* bus.on(Subjects.request, authHandler, { priority: 100 });
|
|
1826
|
+
*
|
|
1827
|
+
* // Logging runs next
|
|
1828
|
+
* bus.on(Subjects.request, logHandler, { priority: 50 });
|
|
1829
|
+
*
|
|
1830
|
+
* // Business logic runs last (default priority)
|
|
1831
|
+
* bus.on(Subjects.request, businessHandler);
|
|
1832
|
+
* ```
|
|
1833
|
+
*/
|
|
1834
|
+
priority?: number;
|
|
1835
|
+
}
|
|
1836
|
+
/**
|
|
1837
|
+
* Options for emitting events.
|
|
1838
|
+
*
|
|
1839
|
+
* Extends BaseMessage to provide message tracking.
|
|
1840
|
+
* All fields are optional - defaults will be auto-generated.
|
|
1841
|
+
*/
|
|
1842
|
+
interface EmitOptions {
|
|
1843
|
+
/**
|
|
1844
|
+
* Unique identifier for this event.
|
|
1845
|
+
* Auto-generated if not provided.
|
|
1846
|
+
*/
|
|
1847
|
+
messageId?: string;
|
|
1848
|
+
/**
|
|
1849
|
+
* Optional correlation ID for linking related operations.
|
|
1850
|
+
* Useful for tracking events as part of a larger workflow.
|
|
1851
|
+
*/
|
|
1852
|
+
correlationId?: string;
|
|
1853
|
+
/**
|
|
1854
|
+
* Optional set of transport keys to send this event over.
|
|
1855
|
+
* If not specified, the event will be emitted locally and relayed to all ready transports.
|
|
1856
|
+
* Can be provided as a Set or Array of transport names.
|
|
1857
|
+
*/
|
|
1858
|
+
transports?: Set<BusTransportKeys> | Array<BusTransportKeys>;
|
|
1859
|
+
}
|
|
1860
|
+
/**
|
|
1861
|
+
* Options for making requests.
|
|
1862
|
+
*
|
|
1863
|
+
* Extends EmitOptions with request-specific settings like timeout.
|
|
1864
|
+
*/
|
|
1865
|
+
interface RequestOptions extends EmitOptions {
|
|
1866
|
+
/**
|
|
1867
|
+
* Timeout in milliseconds. Defaults to DEFAULT_REQUEST_TIMEOUT_MS (60 seconds) if not specified.
|
|
1868
|
+
* Use `0` for no automatic timeout — the request stays open until resolved,
|
|
1869
|
+
* rejected, or cancelled via the `signal` AbortSignal.
|
|
1870
|
+
*/
|
|
1871
|
+
timeout?: number;
|
|
1872
|
+
/**
|
|
1873
|
+
* AbortSignal to cancel the request.
|
|
1874
|
+
*
|
|
1875
|
+
* When aborted, the request will reject with an AbortError.
|
|
1876
|
+
* This allows callers to cancel long-running requests when they're
|
|
1877
|
+
* no longer needed (e.g., user typing invalidates previous autocomplete).
|
|
1878
|
+
* @example
|
|
1879
|
+
* ```typescript
|
|
1880
|
+
* const controller = new AbortController();
|
|
1881
|
+
* const result = MakaioBus.request(Subject, payload, {
|
|
1882
|
+
* signal: controller.signal,
|
|
1883
|
+
* });
|
|
1884
|
+
* // Later, if needed:
|
|
1885
|
+
* controller.abort();
|
|
1886
|
+
* ```
|
|
1887
|
+
*/
|
|
1888
|
+
signal?: AbortSignal;
|
|
1889
|
+
}
|
|
1890
|
+
//#endregion
|
|
1891
|
+
//#region packages/bus-core/src/types/handler-entry.d.ts
|
|
1892
|
+
/**
|
|
1893
|
+
* Handler entry with priority for middleware-style ordering.
|
|
1894
|
+
* Higher priority values run earlier in the handler chain.
|
|
1895
|
+
*/
|
|
1896
|
+
interface HandlerEntry<H> {
|
|
1897
|
+
handler: H;
|
|
1898
|
+
priority: number;
|
|
1899
|
+
}
|
|
1900
|
+
//#endregion
|
|
1901
|
+
//#region packages/bus-core/src/types/bus.d.ts
|
|
1902
|
+
/**
|
|
1903
|
+
* Internal bus context containing handler registries and shared state.
|
|
1904
|
+
*
|
|
1905
|
+
* Enables creation of isolated bus instances (e.g., for testing) by providing
|
|
1906
|
+
* separate handler maps per instance.
|
|
1907
|
+
*
|
|
1908
|
+
* Handler arrays are sorted by priority (highest first), with registration order
|
|
1909
|
+
* preserved for handlers with equal priority.
|
|
1910
|
+
*/
|
|
1911
|
+
interface MakaioBusContext {
|
|
1912
|
+
eventHandlers: Map<string, Array<HandlerEntry<EventHandler<unknown>>>>;
|
|
1913
|
+
requestHandlers: Map<string, Array<HandlerEntry<RequestHandler<unknown, unknown>>>>;
|
|
1914
|
+
interceptorHandlers: Map<string, Array<InterceptorEntry<InterceptorHandler<unknown>>>>;
|
|
1915
|
+
anyHandlers: Set<AnyHandler>;
|
|
1916
|
+
transportRegistry: TransportRegistry;
|
|
1917
|
+
namespaceRegistry: NamespaceRegistry;
|
|
1918
|
+
/** Remote handler priorities from subscribe messages; keyed by subject pattern. */
|
|
1919
|
+
remoteRequestHandlers: Map<string, Array<{
|
|
1920
|
+
transport: string;
|
|
1921
|
+
priority: number;
|
|
1922
|
+
}>>;
|
|
1923
|
+
/**
|
|
1924
|
+
* Set of transport names that have subscribed to each subject with event-only handlers
|
|
1925
|
+
* (i.e. subscribe messages whose priority array was empty).
|
|
1926
|
+
*
|
|
1927
|
+
* Tracked separately from `remoteRequestHandlers` because event-only subscriptions
|
|
1928
|
+
* produce no priority entries yet must still influence advertised-state decisions:
|
|
1929
|
+
* if a remote has event-only handlers for a subject, peers should still receive a
|
|
1930
|
+
* `subscribe` (with an empty priority array) rather than an `unsubscribe`.
|
|
1931
|
+
*/
|
|
1932
|
+
remoteEventHandlers: Map<string, Set<string>>;
|
|
1933
|
+
}
|
|
1934
|
+
/**
|
|
1935
|
+
* Result of registering a transport on the bus.
|
|
1936
|
+
*/
|
|
1937
|
+
interface TransportRegistration {
|
|
1938
|
+
/** Remove the transport from the registry and purge its remote handler entries. */
|
|
1939
|
+
unregister: () => void;
|
|
1940
|
+
/**
|
|
1941
|
+
* Resolves when initial subscribe synchronization is complete and requests
|
|
1942
|
+
* can safely route through this transport. Resolves immediately for
|
|
1943
|
+
* transports that do not implement `ready`.
|
|
1944
|
+
*/
|
|
1945
|
+
ready: Promise<void>;
|
|
1946
|
+
}
|
|
1947
|
+
/**
|
|
1948
|
+
* Options for {@link IMakaioBus.connect}.
|
|
1949
|
+
*/
|
|
1950
|
+
interface ConnectOptions {
|
|
1951
|
+
/**
|
|
1952
|
+
* Whether to await subscribe-sync readiness after connecting (default: `true`).
|
|
1953
|
+
*
|
|
1954
|
+
* When `true`, `connect()` resolves only after all transports have completed
|
|
1955
|
+
* the subscribe-sync handshake (`transport.ready`), guaranteeing
|
|
1956
|
+
* `remoteRequestHandlers` is fully populated before any request dispatch.
|
|
1957
|
+
*
|
|
1958
|
+
* Set to `false` to resolve as soon as sockets are open. Useful when the
|
|
1959
|
+
* caller needs the socket open for a custom handshake before subscribe-sync.
|
|
1960
|
+
* @defaultValue true
|
|
1961
|
+
*/
|
|
1962
|
+
awaitReady?: boolean;
|
|
1963
|
+
}
|
|
1964
|
+
type IMakaioBus<NamespaceDomain extends string | unknown = unknown, Subjects extends SubjectDefinition = SubjectDefinition, StrictNamespace = {
|
|
1965
|
+
$meta: {
|
|
1966
|
+
namespace: NamespaceDomain extends string ? NamespaceDomain : string;
|
|
1967
|
+
};
|
|
1968
|
+
}> = {
|
|
1969
|
+
namespace: NamespaceDomain;
|
|
1970
|
+
/**
|
|
1971
|
+
* Register an event or request handler.
|
|
1972
|
+
*
|
|
1973
|
+
* **Events:** Fire-and-forget - multiple handlers can listen and execute in parallel.
|
|
1974
|
+
* **Requests:** Request-response with middleware support - handlers form a chain.
|
|
1975
|
+
*
|
|
1976
|
+
* **Wildcard Support:** Use `.$all` property on subjects to match all subjects in a namespace.
|
|
1977
|
+
* Wildcard handlers receive `unknown` payload and must use type guards.
|
|
1978
|
+
* @param subject - SubjectDefinition object (exact or wildcard)
|
|
1979
|
+
* @param handler - Handler function (EventHandler for events, RequestHandler for requests)
|
|
1980
|
+
* @returns Unsubscribe function
|
|
1981
|
+
* @example Basic event handler with typed payload
|
|
1982
|
+
* ```typescript
|
|
1983
|
+
* const { subjects: AgentSubjects } = MakaioBus.registerNamespace('agent', {
|
|
1984
|
+
* started: z.object({ agentId: z.string() }),
|
|
1985
|
+
* });
|
|
1986
|
+
*
|
|
1987
|
+
* const unsubscribe = on(AgentSubjects.started, (context) => {
|
|
1988
|
+
* context.payload.agentId; // ✅ string - fully typed
|
|
1989
|
+
* console.debug('Agent started:', context.payload.agentId);
|
|
1990
|
+
* });
|
|
1991
|
+
* ```
|
|
1992
|
+
* @example Wildcard handlers for namespace-level events
|
|
1993
|
+
* ```typescript
|
|
1994
|
+
* // Matches all subjects in namespace
|
|
1995
|
+
* on(AgentSubjects.$all, (context) => {
|
|
1996
|
+
* context.payload; // unknown - must use type guards
|
|
1997
|
+
* if ('agentId' in context.payload) {
|
|
1998
|
+
* console.debug('Any agent event:', context.payload.agentId);
|
|
1999
|
+
* }
|
|
2000
|
+
* });
|
|
2001
|
+
* ```
|
|
2002
|
+
* @example Request handler with typed request/response
|
|
2003
|
+
* ```typescript
|
|
2004
|
+
* const { subjects: AgentSubjects } = MakaioBus.registerNamespace('agent', {
|
|
2005
|
+
* toolApprove: {
|
|
2006
|
+
* request: z.object({ toolName: z.string() }),
|
|
2007
|
+
* response: z.object({ approved: z.boolean() }),
|
|
2008
|
+
* },
|
|
2009
|
+
* });
|
|
2010
|
+
*
|
|
2011
|
+
* on(AgentSubjects.toolApprove, (context) => {
|
|
2012
|
+
* const { toolName } = context.payload; // ✅ fully typed
|
|
2013
|
+
* context.setResult({ approved: true });
|
|
2014
|
+
* });
|
|
2015
|
+
* ```
|
|
2016
|
+
* @example Middleware pattern for request chain
|
|
2017
|
+
* ```typescript
|
|
2018
|
+
* on(AgentSubjects.toolApprove, async (context) => {
|
|
2019
|
+
* console.debug('Before approval');
|
|
2020
|
+
* await context.next();
|
|
2021
|
+
* console.debug('After approval');
|
|
2022
|
+
* });
|
|
2023
|
+
* ```
|
|
2024
|
+
*/
|
|
2025
|
+
on<Subject extends Subjects & StrictNamespace, IsChannel = Subject['$meta']['channel']>(subject: IsChannel extends true ? never : Subject, handler: Subject extends SubjectDefinition ? HandlerForSubjectDefinition<Subject> : never, options?: OnOptions): () => void; /** Register an interceptor that runs BEFORE handlers (payload transform, blocking, priority). */
|
|
2026
|
+
intercept<Subject extends Subjects & StrictNamespace>(subject: Subject, handler: InterceptorHandler<Subject['$meta']['payload']>, options?: InterceptOptions): () => void;
|
|
2027
|
+
/**
|
|
2028
|
+
* Register a one-time event or request handler that auto-unsubscribes after first invocation.
|
|
2029
|
+
*
|
|
2030
|
+
* Wraps the `on()` method to automatically unsubscribe after the handler fires once.
|
|
2031
|
+
* The handler is removed BEFORE being invoked to prevent re-entrance issues if the
|
|
2032
|
+
* handler triggers the same event.
|
|
2033
|
+
*
|
|
2034
|
+
* **Events:** Fire-and-forget - handler executes once then auto-unsubscribes.
|
|
2035
|
+
* **Requests:** Request-response - handler executes once then auto-unsubscribes.
|
|
2036
|
+
*
|
|
2037
|
+
* **Wildcard Support:** Like `on()`, supports `.$all` property for namespace-level patterns.
|
|
2038
|
+
* @param subject - SubjectDefinition object (exact or wildcard)
|
|
2039
|
+
* @param handler - Handler function (EventHandler for events, RequestHandler for requests)
|
|
2040
|
+
* @returns Unsubscribe function for manual cleanup if needed
|
|
2041
|
+
* @example Basic one-time event handler
|
|
2042
|
+
* ```typescript
|
|
2043
|
+
* const { subjects: AgentSubjects } = MakaioBus.registerNamespace('agent', {
|
|
2044
|
+
* started: z.object({ agentId: z.string() }),
|
|
2045
|
+
* });
|
|
2046
|
+
*
|
|
2047
|
+
* once(AgentSubjects.started, (context) => {
|
|
2048
|
+
* context.payload.agentId; // ✅ string - fully typed
|
|
2049
|
+
* console.debug('Agent started once:', context.payload.agentId);
|
|
2050
|
+
* });
|
|
2051
|
+
*
|
|
2052
|
+
* await emit(AgentSubjects.started, { agentId: 'agent-123' }); // Handler fires
|
|
2053
|
+
* await emit(AgentSubjects.started, { agentId: 'agent-456' }); // Handler does NOT fire
|
|
2054
|
+
* ```
|
|
2055
|
+
* @example Manual unsubscribe before first fire
|
|
2056
|
+
* ```typescript
|
|
2057
|
+
* const unsubscribe = once(AgentSubjects.started, (context) => {
|
|
2058
|
+
* console.debug('This will never run');
|
|
2059
|
+
* });
|
|
2060
|
+
*
|
|
2061
|
+
* unsubscribe(); // Manually unsubscribe before event fires
|
|
2062
|
+
* await emit(AgentSubjects.started, { agentId: 'agent-123' }); // Handler does NOT fire
|
|
2063
|
+
* ```
|
|
2064
|
+
* @example Wildcard handler for one-time namespace monitoring
|
|
2065
|
+
* ```typescript
|
|
2066
|
+
* once(AgentSubjects.$all, (context) => {
|
|
2067
|
+
* context.payload; // unknown - must use type guards
|
|
2068
|
+
* console.debug('First agent event:', context.payload);
|
|
2069
|
+
* });
|
|
2070
|
+
* ```
|
|
2071
|
+
* @example One-time request handler
|
|
2072
|
+
* ```typescript
|
|
2073
|
+
* const { subjects: AgentSubjects } = MakaioBus.registerNamespace('agent', {
|
|
2074
|
+
* toolApprove: {
|
|
2075
|
+
* request: z.object({ toolName: z.string() }),
|
|
2076
|
+
* response: z.object({ approved: z.boolean() }),
|
|
2077
|
+
* },
|
|
2078
|
+
* });
|
|
2079
|
+
*
|
|
2080
|
+
* once(AgentSubjects.toolApprove, (context) => {
|
|
2081
|
+
* const { toolName } = context.payload; // ✅ fully typed
|
|
2082
|
+
* context.setResult({ approved: true });
|
|
2083
|
+
* });
|
|
2084
|
+
*
|
|
2085
|
+
* await request(AgentSubjects.toolApprove, { toolName: 'deleteFile' }); // Handler fires
|
|
2086
|
+
* await request(AgentSubjects.toolApprove, { toolName: 'createFile' }); // Handler does NOT fire
|
|
2087
|
+
* ```
|
|
2088
|
+
*/
|
|
2089
|
+
once<Subject extends Subjects & StrictNamespace, IsChannel = Subject['$meta']['channel']>(subject: IsChannel extends true ? never : Subject, handler: Subject extends SubjectDefinition ? HandlerForSubjectDefinition<Subject> : never): () => void;
|
|
2090
|
+
/**
|
|
2091
|
+
* Wait for an event to occur, returning a Promise.
|
|
2092
|
+
*
|
|
2093
|
+
* Note: Request subjects are not supported with the promise version of once().
|
|
2094
|
+
* Use the callback version for request handlers: `once(subject, handler)`
|
|
2095
|
+
* @param subject - Event SubjectDefinition object (exact or wildcard)
|
|
2096
|
+
* @param options - Options object with: timeoutMs (reject after timeout), filter (only resolve when filter returns true), signal (AbortSignal to cancel waiting)
|
|
2097
|
+
* @returns Promise that resolves with the event context
|
|
2098
|
+
* @example Simple await
|
|
2099
|
+
* ```typescript
|
|
2100
|
+
* const ctx = await bus.once(Subjects.init);
|
|
2101
|
+
* console.debug('Event received:', ctx.payload);
|
|
2102
|
+
* ```
|
|
2103
|
+
* @example With timeout
|
|
2104
|
+
* ```typescript
|
|
2105
|
+
* try {
|
|
2106
|
+
* const ctx = await bus.once(Subjects.init, { timeoutMs: 5000 });
|
|
2107
|
+
* } catch (err) {
|
|
2108
|
+
* if (err instanceof OnceTimeoutError) {
|
|
2109
|
+
* console.debug('Timed out waiting for event');
|
|
2110
|
+
* }
|
|
2111
|
+
* }
|
|
2112
|
+
* ```
|
|
2113
|
+
* @example With filter (waits for matching event)
|
|
2114
|
+
* ```typescript
|
|
2115
|
+
* const ctx = await bus.once(Subjects.message, {
|
|
2116
|
+
* filter: (payload) => payload.sessionId === expectedId
|
|
2117
|
+
* });
|
|
2118
|
+
* // Resolves only when a message with matching sessionId is received
|
|
2119
|
+
* ```
|
|
2120
|
+
* @example With AbortSignal
|
|
2121
|
+
* ```typescript
|
|
2122
|
+
* const controller = new AbortController();
|
|
2123
|
+
* const promise = bus.once(Subjects.init, { signal: controller.signal });
|
|
2124
|
+
* controller.abort(); // Cancels the wait
|
|
2125
|
+
* ```
|
|
2126
|
+
*/
|
|
2127
|
+
once<Subject extends Subjects & StrictNamespace, IsRequest = Subject['$meta']['isRequest'], IsChannel = Subject['$meta']['channel']>(subject: IsChannel extends true ? never : IsRequest extends false ? Subject : never, options?: Subject extends SubjectDefinition ? OnceOptions<Subject> : never): Promise<Subject extends SubjectDefinition ? Parameters<HandlerForSubjectDefinition<Subject>>[0] : never>;
|
|
2128
|
+
/**
|
|
2129
|
+
* Emit an event to all registered handlers.
|
|
2130
|
+
*
|
|
2131
|
+
* Events are fire-and-forget - all handlers execute in parallel.
|
|
2132
|
+
* Handler errors are logged but don't stop other handlers from executing.
|
|
2133
|
+
*
|
|
2134
|
+
* **Note:** You cannot emit to wildcard patterns. Use concrete subject keys only.
|
|
2135
|
+
* Handlers registered with wildcards will still receive the event if it matches.
|
|
2136
|
+
* @param subject - Concrete event subject (wildcards not allowed)
|
|
2137
|
+
* @param payload - Event payload
|
|
2138
|
+
* @param options - Emit options (messageId, correlationId, transports)
|
|
2139
|
+
*
|
|
2140
|
+
* ## Transport Routing
|
|
2141
|
+
* - `transports: undefined` - Send to ALL registered transports (default)
|
|
2142
|
+
* - `transports: []` - Local only, don't send to any transports
|
|
2143
|
+
* - `transports: ['ws', 'nats']` - Send only to specified transports
|
|
2144
|
+
* @example
|
|
2145
|
+
* ```typescript
|
|
2146
|
+
* const { subjects: AgentSubjects } = MakaioBus.registerNamespace('agent', {
|
|
2147
|
+
* started: z.object({ agentId: z.string() }),
|
|
2148
|
+
* });
|
|
2149
|
+
*
|
|
2150
|
+
* // Send to all transports (default)
|
|
2151
|
+
* await emit(AgentSubjects.started, { agentId: 'agent-123' });
|
|
2152
|
+
*
|
|
2153
|
+
* // Local only, no transports
|
|
2154
|
+
* await emit(
|
|
2155
|
+
* AgentSubjects.started,
|
|
2156
|
+
* { agentId: 'agent-123' },
|
|
2157
|
+
* { transports: [] }
|
|
2158
|
+
* );
|
|
2159
|
+
*
|
|
2160
|
+
* // Send to specific transports
|
|
2161
|
+
* await emit(
|
|
2162
|
+
* AgentSubjects.started,
|
|
2163
|
+
* { agentId: 'agent-123' },
|
|
2164
|
+
* { transports: ['websocket'] }
|
|
2165
|
+
* );
|
|
2166
|
+
*
|
|
2167
|
+
* // With tracking IDs:
|
|
2168
|
+
* await emit(
|
|
2169
|
+
* AgentSubjects.started,
|
|
2170
|
+
* { agentId: 'agent-123' },
|
|
2171
|
+
* { correlationId: 'user-action-123' }
|
|
2172
|
+
* );
|
|
2173
|
+
* ```
|
|
2174
|
+
*/
|
|
2175
|
+
emit<Subject extends Subjects & StrictNamespace, IsRequest = Subject['$meta']['isRequest'], IsWildcard = (Subject['subject'] extends WildcardSubject ? true : false), IsChannel = Subject['$meta']['channel']>(subject: IsChannel extends true ? never : IsRequest extends false ? IsWildcard extends false ? Subject : never : never, payload: Subject['$meta']['payload'], options?: EmitOptions): Promise<void>;
|
|
2176
|
+
/**
|
|
2177
|
+
* Execute a request and wait for a response.
|
|
2178
|
+
*
|
|
2179
|
+
* Requests follow a middleware chain pattern - handlers are called in order
|
|
2180
|
+
* until one calls setResult() or all handlers complete.
|
|
2181
|
+
*
|
|
2182
|
+
* **Note:** You cannot request via wildcard patterns. Use concrete subject keys only.
|
|
2183
|
+
* Handlers registered with wildcards will still match if the subject matches their pattern.
|
|
2184
|
+
* @param subject - Concrete request subject (wildcards not allowed)
|
|
2185
|
+
* @param payload - Request payload
|
|
2186
|
+
* @param options - Request options (timeout, correlationId, transports)
|
|
2187
|
+
* @returns Response value
|
|
2188
|
+
* @throws \{NoHandlerError\} If no handler is registered
|
|
2189
|
+
* @throws \{TimeoutError\} If request times out
|
|
2190
|
+
* @throws \{ValidationError\} If payload validation fails
|
|
2191
|
+
* @throws \{RequestError\} If handler throws an error
|
|
2192
|
+
*
|
|
2193
|
+
* ## Transport Routing
|
|
2194
|
+
* - `transports: undefined` - Send to ALL registered transports (default)
|
|
2195
|
+
* - `transports: []` - Local only, don't send to any transports
|
|
2196
|
+
* - `transports: ['ws', 'nats']` - Send only to specified transports
|
|
2197
|
+
* @example
|
|
2198
|
+
* ```typescript
|
|
2199
|
+
* // ✅ Concrete subject
|
|
2200
|
+
* const result = await request(
|
|
2201
|
+
* AgentSubjects.toolApprove,
|
|
2202
|
+
* { toolName: 'deleteFile', args: {}, toolCallId: 'call_123' },
|
|
2203
|
+
* { timeout: 10000 }
|
|
2204
|
+
* );
|
|
2205
|
+
* console.debug(result.approved);
|
|
2206
|
+
*
|
|
2207
|
+
* // ❌ Cannot use wildcards
|
|
2208
|
+
* // await request('agent.*', { ... }); // Type error
|
|
2209
|
+
*
|
|
2210
|
+
* // With specific transports
|
|
2211
|
+
* const result = await request(
|
|
2212
|
+
* AgentSubjects.toolApprove,
|
|
2213
|
+
* { toolName: 'deleteFile', args: {}, toolCallId: 'call_123' },
|
|
2214
|
+
* { transports: ['websocket'], timeout: 10000 }
|
|
2215
|
+
* );
|
|
2216
|
+
* ```
|
|
2217
|
+
*/
|
|
2218
|
+
request<Subject extends Subjects & StrictNamespace, IsRequest = Subject['$meta']['isRequest'], IsChannel = Subject['$meta']['channel']>(subject: IsChannel extends true ? never : IsRequest extends true ? Subject : never, payload: Subject['$meta']['payload']['request'], options?: RequestOptions): Promise<IsRequest extends true ? Subject['$meta']['payload']['response'] : never>;
|
|
2219
|
+
/**
|
|
2220
|
+
* Execute a request, returning a discriminated union instead of throwing for missing handlers.
|
|
2221
|
+
*
|
|
2222
|
+
* Use for optional services. Only NoHandlerError is caught - other errors propagate.
|
|
2223
|
+
* @see {@link OptionalResult} for return type details
|
|
2224
|
+
*/
|
|
2225
|
+
requestOptional<Subject extends Subjects & StrictNamespace, IsRequest = Subject['$meta']['isRequest'], IsChannel = Subject['$meta']['channel']>(subject: IsChannel extends true ? never : IsRequest extends true ? Subject : never, payload: Subject['$meta']['payload']['request'], options?: RequestOptions): Promise<OptionalResult<IsRequest extends true ? Subject['$meta']['payload']['response'] : never>>;
|
|
2226
|
+
/**
|
|
2227
|
+
* Execute a broadcast request and collect responses from ALL handlers.
|
|
2228
|
+
*
|
|
2229
|
+
* Unlike `request()` which uses a middleware chain and returns the first result,
|
|
2230
|
+
* `broadcast()` executes all handlers in parallel and aggregates their responses.
|
|
2231
|
+
*
|
|
2232
|
+
* Use for discovery patterns where multiple nodes may respond (e.g., fs.listSources).
|
|
2233
|
+
*
|
|
2234
|
+
* **Note:** You cannot broadcast via wildcard patterns. Use concrete subject keys only.
|
|
2235
|
+
* Handlers registered with wildcards will still match if the subject matches their pattern.
|
|
2236
|
+
*
|
|
2237
|
+
* **Handler Usage:**
|
|
2238
|
+
* Handlers should call `ctx.identify(nodeId)` before `ctx.setResult()` to tag their response.
|
|
2239
|
+
* If `identify()` is not called, the response is tagged as 'anonymous'.
|
|
2240
|
+
* @param subject - Concrete request subject (wildcards not allowed)
|
|
2241
|
+
* @param payload - Request payload
|
|
2242
|
+
* @param options - Request options (timeout, correlationId)
|
|
2243
|
+
* @returns Array of \{ nodeId, payload \} responses from all handlers
|
|
2244
|
+
* @example
|
|
2245
|
+
* ```typescript
|
|
2246
|
+
* // Discover all filesystem sources from all nodes
|
|
2247
|
+
* const results = await MakaioBus.broadcast(FileSystemSubjects.listSources, \{\});
|
|
2248
|
+
* // results: [
|
|
2249
|
+
* // \{ nodeId: 'local', payload: \{ sources: [...] \} \},
|
|
2250
|
+
* // \{ nodeId: 'container-1', payload: \{ sources: [...] \} \},
|
|
2251
|
+
* // ]
|
|
2252
|
+
*
|
|
2253
|
+
* // Aggregate sources
|
|
2254
|
+
* const allSources = results.flatMap(r => r.payload.sources);
|
|
2255
|
+
* ```
|
|
2256
|
+
*/
|
|
2257
|
+
broadcast<Subject extends Subjects & StrictNamespace, IsRequest = Subject['$meta']['isRequest'], IsChannel = Subject['$meta']['channel']>(subject: IsChannel extends true ? never : IsRequest extends true ? Subject : never, payload: Subject['$meta']['payload']['request'], options?: RequestOptions): Promise<BroadcastResult<IsRequest extends true ? Subject['$meta']['payload']['response'] : never>[]>;
|
|
2258
|
+
scoped: <Domain extends string, Subjects extends SubjectRecord, F, Sc extends Record<string, SubjectSchema>>(input: BusNamespace<Domain, Subjects, F, Sc>, context?: MakaioBusContext) => ScopedBus<Domain>;
|
|
2259
|
+
/**
|
|
2260
|
+
* Create a filtered bus with a base payload filter.
|
|
2261
|
+
*
|
|
2262
|
+
* The filter is automatically applied to all `on()` and `once()` calls.
|
|
2263
|
+
*
|
|
2264
|
+
* Optionally provide a type parameter for type-safe filter keys.
|
|
2265
|
+
* @param filter - Base filter to apply to all subscriptions
|
|
2266
|
+
* @returns FilteredBus with the specified filter
|
|
2267
|
+
* @example
|
|
2268
|
+
* ```typescript
|
|
2269
|
+
* // Untyped (loose) - any keys allowed
|
|
2270
|
+
* const agentBus = MakaioBus.withFilter({ agentId: this.agentId });
|
|
2271
|
+
*
|
|
2272
|
+
* // Type-safe filter keys
|
|
2273
|
+
* interface AgentPayload { agentId: string; sessionId: string }
|
|
2274
|
+
* const strictBus = MakaioBus.withFilter<AgentPayload>({ agentId: 'x' });
|
|
2275
|
+
* ```
|
|
2276
|
+
*/
|
|
2277
|
+
withFilter: <Payload = unknown>(filter: [unknown] extends [Payload] ? PayloadFilter : TypedPayloadFilter<Payload>) => IFilteredBus<NamespaceDomain extends string ? NamespaceDomain : string>;
|
|
2278
|
+
/**
|
|
2279
|
+
* Register a handler that receives ALL messages (events and requests) across all namespaces.
|
|
2280
|
+
*
|
|
2281
|
+
* **Debugging/Testing Only:** Noops in production (process.env.NODE_ENV === 'production').
|
|
2282
|
+
* Useful for logging, debugging, and test assertions that need visibility into all bus activity.
|
|
2283
|
+
*
|
|
2284
|
+
* Handler receives complete metadata: type, subject, namespace, payload, messageId, correlationId.
|
|
2285
|
+
* @param handler - Function to invoke for every message
|
|
2286
|
+
* @returns Unsubscribe function (noop in production)
|
|
2287
|
+
* @example
|
|
2288
|
+
* ```typescript
|
|
2289
|
+
* const unsubscribe = bus.__onAny((context) => {
|
|
2290
|
+
* console.debug(`[${context.type}] ${context.namespace}:${context.subject}`, context.payload);
|
|
2291
|
+
* });
|
|
2292
|
+
* ```
|
|
2293
|
+
*/
|
|
2294
|
+
__onAny: (handler: AnyHandler) => () => void;
|
|
2295
|
+
__resetHandlers?: () => void;
|
|
2296
|
+
/**
|
|
2297
|
+
* Register a transport by its name property.
|
|
2298
|
+
*
|
|
2299
|
+
* Convenience method that delegates to `getContext().transportRegistry.registerTransport()`.
|
|
2300
|
+
* The transport's `name` property is used as the registry key.
|
|
2301
|
+
* @param transport - Transport to register
|
|
2302
|
+
* @returns Registration object with `unregister` and `ready` promise
|
|
2303
|
+
*/
|
|
2304
|
+
registerTransport(transport: BusTransport): TransportRegistration;
|
|
2305
|
+
/**
|
|
2306
|
+
* Unregister a transport by name.
|
|
2307
|
+
*
|
|
2308
|
+
* No-op if no transport is registered under that name.
|
|
2309
|
+
* @param name - Transport name to unregister
|
|
2310
|
+
*/
|
|
2311
|
+
unregisterTransport(name: string): void;
|
|
2312
|
+
/**
|
|
2313
|
+
* Disconnect all registered transports and clear the transport map.
|
|
2314
|
+
*
|
|
2315
|
+
* Convenience method for tearing down a bus instance. The inverse of
|
|
2316
|
+
* passing `transports` to `createBusInstance()` or calling
|
|
2317
|
+
* `registerTransport()` individually.
|
|
2318
|
+
*/
|
|
2319
|
+
disconnect(): void;
|
|
2320
|
+
/**
|
|
2321
|
+
* Trigger an immediate reconnection attempt on all disconnected transports.
|
|
2322
|
+
*
|
|
2323
|
+
* Delegates to each transport's `reconnect()` method if available. For
|
|
2324
|
+
* transports with exponential-backoff reconnection (e.g. WebSocket), this
|
|
2325
|
+
* wakes the backoff sleep and returns once the attempt is *initiated* — not
|
|
2326
|
+
* once the connection is established. For one-shot transports it resolves
|
|
2327
|
+
* after the connect attempt completes. Failures are logged but do not reject
|
|
2328
|
+
* this promise. No-op when all transports are already connected.
|
|
2329
|
+
*/
|
|
2330
|
+
reconnect(): Promise<void>;
|
|
2331
|
+
/**
|
|
2332
|
+
* Resolves when all transports registered at connect-time have completed
|
|
2333
|
+
* subscribe-sync. If {@link connect} was called with the default `awaitReady: true`,
|
|
2334
|
+
* this is already resolved when `connect()` returns. If `awaitReady: false` was used,
|
|
2335
|
+
* await this to ensure readiness before dispatching requests.
|
|
2336
|
+
*
|
|
2337
|
+
* Resolves immediately if no transports are registered or `connect()` has not been called.
|
|
2338
|
+
*/
|
|
2339
|
+
readonly ready: Promise<void>;
|
|
2340
|
+
/**
|
|
2341
|
+
* Connect all registered transports and optionally await subscribe-sync readiness.
|
|
2342
|
+
*
|
|
2343
|
+
* Calls `transport.connect()` on every transport registered by this bus instance.
|
|
2344
|
+
* If any transport fails to connect, all transports are disconnected and unregistered
|
|
2345
|
+
* (rollback) before the error is re-thrown. Pass `{ awaitReady: false }` to resolve
|
|
2346
|
+
* as soon as sockets are open without waiting for the subscribe-sync handshake.
|
|
2347
|
+
* Concurrent calls are safe — a second in-flight call awaits the same promise. Once
|
|
2348
|
+
* sockets are open, subsequent calls are no-ops unless a prior
|
|
2349
|
+
* `connect({ awaitReady: false })` left the readiness handshake pending; in that case,
|
|
2350
|
+
* default `connect()` still awaits `bus.ready`.
|
|
2351
|
+
* @param options - Connection options (see {@link ConnectOptions})
|
|
2352
|
+
* @throws If any transport's `connect()` or `ready` promise rejects (after rollback)
|
|
2353
|
+
*/
|
|
2354
|
+
connect(options?: ConnectOptions): Promise<void>;
|
|
2355
|
+
getContext(): MakaioBusContext;
|
|
2356
|
+
/**
|
|
2357
|
+
* Register a namespace from a `BusNamespaceDefinition` created by `createBusNamespace()`.
|
|
2358
|
+
*
|
|
2359
|
+
* Returns a `BusNamespace` that extends the definition with a `scopedBus()` method.
|
|
2360
|
+
* @param definition - Namespace definition created by `createBusNamespace()` from `@makaio/core`
|
|
2361
|
+
* @returns Registered namespace with `scopedBus()` and pre-computed FilterPayload type
|
|
2362
|
+
*/
|
|
2363
|
+
registerNamespace<Domain extends string, Schemas extends Record<string, SubjectSchema>>(definition: BusNamespaceDefinition<Domain, Schemas>): BusNamespace<Domain, SubjectRecordFromSchemaRecord<Schemas>, FilterablePayloadIntersection<SubjectRecordFromSchemaRecord<Schemas>>, Schemas>;
|
|
2364
|
+
/**
|
|
2365
|
+
* Register multiple namespaces in a single call.
|
|
2366
|
+
*
|
|
2367
|
+
* Convenience wrapper for composition roots that register a catalog of namespaces at boot:
|
|
2368
|
+
* ```typescript
|
|
2369
|
+
* MakaioBus.registerNamespaces(FrameworkContractNamespaces);
|
|
2370
|
+
* ```
|
|
2371
|
+
* @param definitions - Array of namespace definitions to register
|
|
2372
|
+
*/
|
|
2373
|
+
registerNamespaces(definitions: readonly RegistrableBusNamespaceDefinition[]): void; /** Get the schema for a registered subject, or undefined if not found. */
|
|
2374
|
+
getSchema<T extends SubjectDefinition>(subject: T | string): SubjectSchema | undefined;
|
|
2375
|
+
/**
|
|
2376
|
+
* Extend a registered subject's schema with additional fields.
|
|
2377
|
+
*
|
|
2378
|
+
* Adds new root-level fields to the Zod schema used for dev-mode validation and
|
|
2379
|
+
* widens the TypeScript payload type. Successive calls accumulate — two packages
|
|
2380
|
+
* can independently extend the same subject without overwriting each other.
|
|
2381
|
+
*
|
|
2382
|
+
* The returned value is the same runtime SubjectDefinition object — only the
|
|
2383
|
+
* TypeScript type is widened. Bus routing is unaffected.
|
|
2384
|
+
* @param subject - SubjectDefinition from a registered namespace
|
|
2385
|
+
* @param extensions - For request subjects: `{ request?: { field: z.string() }, response?: {...} }`.
|
|
2386
|
+
* For event subjects: `{ field: z.string() }` (flat record of additional Zod fields).
|
|
2387
|
+
* @returns The same SubjectDefinition with wider TypeScript types
|
|
2388
|
+
*/
|
|
2389
|
+
extendSubject<SD extends Subjects & StrictNamespace, Ext extends SubjectExtension<SD>>(subject: SD, extensions: Ext): ExtendedSubjectDefinition<SD, Ext>;
|
|
2390
|
+
};
|
|
2391
|
+
//#endregion
|
|
2392
|
+
//#region packages/bus-core/src/utils/transport.d.ts
|
|
2393
|
+
/**
|
|
2394
|
+
* Detects a "no handler" error for a specific request subject.
|
|
2395
|
+
*
|
|
2396
|
+
* Works for both in-process {@link NoHandlerError} instances and deserialized
|
|
2397
|
+
* errors that carry a `code` + `subject` after a transport round-trip.
|
|
2398
|
+
* The `subject` field is preserved by transport error serialization, so no
|
|
2399
|
+
* fragile message-string matching is needed.
|
|
2400
|
+
* @param error - Error from a relayed request or transport response
|
|
2401
|
+
* @param fullSubject - Full request subject key (namespace.subject)
|
|
2402
|
+
* @returns True when the error indicates no local handler for this subject
|
|
2403
|
+
*/
|
|
2404
|
+
declare function isNoHandlerErrorForSubject(error: unknown, fullSubject: string): boolean;
|
|
2405
|
+
/**
|
|
2406
|
+
* Extracts the full subject key from a bus message.
|
|
2407
|
+
*
|
|
2408
|
+
* Combines the namespace and subject into the full subject key format
|
|
2409
|
+
* (namespace.subject) used for handler lookups and subscription matching.
|
|
2410
|
+
* Returns null if the message doesn't contain the required fields.
|
|
2411
|
+
* @param message - Bus message (event or request)
|
|
2412
|
+
* @returns Full subject key in format "namespace.subject", or null if fields are missing
|
|
2413
|
+
* @example
|
|
2414
|
+
* ```typescript
|
|
2415
|
+
* const message: BusMessage = {
|
|
2416
|
+
* type: 'event',
|
|
2417
|
+
* subject: 'log',
|
|
2418
|
+
* namespace: 'adapter',
|
|
2419
|
+
* payload: { message: 'Hello' },
|
|
2420
|
+
* messageId: 'msg-123',
|
|
2421
|
+
* };
|
|
2422
|
+
*
|
|
2423
|
+
* const fullSubject = getSubjectFromBusMessage(message);
|
|
2424
|
+
* // Returns: "adapter.log"
|
|
2425
|
+
* ```
|
|
2426
|
+
*/
|
|
2427
|
+
declare function getSubjectFromBusMessage(message: BusMessage): string | null;
|
|
2428
|
+
/**
|
|
2429
|
+
* Reconstruct an Error from a structured transport error payload.
|
|
2430
|
+
*
|
|
2431
|
+
* Preserves `code` and arbitrary `data` properties so callers can
|
|
2432
|
+
* inspect them for programmatic error handling.
|
|
2433
|
+
* @param transportError - The structured error received over the wire
|
|
2434
|
+
* @returns An Error with `code` and data properties attached
|
|
2435
|
+
*/
|
|
2436
|
+
declare function deserializeTransportError(transportError: BusTransportError): Error;
|
|
2437
|
+
//#endregion
|
|
2438
|
+
//#region packages/bus-core/src/utils/payload-filter.d.ts
|
|
2439
|
+
/**
|
|
2440
|
+
* Get a nested value from an object using dot-notation path.
|
|
2441
|
+
* @param obj - Object to traverse
|
|
2442
|
+
* @param path - Dot-notation path (e.g., 'raw.msg.type')
|
|
2443
|
+
* @returns Value at path, or undefined if not found
|
|
2444
|
+
* @example
|
|
2445
|
+
* ```typescript
|
|
2446
|
+
* const obj = { raw: { msg: { type: 'event' } } };
|
|
2447
|
+
* getPath(obj, 'raw.msg.type'); // 'event'
|
|
2448
|
+
* getPath(obj, 'raw.missing'); // undefined
|
|
2449
|
+
* ```
|
|
2450
|
+
*/
|
|
2451
|
+
declare function getPath(obj: unknown, path: string): unknown;
|
|
2452
|
+
/**
|
|
2453
|
+
* Check if a payload matches all filter conditions.
|
|
2454
|
+
*
|
|
2455
|
+
* All conditions are ANDed together - all must match for the filter to pass.
|
|
2456
|
+
* @param payload - Message payload to check
|
|
2457
|
+
* @param filter - Filter specification with field paths and operators
|
|
2458
|
+
* @returns true if payload matches all filter conditions
|
|
2459
|
+
* @example
|
|
2460
|
+
* ```typescript
|
|
2461
|
+
* const payload = {
|
|
2462
|
+
* agentId: 'agent-123',
|
|
2463
|
+
* raw: { msg: { type: 'session_configured' } },
|
|
2464
|
+
* status: 'active',
|
|
2465
|
+
* };
|
|
2466
|
+
*
|
|
2467
|
+
* // All conditions must match
|
|
2468
|
+
* matchesFilter(payload, {
|
|
2469
|
+
* agentId: 'agent-123',
|
|
2470
|
+
* 'raw.msg.type': 'session_configured',
|
|
2471
|
+
* }); // true
|
|
2472
|
+
*
|
|
2473
|
+
* // With operators
|
|
2474
|
+
* matchesFilter(payload, {
|
|
2475
|
+
* status: { $in: ['active', 'pending'] },
|
|
2476
|
+
* }); // true
|
|
2477
|
+
*
|
|
2478
|
+
* matchesFilter(payload, {
|
|
2479
|
+
* error: { $exists: false },
|
|
2480
|
+
* }); // true (no error field)
|
|
2481
|
+
* ```
|
|
2482
|
+
*/
|
|
2483
|
+
declare function matchesFilter(payload: unknown, filter: PayloadFilter): boolean;
|
|
2484
|
+
/**
|
|
2485
|
+
* Merge two payload filters together.
|
|
2486
|
+
*
|
|
2487
|
+
* Later filter values override earlier ones for the same path.
|
|
2488
|
+
* @param base - Base filter
|
|
2489
|
+
* @param override - Filter to merge in (overrides base)
|
|
2490
|
+
* @returns Merged filter
|
|
2491
|
+
*/
|
|
2492
|
+
declare function mergeFilters(base: PayloadFilter | undefined, override: PayloadFilter | undefined): PayloadFilter | undefined;
|
|
2493
|
+
//#endregion
|
|
2494
|
+
//#region packages/bus-core/src/utils/url-config.d.ts
|
|
2495
|
+
/**
|
|
2496
|
+
* Bus URL configuration utilities.
|
|
2497
|
+
*
|
|
2498
|
+
* Provides consistent parsing of bus URL environment variables across
|
|
2499
|
+
* all consumers (Electron, Vite configs, etc.) with correct handling of:
|
|
2500
|
+
*
|
|
2501
|
+
* - Default localhost development URLs (explicit port 6252)
|
|
2502
|
+
* - User-provided production URLs (preserve protocol defaults like wss:// to 443)
|
|
2503
|
+
*/
|
|
2504
|
+
/**
|
|
2505
|
+
* Parsed bus URL configuration.
|
|
2506
|
+
*/
|
|
2507
|
+
interface BusUrlConfig {
|
|
2508
|
+
/**
|
|
2509
|
+
* The full URL href for client connections.
|
|
2510
|
+
* For default localhost, includes explicit port.
|
|
2511
|
+
* For user-provided URLs, preserves original (protocol defaults intact).
|
|
2512
|
+
*/
|
|
2513
|
+
href: string;
|
|
2514
|
+
/**
|
|
2515
|
+
* The port number for server binding.
|
|
2516
|
+
* - For default localhost: 6252
|
|
2517
|
+
* - For user-provided URLs with explicit port: that port
|
|
2518
|
+
* - For user-provided URLs without port: undefined (use protocol default)
|
|
2519
|
+
*/
|
|
2520
|
+
port: number | undefined;
|
|
2521
|
+
/**
|
|
2522
|
+
* Whether this is the default localhost URL (no env var set).
|
|
2523
|
+
*/
|
|
2524
|
+
isDefault: boolean;
|
|
2525
|
+
}
|
|
2526
|
+
/**
|
|
2527
|
+
* Parses the bus URL from environment variable with correct default handling.
|
|
2528
|
+
*
|
|
2529
|
+
* Key behaviors:
|
|
2530
|
+
* - No env var: Returns default `ws://localhost:6252/bus` with explicit port 6252
|
|
2531
|
+
* - Env var with explicit port: Uses that port
|
|
2532
|
+
* - Env var without port (e.g., `wss://bus.example.com/bus`): Preserves URL as-is,
|
|
2533
|
+
* returns `port: undefined` so protocol defaults (443 for wss://) are respected
|
|
2534
|
+
* @param envValue - The value of MAKAIO_BUS_URL environment variable (or undefined)
|
|
2535
|
+
* @returns Parsed configuration with href, port, and isDefault flag
|
|
2536
|
+
* @example
|
|
2537
|
+
* ```typescript
|
|
2538
|
+
* // No env var - local development
|
|
2539
|
+
* const config = parseBusUrl(undefined);
|
|
2540
|
+
* // { href: 'ws://localhost:6252/bus', port: 6252, isDefault: true }
|
|
2541
|
+
*
|
|
2542
|
+
* // Production with explicit port
|
|
2543
|
+
* const config = parseBusUrl('wss://bus.example.com:9000/bus');
|
|
2544
|
+
* // { href: 'wss://bus.example.com:9000/bus', port: 9000, isDefault: false }
|
|
2545
|
+
*
|
|
2546
|
+
* // Production with protocol default port
|
|
2547
|
+
* const config = parseBusUrl('wss://bus.example.com/bus');
|
|
2548
|
+
* // { href: 'wss://bus.example.com/bus', port: undefined, isDefault: false }
|
|
2549
|
+
* ```
|
|
2550
|
+
*/
|
|
2551
|
+
declare function parseBusUrl(envValue: string | undefined): BusUrlConfig;
|
|
2552
|
+
//#endregion
|
|
2553
|
+
//#region packages/bus-core/src/utils/subscription-matching.d.ts
|
|
2554
|
+
/**
|
|
2555
|
+
* Subscription pattern matching utilities.
|
|
2556
|
+
*
|
|
2557
|
+
* Supports exact matches, subject wildcards (e.g., 'adapter.*'),
|
|
2558
|
+
* and namespace wildcards (e.g., 'adapter:*').
|
|
2559
|
+
*
|
|
2560
|
+
* ## Pattern Matching Decision Tree
|
|
2561
|
+
*
|
|
2562
|
+
* ```
|
|
2563
|
+
* Pattern ends with...?
|
|
2564
|
+
* │
|
|
2565
|
+
* ├─ No asterisk (e.g., 'adapter.log')
|
|
2566
|
+
* │ └─ Exact match: subject === pattern
|
|
2567
|
+
* │
|
|
2568
|
+
* ├─ ':*' (e.g., 'adapter:*', 'adapter:claudeCode:*')
|
|
2569
|
+
* │ └─ Namespace wildcard: matches child namespace subjects
|
|
2570
|
+
* │ • 'adapter:*' matches 'adapter:claudeCode.log'
|
|
2571
|
+
* │ • 'adapter:*' matches 'adapter:claudeCode:sdk.thinking'
|
|
2572
|
+
* │ • 'adapter:*' does NOT match 'adapter.log' (no child namespace)
|
|
2573
|
+
* │
|
|
2574
|
+
* └─ '.*' (e.g., 'adapter.*', 'adapter:claudeCode.*')
|
|
2575
|
+
* └─ Subject wildcard: matches subjects in specific namespace
|
|
2576
|
+
* • 'adapter.*' matches 'adapter.log', 'adapter.error'
|
|
2577
|
+
* • 'adapter.*' does NOT match 'adapter:claudeCode.log'
|
|
2578
|
+
* • 'adapter:claudeCode.*' matches 'adapter:claudeCode.log'
|
|
2579
|
+
* ```
|
|
2580
|
+
*
|
|
2581
|
+
* ## Colon vs Dot Semantics
|
|
2582
|
+
*
|
|
2583
|
+
* - **Colon (`:`)** = namespace hierarchy boundary
|
|
2584
|
+
* - `adapter:claudeCode` is a child namespace of `adapter`
|
|
2585
|
+
* - Wildcard `:*` crosses this boundary
|
|
2586
|
+
*
|
|
2587
|
+
* - **Dot (`.`)** = subject separator within namespace
|
|
2588
|
+
* - `adapter.log` is a subject in the `adapter` namespace
|
|
2589
|
+
* - Wildcard `.*` enumerates subjects, doesn't cross namespace boundaries
|
|
2590
|
+
*/
|
|
2591
|
+
/**
|
|
2592
|
+
* Check if a subject matches a subscription pattern.
|
|
2593
|
+
*
|
|
2594
|
+
* Patterns can be:
|
|
2595
|
+
* - Exact match: 'adapter:claudeCode.log' matches only 'adapter:claudeCode.log'
|
|
2596
|
+
* - Subject wildcard: 'adapter:claudeCode.*' matches 'adapter:claudeCode.log', 'adapter:claudeCode.initialized'
|
|
2597
|
+
* - Namespace wildcard: 'adapter:*' matches subjects from child namespaces
|
|
2598
|
+
* @param subject - Subject to match (e.g., 'adapter:claudeCode:sdk.thinking')
|
|
2599
|
+
* @param pattern - Subscription pattern (e.g., 'adapter:*', 'adapter:claudeCode.*', 'adapter:claudeCode.log')
|
|
2600
|
+
* @returns true if subject matches pattern
|
|
2601
|
+
* @example
|
|
2602
|
+
* ```typescript
|
|
2603
|
+
* // Exact match
|
|
2604
|
+
* matchesSubscription('adapter.log', 'adapter.log')
|
|
2605
|
+
* // → true
|
|
2606
|
+
*
|
|
2607
|
+
* // Subject wildcard - matches subjects in namespace
|
|
2608
|
+
* matchesSubscription('adapter.log', 'adapter.*')
|
|
2609
|
+
* // → true
|
|
2610
|
+
* matchesSubscription('adapter.initialized', 'adapter.*')
|
|
2611
|
+
* // → true
|
|
2612
|
+
* matchesSubscription('adapter:claudeCode.log', 'adapter.*')
|
|
2613
|
+
* // → false (different namespace - adapter:claudeCode vs adapter)
|
|
2614
|
+
*
|
|
2615
|
+
* // Namespace wildcard - matches child namespaces
|
|
2616
|
+
* matchesSubscription('adapter:claudeCode.initialized', 'adapter:*')
|
|
2617
|
+
* // → true (claudeCode is child of adapter)
|
|
2618
|
+
* matchesSubscription('adapter:claudeCode:sdk.thinking', 'adapter:*')
|
|
2619
|
+
* // → true (sdk is descendant of adapter)
|
|
2620
|
+
* matchesSubscription('adapter:gpt.initialized', 'adapter:*')
|
|
2621
|
+
* // → true (gpt is child of adapter)
|
|
2622
|
+
*
|
|
2623
|
+
* // Multi-level namespace wildcard
|
|
2624
|
+
* matchesSubscription('adapter:claudeCode:sdk.thinking', 'adapter:claudeCode:*')
|
|
2625
|
+
* // → true (sdk is child of adapter:claudeCode)
|
|
2626
|
+
* matchesSubscription('adapter:gpt.initialized', 'adapter:claudeCode:*')
|
|
2627
|
+
* // → false (different branch)
|
|
2628
|
+
* ```
|
|
2629
|
+
*/
|
|
2630
|
+
declare function matchesSubscription(subject: string, pattern: string): boolean;
|
|
2631
|
+
/**
|
|
2632
|
+
* Check if a subject matches any pattern in a collection.
|
|
2633
|
+
* @param subject - Subject to match
|
|
2634
|
+
* @param patterns - Collection of subscription patterns
|
|
2635
|
+
* @returns true if subject matches at least one pattern
|
|
2636
|
+
* @example
|
|
2637
|
+
* ```typescript
|
|
2638
|
+
* matchesAnySubscription('adapter.log', new Set(['adapter.*', 'agent.*']))
|
|
2639
|
+
* // → true (matches 'adapter.*')
|
|
2640
|
+
*
|
|
2641
|
+
* matchesAnySubscription('adapter:claudeCode.initialized', new Set(['adapter:*']))
|
|
2642
|
+
* // → true (matches 'adapter:*')
|
|
2643
|
+
*
|
|
2644
|
+
* matchesAnySubscription('session.started', new Set(['adapter.*', 'adapter:*']))
|
|
2645
|
+
* // → false (no match)
|
|
2646
|
+
*
|
|
2647
|
+
* matchesAnySubscription('adapter.log', new Set())
|
|
2648
|
+
* // → false (empty patterns)
|
|
2649
|
+
* ```
|
|
2650
|
+
*/
|
|
2651
|
+
declare function matchesAnySubscription(subject: string, patterns: Iterable<string>): boolean;
|
|
2652
|
+
//#endregion
|
|
2653
|
+
//#region packages/bus-core/src/errors/bus-error.d.ts
|
|
2654
|
+
/**
|
|
2655
|
+
* Base error class for all bus-related errors.
|
|
2656
|
+
*/
|
|
2657
|
+
declare class BusError extends MakaioError {
|
|
2658
|
+
readonly subject?: string | undefined;
|
|
2659
|
+
/**
|
|
2660
|
+
* @param message - Human-readable error description
|
|
2661
|
+
* @param subject - Fully-qualified subject name (namespace.subject) for the failed operation
|
|
2662
|
+
*/
|
|
2663
|
+
constructor(message: string, subject?: string | undefined);
|
|
2664
|
+
}
|
|
2665
|
+
//#endregion
|
|
2666
|
+
//#region packages/bus-core/src/errors/channel-auth-error.d.ts
|
|
2667
|
+
/**
|
|
2668
|
+
* Thrown when channel authentication fails during the handshake.
|
|
2669
|
+
* Indicates the provided token does not match the endpoint's expected token.
|
|
2670
|
+
*/
|
|
2671
|
+
declare class ChannelAuthError extends BusError {
|
|
2672
|
+
/**
|
|
2673
|
+
* @param endpoint - The endpoint name that failed authentication
|
|
2674
|
+
*/
|
|
2675
|
+
constructor(endpoint: string);
|
|
2676
|
+
}
|
|
2677
|
+
//#endregion
|
|
2678
|
+
//#region packages/bus-core/src/errors/channel-closed-error.d.ts
|
|
2679
|
+
/**
|
|
2680
|
+
* Thrown when an operation is attempted on a closed DirectChannel.
|
|
2681
|
+
* All pending requests are rejected with this error when a channel closes.
|
|
2682
|
+
*/
|
|
2683
|
+
declare class ChannelClosedError extends BusError {
|
|
2684
|
+
/**
|
|
2685
|
+
* @param channelId - The identifier of the channel that is closed
|
|
2686
|
+
*/
|
|
2687
|
+
constructor(channelId: string);
|
|
2688
|
+
}
|
|
2689
|
+
//#endregion
|
|
2690
|
+
//#region packages/bus-core/src/errors/channel-only-error.d.ts
|
|
2691
|
+
/**
|
|
2692
|
+
* Thrown when a channel-only subject is used directly on the public bus.
|
|
2693
|
+
* Channel subjects must be routed through a DirectChannel, not the public bus API.
|
|
2694
|
+
*/
|
|
2695
|
+
declare class ChannelOnlyError extends BusError {
|
|
2696
|
+
/**
|
|
2697
|
+
* @param subject - The channel-only subject that was used on the public bus
|
|
2698
|
+
*/
|
|
2699
|
+
constructor(subject: string);
|
|
2700
|
+
}
|
|
2701
|
+
//#endregion
|
|
2702
|
+
//#region packages/bus-core/src/errors/local-subject-error.d.ts
|
|
2703
|
+
/**
|
|
2704
|
+
* Thrown when a remote peer attempts to invoke a local-only subject over a
|
|
2705
|
+
* transport. Local subjects are never serializable and must not be routed
|
|
2706
|
+
* across process or network boundaries.
|
|
2707
|
+
*/
|
|
2708
|
+
declare class LocalSubjectError extends BusError {
|
|
2709
|
+
/**
|
|
2710
|
+
* @param subject - The local-only subject that was invoked remotely
|
|
2711
|
+
*/
|
|
2712
|
+
constructor(subject: string);
|
|
2713
|
+
}
|
|
2714
|
+
//#endregion
|
|
2715
|
+
//#region packages/bus-core/src/errors/no-handler-error.d.ts
|
|
2716
|
+
/**
|
|
2717
|
+
* Stable error code for "no handler registered" failures.
|
|
2718
|
+
*/
|
|
2719
|
+
declare const NO_HANDLER_ERROR_CODE: "NO_HANDLER";
|
|
2720
|
+
/**
|
|
2721
|
+
* Error thrown when no handler is registered for a request.
|
|
2722
|
+
*/
|
|
2723
|
+
declare class NoHandlerError extends BusError {
|
|
2724
|
+
readonly code: "NO_HANDLER";
|
|
2725
|
+
/**
|
|
2726
|
+
* @param subject - Fully-qualified subject name for which no handler was found
|
|
2727
|
+
*/
|
|
2728
|
+
constructor(subject: string);
|
|
2729
|
+
}
|
|
2730
|
+
//#endregion
|
|
2731
|
+
//#region packages/bus-core/src/errors/request-error.d.ts
|
|
2732
|
+
/**
|
|
2733
|
+
* Generic error thrown when a request fails for any other reason.
|
|
2734
|
+
*/
|
|
2735
|
+
declare class RequestError extends BusError {
|
|
2736
|
+
readonly cause?: Error | undefined;
|
|
2737
|
+
/**
|
|
2738
|
+
* @param subject - Fully-qualified subject name for the failed request
|
|
2739
|
+
* @param message - Human-readable description of the failure
|
|
2740
|
+
* @param cause - Underlying error thrown by the handler, if any
|
|
2741
|
+
*/
|
|
2742
|
+
constructor(subject: string, message: string, cause?: Error | undefined);
|
|
2743
|
+
}
|
|
2744
|
+
//#endregion
|
|
2745
|
+
//#region packages/bus-core/src/errors/timeout-error.d.ts
|
|
2746
|
+
/**
|
|
2747
|
+
* Error thrown when a request times out.
|
|
2748
|
+
*/
|
|
2749
|
+
declare class TimeoutError extends BusError {
|
|
2750
|
+
readonly timeoutMs: number;
|
|
2751
|
+
/**
|
|
2752
|
+
* @param subject - Fully-qualified subject name for the timed-out request
|
|
2753
|
+
* @param timeoutMs - Timeout duration in milliseconds that was exceeded
|
|
2754
|
+
*/
|
|
2755
|
+
constructor(subject: string, timeoutMs: number);
|
|
2756
|
+
}
|
|
2757
|
+
//#endregion
|
|
2758
|
+
//#region packages/bus-core/src/errors/validation-error.d.ts
|
|
2759
|
+
/**
|
|
2760
|
+
* Error thrown when payload validation fails.
|
|
2761
|
+
*/
|
|
2762
|
+
declare class ValidationError extends BusError {
|
|
2763
|
+
readonly zodError: z.ZodError;
|
|
2764
|
+
/**
|
|
2765
|
+
* @param subject - Fully-qualified subject name for which validation failed
|
|
2766
|
+
* @param zodError - Zod validation error containing the individual issue details
|
|
2767
|
+
*/
|
|
2768
|
+
constructor(subject: string, zodError: z.ZodError);
|
|
2769
|
+
}
|
|
2770
|
+
//#endregion
|
|
2771
|
+
//#region packages/bus-core/src/bus.d.ts
|
|
2772
|
+
/**
|
|
2773
|
+
* Creates a new bus context containing handler registries and shared state.
|
|
2774
|
+
*
|
|
2775
|
+
* Used internally by createBusInstance to manage event and request handlers.
|
|
2776
|
+
* Can be used to create isolated bus instances (e.g., for testing) by providing
|
|
2777
|
+
* separate handler maps per instance.
|
|
2778
|
+
* @returns A new MakaioBusContext instance with empty handler registries
|
|
2779
|
+
*/
|
|
2780
|
+
declare const createBusContext: () => MakaioBusContext;
|
|
2781
|
+
/**
|
|
2782
|
+
* Options for creating a bus instance.
|
|
2783
|
+
*/
|
|
2784
|
+
interface CreateBusOptions<Namespace extends string | undefined = undefined> {
|
|
2785
|
+
/** Pre-created context. Omit for a fresh one. */
|
|
2786
|
+
context?: MakaioBusContext;
|
|
2787
|
+
/** Namespace scope (e.g. 'adapter:claudeCode'). */
|
|
2788
|
+
namespace?: Namespace;
|
|
2789
|
+
/** Transports to register immediately after creation. */
|
|
2790
|
+
transports?: BusTransport[];
|
|
2791
|
+
}
|
|
2792
|
+
/**
|
|
2793
|
+
* Creates a new bus instance with optional context, namespace isolation, and transports.
|
|
2794
|
+
*
|
|
2795
|
+
* The bus instance provides methods for type-safe event emission, request/response
|
|
2796
|
+
* patterns, handler registration, and namespace management. Handlers use
|
|
2797
|
+
* SubjectDefinition objects (not strings) for full type safety and schema validation.
|
|
2798
|
+
* @param options - Optional creation options. `context` defaults to a fresh `createBusContext()`.
|
|
2799
|
+
* `namespace` scopes the instance (e.g. `'adapter:claudeCode'`). `transports` are registered
|
|
2800
|
+
* immediately after creation.
|
|
2801
|
+
* @returns A new IMakaioBus instance with methods for on, emit, request, scoped, and schema management
|
|
2802
|
+
*/
|
|
2803
|
+
declare function createBusInstance<Namespace extends string | undefined = undefined>(options?: CreateBusOptions<Namespace>): IMakaioBus<Namespace>;
|
|
2804
|
+
/**
|
|
2805
|
+
* Main bus instance with unified API for events and request/response flows.
|
|
2806
|
+
*
|
|
2807
|
+
* Provides a singleton bus that manages schema-backed messaging with type-safe
|
|
2808
|
+
* subjects, namespace isolation, and transport routing. Use this as the central
|
|
2809
|
+
* coordination point for all cross-component communication.
|
|
2810
|
+
*
|
|
2811
|
+
* **Core Methods:**
|
|
2812
|
+
* - `registerNamespace()` - Register typed subjects with Zod schemas
|
|
2813
|
+
* - `on()` - Subscribe to events or requests with typed handlers
|
|
2814
|
+
* - `emit()` - Fire-and-forget event broadcasting
|
|
2815
|
+
* - `request()` - Request-response with middleware chain
|
|
2816
|
+
* - `scoped()` - Create namespace-scoped bus instance
|
|
2817
|
+
*
|
|
2818
|
+
* **Key Features:**
|
|
2819
|
+
* - Type-safe SubjectDefinition objects (no raw strings)
|
|
2820
|
+
* - Runtime validation in development (Zod schemas)
|
|
2821
|
+
* - Wildcard pattern matching with `.$all`
|
|
2822
|
+
* - Transport-backed remote messaging
|
|
2823
|
+
* - Hierarchical namespace support (e.g., `adapter:claudeCode`)
|
|
2824
|
+
* - Middleware chains for request processing
|
|
2825
|
+
* @example Basic usage
|
|
2826
|
+
* ```typescript
|
|
2827
|
+
* import { MakaioBus } from '@makaio/framework/bus';
|
|
2828
|
+
* import { z } from 'zod';
|
|
2829
|
+
*
|
|
2830
|
+
* // Register namespace with typed subjects
|
|
2831
|
+
* const { subjects } = MakaioBus.registerNamespace('agent', {
|
|
2832
|
+
* started: z.object({ agentId: z.string() }),
|
|
2833
|
+
* toolApprove: {
|
|
2834
|
+
* request: z.object({ toolName: z.string() }),
|
|
2835
|
+
* response: z.object({ approved: z.boolean() }),
|
|
2836
|
+
* },
|
|
2837
|
+
* });
|
|
2838
|
+
*
|
|
2839
|
+
* // Subscribe to events
|
|
2840
|
+
* MakaioBus.on(subjects.started, (context) => {
|
|
2841
|
+
* console.debug('Agent started:', context.payload.agentId);
|
|
2842
|
+
* });
|
|
2843
|
+
*
|
|
2844
|
+
* // Emit events
|
|
2845
|
+
* await MakaioBus.emit(subjects.started, { agentId: 'agent-123' });
|
|
2846
|
+
*
|
|
2847
|
+
* // Handle requests
|
|
2848
|
+
* MakaioBus.on(subjects.toolApprove, (context) => {
|
|
2849
|
+
* context.setResult({ approved: true });
|
|
2850
|
+
* });
|
|
2851
|
+
*
|
|
2852
|
+
* // Make requests
|
|
2853
|
+
* const result = await MakaioBus.request(subjects.toolApprove, {
|
|
2854
|
+
* toolName: 'deleteFile',
|
|
2855
|
+
* });
|
|
2856
|
+
* ```
|
|
2857
|
+
*/
|
|
2858
|
+
declare const MakaioBus: IMakaioBus;
|
|
2859
|
+
//#endregion
|
|
2860
|
+
//#region packages/bus-core/src/channel/types.d.ts
|
|
2861
|
+
/**
|
|
2862
|
+
* Encrypted point-to-point communication channel over the bus.
|
|
2863
|
+
*
|
|
2864
|
+
* Provides a bus-compatible interface (on, once, emit, request) where all
|
|
2865
|
+
* payloads are encrypted with a shared AES-256-GCM key derived via ECDH.
|
|
2866
|
+
* Observers, middleware, and transport loggers only see opaque `{ iv, data }` payloads.
|
|
2867
|
+
* Channel messages ride the normal bus transport layer unless the caller
|
|
2868
|
+
* explicitly constrains routing via the underlying bus configuration.
|
|
2869
|
+
*/
|
|
2870
|
+
interface IDirectChannel {
|
|
2871
|
+
/** Unique channel identifier (used in channel-scoped subject namespaces). */
|
|
2872
|
+
readonly channelId: string;
|
|
2873
|
+
/**
|
|
2874
|
+
* Register an event or request handler on this channel.
|
|
2875
|
+
* The handler receives decrypted payloads — encryption is transparent.
|
|
2876
|
+
* @param subject - Subject definition (channel or non-channel subjects both accepted)
|
|
2877
|
+
* @param handler - Handler function matching the subject's schema
|
|
2878
|
+
* @param options - Handler options (priority, etc.)
|
|
2879
|
+
* @returns Unsubscribe function
|
|
2880
|
+
*/
|
|
2881
|
+
on<Subject extends SubjectDefinition>(subject: Subject, handler: HandlerForSubjectDefinition<Subject>, options?: OnOptions): () => void;
|
|
2882
|
+
/**
|
|
2883
|
+
* Register a one-time handler that auto-unsubscribes after first invocation.
|
|
2884
|
+
* @param subject - Subject definition
|
|
2885
|
+
* @param handler - Handler function
|
|
2886
|
+
* @returns Unsubscribe function
|
|
2887
|
+
*/
|
|
2888
|
+
once<Subject extends SubjectDefinition>(subject: Subject, handler: HandlerForSubjectDefinition<Subject>): () => void;
|
|
2889
|
+
/**
|
|
2890
|
+
* Fire-and-forget encrypted event to the peer.
|
|
2891
|
+
* @param subject - Subject definition
|
|
2892
|
+
* @param payload - Event payload (will be encrypted before dispatch)
|
|
2893
|
+
*/
|
|
2894
|
+
emit<Subject extends SubjectDefinition>(subject: Subject, payload: Subject['$meta']['payload']): Promise<void>;
|
|
2895
|
+
/**
|
|
2896
|
+
* Encrypted request-response to the peer.
|
|
2897
|
+
* @param subject - Subject definition (must be a request subject)
|
|
2898
|
+
* @param payload - Request payload (will be encrypted before dispatch)
|
|
2899
|
+
* @param options - Request options (timeout, etc.)
|
|
2900
|
+
* @returns Decrypted response
|
|
2901
|
+
* @throws \{ChannelClosedError\} If the channel is closed
|
|
2902
|
+
* @throws \{NoHandlerError\} If the peer has no handler for this subject
|
|
2903
|
+
*/
|
|
2904
|
+
request<Subject extends SubjectDefinition>(subject: Subject, payload: Subject['$meta']['payload']['request'], options?: {
|
|
2905
|
+
timeout?: number;
|
|
2906
|
+
}): Promise<Subject['$meta']['payload']['response']>;
|
|
2907
|
+
/**
|
|
2908
|
+
* Encrypted request-response, returns `handled: false` instead of throwing NoHandlerError.
|
|
2909
|
+
* @param subject - Subject definition (must be a request subject)
|
|
2910
|
+
* @param payload - Request payload
|
|
2911
|
+
* @param options - Request options
|
|
2912
|
+
* @returns OptionalResult wrapping the response
|
|
2913
|
+
*/
|
|
2914
|
+
requestOptional<Subject extends SubjectDefinition>(subject: Subject, payload: Subject['$meta']['payload']['request'], options?: {
|
|
2915
|
+
timeout?: number;
|
|
2916
|
+
}): Promise<OptionalResult<Subject['$meta']['payload']['response']>>;
|
|
2917
|
+
/**
|
|
2918
|
+
* Close the channel. Notifies peer, rejects pending requests,
|
|
2919
|
+
* unsubscribes all handlers, and discards the shared encryption key.
|
|
2920
|
+
*/
|
|
2921
|
+
close(): void;
|
|
2922
|
+
}
|
|
2923
|
+
/**
|
|
2924
|
+
* Options for creating a channel endpoint.
|
|
2925
|
+
*/
|
|
2926
|
+
interface ChannelEndpointOptions {
|
|
2927
|
+
/** Capability token that clients must present to open this channel. */
|
|
2928
|
+
token: string;
|
|
2929
|
+
}
|
|
2930
|
+
/**
|
|
2931
|
+
* A registered channel endpoint that accepts incoming connections.
|
|
2932
|
+
*/
|
|
2933
|
+
interface ChannelEndpoint {
|
|
2934
|
+
/** The endpoint name (e.g., 'credentials'). */
|
|
2935
|
+
readonly name: string;
|
|
2936
|
+
/** The capability token clients need to open this channel. */
|
|
2937
|
+
readonly token: string;
|
|
2938
|
+
/** Unregister the endpoint, preventing new connections. */
|
|
2939
|
+
close(): void;
|
|
2940
|
+
}
|
|
2941
|
+
//#endregion
|
|
2942
|
+
//#region packages/bus-core/src/channel/system-namespace.d.ts
|
|
2943
|
+
/**
|
|
2944
|
+
* Schema for the system.channel.open handshake request.
|
|
2945
|
+
*
|
|
2946
|
+
* This is the only public-bus subject the channel system introduces.
|
|
2947
|
+
* The handshake includes a capability token that acts as a bearer
|
|
2948
|
+
* credential. Public keys are not secret, but the token grants channel
|
|
2949
|
+
* access and should only travel over trusted transports. Callers should
|
|
2950
|
+
* prefer `transports: []` for same-process channels.
|
|
2951
|
+
*/
|
|
2952
|
+
declare const SystemChannelSchemas: {
|
|
2953
|
+
'channel.open': {
|
|
2954
|
+
request: z.ZodObject<{
|
|
2955
|
+
endpoint: z.ZodString;
|
|
2956
|
+
token: z.ZodString;
|
|
2957
|
+
clientPubKey: z.ZodString;
|
|
2958
|
+
transports: z.ZodArray<z.ZodString>;
|
|
2959
|
+
}, z.core.$strip>;
|
|
2960
|
+
response: z.ZodObject<{
|
|
2961
|
+
channelId: z.ZodString;
|
|
2962
|
+
endpointPubKey: z.ZodString;
|
|
2963
|
+
}, z.core.$strip>;
|
|
2964
|
+
};
|
|
2965
|
+
};
|
|
2966
|
+
//#endregion
|
|
2967
|
+
//#region packages/bus-core/src/channel/channel-endpoint.d.ts
|
|
2968
|
+
/**
|
|
2969
|
+
* Register a channel endpoint that accepts encrypted point-to-point connections.
|
|
2970
|
+
*
|
|
2971
|
+
* Listens for `system.channel.open` requests. When a request arrives for this
|
|
2972
|
+
* endpoint name with the correct token:
|
|
2973
|
+
* 1. Performs the ECDH key exchange (generates a keypair, derives the shared secret).
|
|
2974
|
+
* 2. Instantiates an {@link IDirectChannel} for the endpoint side.
|
|
2975
|
+
* 3. Calls `callback` so the endpoint can register its channel-scoped handlers.
|
|
2976
|
+
* 4. Returns the channel ID and the endpoint public key to the client.
|
|
2977
|
+
*
|
|
2978
|
+
* Multiple endpoints can coexist on the same bus context; each handles only
|
|
2979
|
+
* requests whose `payload.endpoint` matches its own name.
|
|
2980
|
+
* @param context - Bus context to register the endpoint handler on
|
|
2981
|
+
* @param endpointName - Logical name for this endpoint (e.g., 'credentials')
|
|
2982
|
+
* @param callback - Called with the new {@link IDirectChannel} once the handshake
|
|
2983
|
+
* is complete; use this to register channel handlers before the client receives
|
|
2984
|
+
* the handshake response
|
|
2985
|
+
* @param options - Endpoint options including the shared capability token
|
|
2986
|
+
* @returns A {@link ChannelEndpoint} handle whose `close()` unregisters the endpoint
|
|
2987
|
+
*/
|
|
2988
|
+
declare function createChannelEndpoint(context: MakaioBusContext, endpointName: string, callback: (channel: IDirectChannel) => void, options: ChannelEndpointOptions): ChannelEndpoint;
|
|
2989
|
+
/**
|
|
2990
|
+
* Open an encrypted point-to-point channel to a registered endpoint.
|
|
2991
|
+
*
|
|
2992
|
+
* Performs the ECDH handshake via `system.channel.open`:
|
|
2993
|
+
* 1. Generates an ephemeral ECDH keypair.
|
|
2994
|
+
* 2. Sends the client public key and capability token to the endpoint.
|
|
2995
|
+
* 3. Receives the channel ID and endpoint public key.
|
|
2996
|
+
* 4. Derives the shared AES-256-GCM key from the client private key and endpoint
|
|
2997
|
+
* public key.
|
|
2998
|
+
* 5. Returns a `IDirectChannel` ready for encrypted communication.
|
|
2999
|
+
*
|
|
3000
|
+
* By default the handshake is dispatched over all registered transports so the
|
|
3001
|
+
* endpoint can reside in a different process. Pass `transports: []` to restrict
|
|
3002
|
+
* the handshake (and the resulting channel) to the local process only — this is
|
|
3003
|
+
* the correct choice whenever both sides are guaranteed to share the same bus
|
|
3004
|
+
* context (e.g., credential service and its same-process callers).
|
|
3005
|
+
* @param context - Bus context to use for the handshake request
|
|
3006
|
+
* @param endpointName - Logical name of the endpoint to connect to
|
|
3007
|
+
* @param options - Connection options including the shared capability token and
|
|
3008
|
+
* an optional transport allowlist (`transports: []` for local-only)
|
|
3009
|
+
* @returns Resolved `IDirectChannel` once the handshake completes
|
|
3010
|
+
* @throws \{RequestError\} If the handshake fails — for authentication failures, the
|
|
3011
|
+
* cause is a \{ChannelAuthError\}
|
|
3012
|
+
* @throws \{NoHandlerError\} If no endpoint with the given name is registered
|
|
3013
|
+
*/
|
|
3014
|
+
declare function openChannel(context: MakaioBusContext, endpointName: string, options: {
|
|
3015
|
+
token: string;
|
|
3016
|
+
transports?: ReadonlyArray<BusTransportKeys>;
|
|
3017
|
+
}): Promise<IDirectChannel>;
|
|
3018
|
+
//#endregion
|
|
3019
|
+
//#region packages/bus-core/src/utils/correlation-tracker.d.ts
|
|
3020
|
+
/**
|
|
3021
|
+
* Correlation tracker for request-response matching.
|
|
3022
|
+
*
|
|
3023
|
+
* Manages pending requests with timeout handling and automatic cleanup.
|
|
3024
|
+
*/
|
|
3025
|
+
/**
|
|
3026
|
+
* Tracks correlation IDs for request-response matching.
|
|
3027
|
+
*
|
|
3028
|
+
* Provides automatic timeout handling and cleanup for pending requests.
|
|
3029
|
+
* @example
|
|
3030
|
+
* ```typescript
|
|
3031
|
+
* const tracker = new CorrelationTracker();
|
|
3032
|
+
*
|
|
3033
|
+
* // Track a request with 5 second timeout
|
|
3034
|
+
* const promise = tracker.track('correlation-123', 5000);
|
|
3035
|
+
*
|
|
3036
|
+
* // Later, resolve when response arrives
|
|
3037
|
+
* tracker.resolve('correlation-123', { data: 'result' });
|
|
3038
|
+
*
|
|
3039
|
+
* // Or reject on error
|
|
3040
|
+
* tracker.reject('correlation-123', new Error('Failed'));
|
|
3041
|
+
* ```
|
|
3042
|
+
*/
|
|
3043
|
+
declare class CorrelationTracker {
|
|
3044
|
+
private pending;
|
|
3045
|
+
private static readonly DEFAULT_ABORT_MESSAGE;
|
|
3046
|
+
/**
|
|
3047
|
+
* Create a new correlation tracker.
|
|
3048
|
+
*/
|
|
3049
|
+
constructor();
|
|
3050
|
+
/**
|
|
3051
|
+
* Track a pending request.
|
|
3052
|
+
*
|
|
3053
|
+
* Returns a promise that resolves when the response arrives or rejects on timeout.
|
|
3054
|
+
* When `timeout` is `0`, no automatic timeout is set — the promise stays open
|
|
3055
|
+
* until `resolve()` or `reject()` is called externally (e.g. by the caller's
|
|
3056
|
+
* own `AbortSignal` or `pTimeout` wrapper).
|
|
3057
|
+
* @param correlationId - Correlation ID for the request
|
|
3058
|
+
* @param timeout - Timeout in milliseconds; `0` means no automatic timeout
|
|
3059
|
+
* @param signal - Optional AbortSignal to cancel and cleanup the pending entry
|
|
3060
|
+
* @returns Promise that resolves with the response result
|
|
3061
|
+
*/
|
|
3062
|
+
track(correlationId: string, timeout: number, signal?: AbortSignal): Promise<unknown>;
|
|
3063
|
+
/**
|
|
3064
|
+
* Convert AbortSignal reasons into Error instances while preserving reason detail.
|
|
3065
|
+
* @param signal - Abort signal associated with the pending request.
|
|
3066
|
+
* @returns Normalized abort error preserving the original reason when available.
|
|
3067
|
+
*/
|
|
3068
|
+
private getAbortError;
|
|
3069
|
+
/**
|
|
3070
|
+
* Resolve a pending request.
|
|
3071
|
+
*
|
|
3072
|
+
* Clears the timeout and removes the request from tracking.
|
|
3073
|
+
* @param correlationId - Correlation ID for the request
|
|
3074
|
+
* @param result - Response result
|
|
3075
|
+
*/
|
|
3076
|
+
resolve(correlationId: string, result: unknown): void;
|
|
3077
|
+
/**
|
|
3078
|
+
* Reject a pending request.
|
|
3079
|
+
*
|
|
3080
|
+
* Clears the timeout and removes the request from tracking.
|
|
3081
|
+
* @param correlationId - Correlation ID for the request
|
|
3082
|
+
* @param error - Error to reject with
|
|
3083
|
+
*/
|
|
3084
|
+
reject(correlationId: string, error: Error): void;
|
|
3085
|
+
/**
|
|
3086
|
+
* Cancel a pending request and remove its correlation entry.
|
|
3087
|
+
* @param correlationId - Correlation ID for the request
|
|
3088
|
+
* @param error - Optional cancellation error
|
|
3089
|
+
*/
|
|
3090
|
+
cancel(correlationId: string, error?: Error): void;
|
|
3091
|
+
/**
|
|
3092
|
+
* Clean up all pending requests.
|
|
3093
|
+
*
|
|
3094
|
+
* Clears all timeouts and rejects all pending requests with a disconnection error.
|
|
3095
|
+
*/
|
|
3096
|
+
cleanup(): void;
|
|
3097
|
+
}
|
|
3098
|
+
//#endregion
|
|
3099
|
+
//#region packages/bus-core/src/lifecycle-schemas.d.ts
|
|
3100
|
+
/** Payload emitted when a transport establishes or re-establishes a connection. */
|
|
3101
|
+
type ConnectedPayload = {
|
|
3102
|
+
transport: string;
|
|
3103
|
+
};
|
|
3104
|
+
/** Payload emitted when a transport loses connection unexpectedly. */
|
|
3105
|
+
type DisconnectedPayload = {
|
|
3106
|
+
transport: string;
|
|
3107
|
+
};
|
|
3108
|
+
//#endregion
|
|
3109
|
+
//#region packages/bus-core/src/lifecycle.d.ts
|
|
3110
|
+
/**
|
|
3111
|
+
* Bus-level lifecycle subjects for subscribing to transport connection state changes.
|
|
3112
|
+
*
|
|
3113
|
+
* All subjects are local-only: they are never relayed across transports, as they
|
|
3114
|
+
* describe the local bus's own connection state.
|
|
3115
|
+
*
|
|
3116
|
+
* Registration happens per-context inside `createBus()`.
|
|
3117
|
+
* @example
|
|
3118
|
+
* ```typescript
|
|
3119
|
+
* import { BusLifecycle } from '@makaio/framework/bus';
|
|
3120
|
+
*
|
|
3121
|
+
* MakaioBus.on(BusLifecycle.connected, ({ payload }) => {
|
|
3122
|
+
* console.log('Transport connected:', payload.transport);
|
|
3123
|
+
* });
|
|
3124
|
+
*
|
|
3125
|
+
* MakaioBus.on(BusLifecycle.disconnected, ({ payload }) => {
|
|
3126
|
+
* console.warn('Transport disconnected:', payload.transport);
|
|
3127
|
+
* });
|
|
3128
|
+
* ```
|
|
3129
|
+
*/
|
|
3130
|
+
declare const BusLifecycle: BusSubjects<FlatSubjectDefinitions<"bus:lifecycle", {
|
|
3131
|
+
connected: LocalSubjectSchema<_$zod.ZodObject<{
|
|
3132
|
+
transport: _$zod.ZodString;
|
|
3133
|
+
}, _$zod_v4_core0.$strip>>;
|
|
3134
|
+
disconnected: LocalSubjectSchema<_$zod.ZodObject<{
|
|
3135
|
+
transport: _$zod.ZodString;
|
|
3136
|
+
}, _$zod_v4_core0.$strip>>;
|
|
3137
|
+
}>, "bus:lifecycle">;
|
|
3138
|
+
//#endregion
|
|
3139
|
+
//#region packages/bus-core/src/extension-namespace-types.d.ts
|
|
3140
|
+
/**
|
|
3141
|
+
* Extension point for extension namespace extensions.
|
|
3142
|
+
*
|
|
3143
|
+
* Use declaration merging to add extension-specific metadata or capabilities:
|
|
3144
|
+
* @example
|
|
3145
|
+
* ```typescript
|
|
3146
|
+
* // In an extension package
|
|
3147
|
+
* declare module '@makaio/framework/bus' {
|
|
3148
|
+
* interface ExtensionNamespaceExtensions {
|
|
3149
|
+
* customMetadata?: {
|
|
3150
|
+
* version: string;
|
|
3151
|
+
* author: string;
|
|
3152
|
+
* };
|
|
3153
|
+
* }
|
|
3154
|
+
* }
|
|
3155
|
+
* ```
|
|
3156
|
+
*/
|
|
3157
|
+
interface ExtensionNamespaceExtensions {}
|
|
3158
|
+
/**
|
|
3159
|
+
* Extension namespace combines a pure bus namespace definition with
|
|
3160
|
+
* extensible extension-specific properties.
|
|
3161
|
+
*
|
|
3162
|
+
* Wraps BusNamespaceDefinition with:
|
|
3163
|
+
* - Automatic 'extension:' prefix for domain naming
|
|
3164
|
+
* - Extension point for extension metadata via declaration merging
|
|
3165
|
+
* @typeParam N - Extension name (without 'extension:' prefix)
|
|
3166
|
+
* @typeParam Subjects - Subject record type from schemas
|
|
3167
|
+
* @typeParam FilterPayload - Filter payload type for type-safe filtering
|
|
3168
|
+
* @typeParam Ext - Extension type preserving specific metadata types
|
|
3169
|
+
* @typeParam Schemas - Original schema record; drives narrow literal types on subjects.$meta
|
|
3170
|
+
*/
|
|
3171
|
+
interface ExtensionNamespace<N extends string = string, _Subjects extends SubjectRecord = SubjectRecord, _FilterPayload = unknown, Ext extends ExtensionNamespaceExtensions = ExtensionNamespaceExtensions, Schemas extends SchemaRecord = SchemaRecord> extends BusNamespaceDefinition<`extension:${N}`, Schemas> {
|
|
3172
|
+
/**
|
|
3173
|
+
* Extension name (without 'extension:' prefix).
|
|
3174
|
+
*/
|
|
3175
|
+
readonly domain: N;
|
|
3176
|
+
/**
|
|
3177
|
+
* Extension properties added via declaration merging.
|
|
3178
|
+
* @see ExtensionNamespaceExtensions
|
|
3179
|
+
*/
|
|
3180
|
+
readonly extensions: Ext;
|
|
3181
|
+
}
|
|
3182
|
+
/**
|
|
3183
|
+
* Configuration for creating an extension namespace.
|
|
3184
|
+
* @typeParam Schemas - Schema record type for bus subjects
|
|
3185
|
+
* @typeParam Ext - Extension type preserving specific metadata types
|
|
3186
|
+
*/
|
|
3187
|
+
interface ExtensionNamespaceConfig<Schemas extends SchemaRecord, Ext extends ExtensionNamespaceExtensions = ExtensionNamespaceExtensions> {
|
|
3188
|
+
/**
|
|
3189
|
+
* Bus subject schemas for extension operations.
|
|
3190
|
+
* Can include both request-response and event schemas.
|
|
3191
|
+
*/
|
|
3192
|
+
schemas: Schemas;
|
|
3193
|
+
/**
|
|
3194
|
+
* Extension properties (populated by declaration merging).
|
|
3195
|
+
* @see ExtensionNamespaceExtensions
|
|
3196
|
+
*/
|
|
3197
|
+
extensions?: Ext;
|
|
3198
|
+
}
|
|
3199
|
+
/**
|
|
3200
|
+
* Infer the extension namespace type from config.
|
|
3201
|
+
* @typeParam N - Extension name without the `extension:` prefix
|
|
3202
|
+
* @typeParam Schemas - Schema record type for bus subjects
|
|
3203
|
+
* @typeParam Ext - Extension type preserving specific metadata types
|
|
3204
|
+
*/
|
|
3205
|
+
type ExtensionNamespaceFromConfig<N extends string, Schemas extends SchemaRecord, Ext extends ExtensionNamespaceExtensions = ExtensionNamespaceExtensions> = ExtensionNamespace<N, SubjectRecordFromSchemaRecord<Schemas>, FilterablePayloadIntersection<SubjectRecordFromSchemaRecord<Schemas>>, Ext, Schemas>;
|
|
3206
|
+
//#endregion
|
|
3207
|
+
//#region packages/bus-core/src/utils/transport-helpers.d.ts
|
|
3208
|
+
/**
|
|
3209
|
+
* Check if a client/tab wants to receive a message based on subscriptions and filters.
|
|
3210
|
+
*
|
|
3211
|
+
* **Filtering logic:**
|
|
3212
|
+
* - No subscriptions = receive all (default broadcast mode)
|
|
3213
|
+
* - With subscriptions: check if message subject matches any subscription pattern
|
|
3214
|
+
* - Apply payload filters if the client has filters for this subject
|
|
3215
|
+
* @param subject - The message subject (if any)
|
|
3216
|
+
* @param payload - The message payload (if any)
|
|
3217
|
+
* @param subscriptions - Set of subscription patterns
|
|
3218
|
+
* @param filters - Map of payload filters per subject
|
|
3219
|
+
* @returns true if the client should receive the message
|
|
3220
|
+
*/
|
|
3221
|
+
declare function shouldReceiveMessage(subject: string | undefined, payload: unknown, subscriptions: Set<string>, filters: Map<string, PayloadFilter>): boolean;
|
|
3222
|
+
/**
|
|
3223
|
+
* Handle response messages for correlation tracking.
|
|
3224
|
+
*
|
|
3225
|
+
* Processes both regular response and broadcast-response messages,
|
|
3226
|
+
* resolving or rejecting the corresponding correlation promise.
|
|
3227
|
+
* @param message - Decoded bus message
|
|
3228
|
+
* @param correlations - Correlation tracker instance
|
|
3229
|
+
* @returns true if the message was a response and was handled
|
|
3230
|
+
*/
|
|
3231
|
+
declare function handleCorrelationResponse(message: BusMessage, correlations: CorrelationTracker): boolean;
|
|
3232
|
+
/**
|
|
3233
|
+
* Track correlation for request/broadcast messages and return appropriate result type.
|
|
3234
|
+
*
|
|
3235
|
+
* **Behavior by message type:**
|
|
3236
|
+
* - Request: Returns promise tracking correlation (resolves to response payload)
|
|
3237
|
+
* - Broadcast: Returns promise tracking correlation (resolves to array of results)
|
|
3238
|
+
* - Other: Returns true immediately (no correlation tracking needed)
|
|
3239
|
+
*
|
|
3240
|
+
* **Timeout semantics:**
|
|
3241
|
+
* Pass `0` to disable automatic timeout — the correlation entry stays open
|
|
3242
|
+
* until resolved or rejected externally. All callers must supply an explicit
|
|
3243
|
+
* value; there is no default so callers cannot accidentally rely on a hidden timeout.
|
|
3244
|
+
* @param message - Bus message to process
|
|
3245
|
+
* @param correlations - Correlation tracker instance
|
|
3246
|
+
* @param timeout - Timeout in milliseconds; `0` means no automatic timeout
|
|
3247
|
+
* @param signal - Optional AbortSignal forwarded to correlation tracking cleanup
|
|
3248
|
+
* @returns Promise resolving to response data, broadcast results, or boolean
|
|
3249
|
+
*/
|
|
3250
|
+
declare function trackMessageCorrelation<TMessage extends BusMessage>(message: TMessage, correlations: CorrelationTracker, timeout: number, signal?: AbortSignal): Promise<TMessage extends BusRequestMessage ? unknown : TMessage extends BusBroadcastMessage ? Array<{
|
|
3251
|
+
nodeId: string;
|
|
3252
|
+
payload: unknown;
|
|
3253
|
+
}> : boolean>;
|
|
3254
|
+
/**
|
|
3255
|
+
* Serialize an error into a transport-safe structure.
|
|
3256
|
+
*
|
|
3257
|
+
* Preserves `subject` alongside `code` so that `isNoHandlerErrorForSubject`
|
|
3258
|
+
* can match deserialized errors without fragile message-string comparisons.
|
|
3259
|
+
* @param error - The error to serialize
|
|
3260
|
+
* @returns Structured error payload
|
|
3261
|
+
*/
|
|
3262
|
+
declare function serializeTransportError(error: unknown): BusTransportError;
|
|
3263
|
+
//#endregion
|
|
3264
|
+
//#region packages/bus-core/src/subscribe-message.d.ts
|
|
3265
|
+
/**
|
|
3266
|
+
* Per-subject subscription state tracked locally on a client transport.
|
|
3267
|
+
*/
|
|
3268
|
+
interface SubscriptionEntry {
|
|
3269
|
+
/** Optional payload filter for server-side smart-routing. */
|
|
3270
|
+
filter?: PayloadFilter;
|
|
3271
|
+
/** Handler priorities registered for this subject. Empty array = event-only. */
|
|
3272
|
+
priorities: number[];
|
|
3273
|
+
}
|
|
3274
|
+
/**
|
|
3275
|
+
* Build a BusSubscribeMessage from local subscription state.
|
|
3276
|
+
* @param subscriptions - Map of subject patterns to their subscription entries
|
|
3277
|
+
* @returns Wire-format subscribe message
|
|
3278
|
+
*/
|
|
3279
|
+
declare function buildSubscribeMessage(subscriptions: Map<string, SubscriptionEntry>): BusSubscribeMessage;
|
|
3280
|
+
/**
|
|
3281
|
+
* Build a BusUnsubscribeMessage for specific subjects and priorities.
|
|
3282
|
+
* @param subjects - Map of subject patterns to priorities being removed
|
|
3283
|
+
* @returns Wire-format unsubscribe message
|
|
3284
|
+
*/
|
|
3285
|
+
declare function buildUnsubscribeMessage(subjects: Record<string, number[]>): BusUnsubscribeMessage;
|
|
3286
|
+
//#endregion
|
|
3287
|
+
//#region packages/bus-core/src/create-extension-namespace.d.ts
|
|
3288
|
+
type Whitespace = ' ' | '\n' | '\r' | '\t' | '\v' | '\f' | '\u00A0' | '\u1680' | '\u2000' | '\u2001' | '\u2002' | '\u2003' | '\u2004' | '\u2005' | '\u2006' | '\u2007' | '\u2008' | '\u2009' | '\u200A' | '\u2028' | '\u2029' | '\u202F' | '\u205F' | '\u3000' | '\uFEFF';
|
|
3289
|
+
type TrimLeft<T extends string> = T extends `${Whitespace}${infer Rest}` ? TrimLeft<Rest> : T;
|
|
3290
|
+
type TrimRight<T extends string> = T extends `${infer Rest}${Whitespace}` ? TrimRight<Rest> : T;
|
|
3291
|
+
type Trim<T extends string> = string extends T ? string : TrimLeft<TrimRight<T>>;
|
|
3292
|
+
/**
|
|
3293
|
+
* Creates an extension namespace with typed subject definitions.
|
|
3294
|
+
*
|
|
3295
|
+
* Pure wrapper around {@link createBusNamespace} that:
|
|
3296
|
+
* - Automatically prepends 'extension:' to the domain name
|
|
3297
|
+
* - Provides extension point for extension-specific metadata via declaration merging
|
|
3298
|
+
* - Preserves type-safe filtering capabilities
|
|
3299
|
+
* @param extensionName - Extension name (e.g., 'terminal' becomes 'extension:terminal')
|
|
3300
|
+
* @param config - Namespace configuration with schemas and optional extensions
|
|
3301
|
+
* @returns Extension namespace with typed subjects and extensions
|
|
3302
|
+
* @example
|
|
3303
|
+
* ```typescript
|
|
3304
|
+
* // Basic usage (bus-only)
|
|
3305
|
+
* const TerminalExtension = createExtensionNamespace('terminal', {
|
|
3306
|
+
* schemas: {
|
|
3307
|
+
* spawn: { request: z.object({ cwd: z.string() }), response: z.object({ terminalId: z.string() }) },
|
|
3308
|
+
* output: z.object({ terminalId: z.string(), data: z.string() }),
|
|
3309
|
+
* },
|
|
3310
|
+
* });
|
|
3311
|
+
*
|
|
3312
|
+
* // With custom extension (after importing extension package)
|
|
3313
|
+
* const MyExtension = createExtensionNamespace('my-extension', {
|
|
3314
|
+
* schemas: { ... },
|
|
3315
|
+
* extensions: {
|
|
3316
|
+
* customMetadata: { version: '1.0.0' },
|
|
3317
|
+
* },
|
|
3318
|
+
* });
|
|
3319
|
+
* ```
|
|
3320
|
+
*/
|
|
3321
|
+
declare function createExtensionNamespace<N extends string, Schemas extends SchemaRecord, Ext extends ExtensionNamespaceExtensions = ExtensionNamespaceExtensions>(extensionName: N, config: ExtensionNamespaceConfig<Schemas, Ext>): ExtensionNamespace<Trim<N>, SubjectRecordFromSchemaRecord<Schemas>, FilterablePayloadIntersection<SubjectRecordFromSchemaRecord<Schemas>>, Ext, Schemas>;
|
|
3322
|
+
//#endregion
|
|
3323
|
+
//#region packages/bus-core/src/utils/warn-unregistered.d.ts
|
|
3324
|
+
/**
|
|
3325
|
+
* Reset the warned-subjects set between test runs.
|
|
3326
|
+
* @internal
|
|
3327
|
+
* @returns Reset function in test mode, undefined otherwise
|
|
3328
|
+
*/
|
|
3329
|
+
declare const __resetWarnedSubjects: (() => void) | undefined;
|
|
3330
|
+
//#endregion
|
|
3331
|
+
export { type BroadcastContext, type BroadcastResult, type BusBroadcastMessage, type BusBroadcastResponseMessage, BusError, type BusEventMessage, type BusHeartbeatMessage, BusLifecycle, type BusMessage, type BusNamespace, type BusReceiveHandler, type BusRequestMessage, type BusResponseMessage, type BusSubscribeMessage, type BusSubscribeSyncCompleteMessage, type BusTransport, type BusTransportError, type BusTransportKeys, type BusTransportRegistry, type BusUnsubscribeMessage, type BusUrlConfig, type BusValidationMode, ChannelAuthError, ChannelClosedError, type ChannelEndpoint, type ChannelEndpointOptions, ChannelOnlyError, type ConnectOptions, type ConnectedPayload, CorrelationTracker, DEFAULT_REQUEST_TIMEOUT_MS, type DefinedSubjectExtension, type DisconnectedPayload, type EventSubjectExtension, type ExtendedSubjectDefinition, type ExtensionNamespace, type ExtensionNamespaceConfig, type ExtensionNamespaceExtensions, type ExtensionNamespaceFromConfig, type IDirectChannel, type IFilteredBus, type IMakaioBus, type InterceptorContext, LocalSubjectError, MakaioBus, type MakaioBusContext, NO_HANDLER_ERROR_CODE, type NamespaceRegistrationOptions, NoHandlerError, type OnOptions, OnceAbortError, type OptionalResult, RequestError, type RequestSubjectExtension, type SchemaViolationCallback, type SchemaViolationReport, type ScopedBus, type ScopedBusFor, type SubjectExtension, type SubscriptionEntry, SystemChannelSchemas, TimeoutError, type TransportRegistration, ValidationError, __resetWarnedSubjects, buildSubscribeMessage, buildUnsubscribeMessage, channelSubject, createBusContext, createBusInstance, createChannelEndpoint, createExtensionNamespace, createFilteredBus, defineSubjectExtension, deserializeTransportError, extendSubjectImpl as extendSubject, getFullSubjectForSubjectDefinition, getPath, getSubjectFromBusMessage, handleCorrelationResponse, isNoHandlerErrorForSubject, isRequestSchema, localSubject, matchesAnySubscription, matchesFilter, matchesSubscription, mergeFilters, openChannel, parseBusUrl, serializeTransportError, shouldReceiveMessage, trackMessageCorrelation };
|