@mastra/server 1.60.0-alpha.8 → 1.60.0
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/CHANGELOG.md +140 -0
- package/dist/{a2a-Eeib3vfP.cjs → a2a-BtXFFv-0.cjs} +4 -4
- package/dist/{a2a-Eeib3vfP.cjs.map → a2a-BtXFFv-0.cjs.map} +1 -1
- package/dist/{a2a-B5m54dOP.js → a2a-DZhtQeFL.js} +3 -3
- package/dist/{a2a-B5m54dOP.js.map → a2a-DZhtQeFL.js.map} +1 -1
- package/dist/{agent-versions-xeysPGel.cjs → agent-versions-MYjO6Wl1.cjs} +2 -2
- package/dist/{agent-versions-xeysPGel.cjs.map → agent-versions-MYjO6Wl1.cjs.map} +1 -1
- package/dist/{agent-versions-CWEnD62A.js → agent-versions-mFXaw5ma.js} +2 -2
- package/dist/{agent-versions-CWEnD62A.js.map → agent-versions-mFXaw5ma.js.map} +1 -1
- package/dist/{api-schema-manifest-BKTXRheC.js → api-schema-manifest-Bx_zU5qw.js} +2 -2
- package/dist/{api-schema-manifest-BKTXRheC.js.map → api-schema-manifest-Bx_zU5qw.js.map} +1 -1
- package/dist/{api-schema-manifest-BbNdh5Ck.cjs → api-schema-manifest-DPgfugJT.cjs} +4 -3
- package/dist/{api-schema-manifest-BbNdh5Ck.cjs.map → api-schema-manifest-DPgfugJT.cjs.map} +1 -1
- package/dist/{background-tasks-C5G2jJax.cjs → background-tasks-8M9W_27g.cjs} +2 -2
- package/dist/{background-tasks-C5G2jJax.cjs.map → background-tasks-8M9W_27g.cjs.map} +1 -1
- package/dist/{builder-registry-CyaUg_iP.cjs → builder-registry-Dcd_ApmT.cjs} +3 -3
- package/dist/{builder-registry-CyaUg_iP.cjs.map → builder-registry-Dcd_ApmT.cjs.map} +1 -1
- package/dist/{builder-registry-CqLsr39q.js → builder-registry-DnEa4qnF.js} +2 -2
- package/dist/{builder-registry-CqLsr39q.js.map → builder-registry-DnEa4qnF.js.map} +1 -1
- package/dist/{channels-BnFQESMf.js → channels-BO3Zd38V.js} +2 -2
- package/dist/{channels-BnFQESMf.js.map → channels-BO3Zd38V.js.map} +1 -1
- package/dist/{channels-Dzy6VM3w.cjs → channels-D9WRnKzU.cjs} +3 -3
- package/dist/{channels-Dzy6VM3w.cjs.map → channels-D9WRnKzU.cjs.map} +1 -1
- package/dist/{constants-CutMu4A_.js → constants-0jFCWoex.js} +13 -2
- package/dist/constants-0jFCWoex.js.map +1 -0
- package/dist/{constants-CXPpy-Ef.cjs → constants-4IJp_uzj.cjs} +18 -1
- package/dist/constants-4IJp_uzj.cjs.map +1 -0
- package/dist/{conversations-CcFLCCeF.cjs → conversations-PF0eKhIu.cjs} +3 -3
- package/dist/{conversations-CcFLCCeF.cjs.map → conversations-PF0eKhIu.cjs.map} +1 -1
- package/dist/{dist-CAVC0nWG.cjs → dist-2zVeGGHi.cjs} +3 -2
- package/dist/{dist-CAVC0nWG.cjs.map → dist-2zVeGGHi.cjs.map} +1 -1
- package/dist/{dist-D7GkGue6.cjs → dist-8-Z5v77M.cjs} +3 -2
- package/dist/{dist-D7GkGue6.cjs.map → dist-8-Z5v77M.cjs.map} +1 -1
- package/dist/{dist-SKhVwZMV.cjs → dist-Be7Caz3Z.cjs} +3 -2
- package/dist/{dist-SKhVwZMV.cjs.map → dist-Be7Caz3Z.cjs.map} +1 -1
- package/dist/{dist-18h28zlO.cjs → dist-BfVTO0pC.cjs} +3 -2
- package/dist/{dist-18h28zlO.cjs.map → dist-BfVTO0pC.cjs.map} +1 -1
- package/dist/{dist-BD0I5lxM.js → dist-CHJcZQdS.js} +2 -2
- package/dist/{dist-BD0I5lxM.js.map → dist-CHJcZQdS.js.map} +1 -1
- package/dist/{dist-BpRGQqjE.cjs → dist-CJKQBH69.cjs} +2 -2
- package/dist/{dist-BpRGQqjE.cjs.map → dist-CJKQBH69.cjs.map} +1 -1
- package/dist/{dist-sUhxlnJz.js → dist-CRgxcDTg.js} +2 -2
- package/dist/{dist-sUhxlnJz.js.map → dist-CRgxcDTg.js.map} +1 -1
- package/dist/{dist-JdnTASYe.js → dist-CscF1cF8.js} +2 -2
- package/dist/{dist-JdnTASYe.js.map → dist-CscF1cF8.js.map} +1 -1
- package/dist/{dist-CpxQhZED.js → dist-Cw-T1gX6.js} +2818 -309
- package/dist/dist-Cw-T1gX6.js.map +1 -0
- package/dist/{dist-DBP9kw_8.cjs → dist-D4NzuG3G.cjs} +3 -2
- package/dist/{dist-DBP9kw_8.cjs.map → dist-D4NzuG3G.cjs.map} +1 -1
- package/dist/{dist-CpaK1qK1.cjs → dist-DERatX43.cjs} +2819 -310
- package/dist/dist-DERatX43.cjs.map +1 -0
- package/dist/{dist-mcwHCl2a.js → dist-F_Ql1co6.js} +2 -2
- package/dist/{dist-mcwHCl2a.js.map → dist-F_Ql1co6.js.map} +1 -1
- package/dist/{dist-C-9xUY65.js → dist-Jn3uXsoB.js} +2 -2
- package/dist/{dist-C-9xUY65.js.map → dist-Jn3uXsoB.js.map} +1 -1
- package/dist/{dist-DyBO3IVt.js → dist-bAFqx06T.js} +2 -2
- package/dist/{dist-DyBO3IVt.js.map → dist-bAFqx06T.js.map} +1 -1
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/{dynamic-workflows-C-6vmau5.cjs → dynamic-workflows-BZ5ru36x.cjs} +3 -3
- package/dist/{dynamic-workflows-C-6vmau5.cjs.map → dynamic-workflows-BZ5ru36x.cjs.map} +1 -1
- package/dist/{dynamic-workflows-B0TE8mjA.js → dynamic-workflows-C6U0Rdoc.js} +2 -2
- package/dist/{dynamic-workflows-B0TE8mjA.js.map → dynamic-workflows-C6U0Rdoc.js.map} +1 -1
- package/dist/{editor-builder-1L3OIY4K.cjs → editor-builder-BmRQift0.cjs} +2 -2
- package/dist/{editor-builder-1L3OIY4K.cjs.map → editor-builder-BmRQift0.cjs.map} +1 -1
- package/dist/{helpers-C54OMiDG.cjs → helpers-BWxRRShz.cjs} +2 -2
- package/dist/{helpers-C54OMiDG.cjs.map → helpers-BWxRRShz.cjs.map} +1 -1
- package/dist/{helpers-Da9nPOFL.js → helpers-DBAYsA50.js} +2 -2
- package/dist/{helpers-Da9nPOFL.js.map → helpers-DBAYsA50.js.map} +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/{observability-new-endpoints-BC-dasRY.cjs → observability-new-endpoints-gRCFhnRr.cjs} +2 -2
- package/dist/{observability-new-endpoints-BC-dasRY.cjs.map → observability-new-endpoints-gRCFhnRr.cjs.map} +1 -1
- package/dist/{probe-image-size-C2F59z8Z.cjs → probe-image-size-CDCRrXNo.cjs} +140 -33
- package/dist/probe-image-size-CDCRrXNo.cjs.map +1 -0
- package/dist/{probe-image-size-mXCWYNrz.js → probe-image-size-Tf8sNZhU.js} +137 -33
- package/dist/probe-image-size-Tf8sNZhU.js.map +1 -0
- package/dist/{responses-BI25doe1.cjs → responses-CKNdSRkS.cjs} +2 -2
- package/dist/{responses-BI25doe1.cjs.map → responses-CKNdSRkS.cjs.map} +1 -1
- package/dist/{rolldown-runtime-CVvi-lCc.cjs → rolldown-runtime-Bd6kNlEP.cjs} +21 -0
- package/dist/{rolldown-runtime-DuvcJU0W.js → rolldown-runtime-maW3aOIk.js} +10 -1
- package/dist/{route-builder-BAAedfru.cjs → route-builder-CWsok5ci.cjs} +2 -2
- package/dist/{route-builder-BAAedfru.cjs.map → route-builder-CWsok5ci.cjs.map} +1 -1
- package/dist/{routes-iUe0w9eL.js → routes-Bh2p-WqG.js} +5 -5
- package/dist/{routes-iUe0w9eL.js.map → routes-Bh2p-WqG.js.map} +1 -1
- package/dist/{routes-mK_LlDMo.cjs → routes-CdbboDwv.cjs} +10 -10
- package/dist/{routes-mK_LlDMo.cjs.map → routes-CdbboDwv.cjs.map} +1 -1
- package/dist/{schedules-DOK225ZZ.cjs → schedules-7YUg_TRM.cjs} +2 -2
- package/dist/{schedules-DOK225ZZ.cjs.map → schedules-7YUg_TRM.cjs.map} +1 -1
- package/dist/{schema-Bv9OdW1f-CHHI-NTr.cjs → schema-Bv9OdW1f-CxTiW8RD.cjs} +2 -2
- package/dist/{schema-Bv9OdW1f-CHHI-NTr.cjs.map → schema-Bv9OdW1f-CxTiW8RD.cjs.map} +1 -1
- package/dist/schema-CNKnRmv1.cjs +1 -0
- package/dist/{scorer-versions-CdVjOtQO.js → scorer-versions-D0_KP67E.js} +2 -2
- package/dist/{scorer-versions-CdVjOtQO.js.map → scorer-versions-D0_KP67E.js.map} +1 -1
- package/dist/{scorer-versions-CYXtxMTU.cjs → scorer-versions-mL--H4LL.cjs} +2 -2
- package/dist/{scorer-versions-CYXtxMTU.cjs.map → scorer-versions-mL--H4LL.cjs.map} +1 -1
- package/dist/server/a2a/store.cjs +1 -0
- package/dist/server/a2a/store.cjs.map +1 -1
- package/dist/server/auth/index.cjs +3 -2
- package/dist/server/auth/index.js +2 -2
- package/dist/server/browser-stream/index.cjs +1 -0
- package/dist/server/browser-stream/index.cjs.map +1 -1
- package/dist/server/constants.d.ts +11 -0
- package/dist/server/constants.d.ts.map +1 -1
- package/dist/server/handlers/a2a.cjs +2 -1
- package/dist/server/handlers/a2a.js +1 -1
- package/dist/server/handlers/agent-builder.cjs +4 -4
- package/dist/server/handlers/agent-builder.js +3 -3
- package/dist/server/handlers/agent-controller.cjs +53 -36
- package/dist/server/handlers/agent-controller.cjs.map +1 -1
- package/dist/server/handlers/agent-controller.d.ts +22 -2
- package/dist/server/handlers/agent-controller.d.ts.map +1 -1
- package/dist/server/handlers/agent-controller.js +51 -35
- package/dist/server/handlers/agent-controller.js.map +1 -1
- package/dist/server/handlers/agent-versions.cjs +4 -3
- package/dist/server/handlers/agent-versions.cjs.map +1 -1
- package/dist/server/handlers/agent-versions.js +2 -2
- package/dist/server/handlers/agents.cjs +8 -8
- package/dist/server/handlers/agents.d.ts +8 -0
- package/dist/server/handlers/agents.d.ts.map +1 -1
- package/dist/server/handlers/agents.js +5 -5
- package/dist/server/handlers/auth.cjs +16 -7
- package/dist/server/handlers/auth.cjs.map +1 -1
- package/dist/server/handlers/auth.d.ts +10 -4
- package/dist/server/handlers/auth.d.ts.map +1 -1
- package/dist/server/handlers/auth.js +14 -6
- package/dist/server/handlers/auth.js.map +1 -1
- package/dist/server/handlers/author-enrichment.cjs +1 -0
- package/dist/server/handlers/author-enrichment.cjs.map +1 -1
- package/dist/server/handlers/authorship.cjs +2 -1
- package/dist/server/handlers/authorship.cjs.map +1 -1
- package/dist/server/handlers/authorship.js +1 -1
- package/dist/server/handlers/background-tasks.cjs +2 -1
- package/dist/server/handlers/builder-registry.cjs +2 -1
- package/dist/server/handlers/builder-registry.js +1 -1
- package/dist/server/handlers/channels.cjs +2 -1
- package/dist/server/handlers/channels.js +1 -1
- package/dist/server/handlers/conversations.cjs +4 -4
- package/dist/server/handlers/conversations.js +2 -2
- package/dist/server/handlers/datasets.cjs +3 -2
- package/dist/server/handlers/datasets.cjs.map +1 -1
- package/dist/server/handlers/datasets.d.ts +6 -6
- package/dist/server/handlers/datasets.js +1 -1
- package/dist/server/handlers/dynamic-workflows.cjs +2 -1
- package/dist/server/handlers/dynamic-workflows.js +1 -1
- package/dist/server/handlers/editor-builder.cjs +2 -1
- package/dist/server/handlers/error.cjs +1 -0
- package/dist/server/handlers/error.cjs.map +1 -1
- package/dist/server/handlers/favorites-enrichment.cjs +2 -1
- package/dist/server/handlers/favorites-enrichment.cjs.map +1 -1
- package/dist/server/handlers/gateway-memory-client.cjs +1 -0
- package/dist/server/handlers/gateway-memory-client.cjs.map +1 -1
- package/dist/server/handlers/logs.cjs +3 -3
- package/dist/server/handlers/logs.js +2 -2
- package/dist/server/handlers/mcp-client-versions.cjs +3 -2
- package/dist/server/handlers/mcp-client-versions.cjs.map +1 -1
- package/dist/server/handlers/mcp-client-versions.js +1 -1
- package/dist/server/handlers/mcp.cjs +2 -2
- package/dist/server/handlers/mcp.js +1 -1
- package/dist/server/handlers/memory.cjs +3 -3
- package/dist/server/handlers/memory.js +2 -2
- package/dist/server/handlers/observability-list-query-schemas.cjs +1 -0
- package/dist/server/handlers/observability-list-query-schemas.cjs.map +1 -1
- package/dist/server/handlers/observability-new-endpoints.cjs +2 -1
- package/dist/server/handlers/observability-shared.cjs +2 -1
- package/dist/server/handlers/observability-shared.cjs.map +1 -1
- package/dist/server/handlers/observability-storage-schemas.cjs +1 -1
- package/dist/server/handlers/observability.cjs +8 -5
- package/dist/server/handlers/observability.cjs.map +1 -1
- package/dist/server/handlers/observability.d.ts.map +1 -1
- package/dist/server/handlers/observability.js +7 -4
- package/dist/server/handlers/observability.js.map +1 -1
- package/dist/server/handlers/plans.cjs +3 -3
- package/dist/server/handlers/plans.js +2 -2
- package/dist/server/handlers/processor-providers.cjs +2 -1
- package/dist/server/handlers/processor-providers.cjs.map +1 -1
- package/dist/server/handlers/processors.cjs +2 -1
- package/dist/server/handlers/processors.cjs.map +1 -1
- package/dist/server/handlers/prompt-block-versions.cjs +3 -2
- package/dist/server/handlers/prompt-block-versions.cjs.map +1 -1
- package/dist/server/handlers/prompt-block-versions.js +1 -1
- package/dist/server/handlers/responses.adapter.cjs +1 -0
- package/dist/server/handlers/responses.adapter.cjs.map +1 -1
- package/dist/server/handlers/responses.cjs +4 -4
- package/dist/server/handlers/responses.js +2 -2
- package/dist/server/handlers/responses.storage.cjs +2 -1
- package/dist/server/handlers/responses.storage.cjs.map +1 -1
- package/dist/server/handlers/responses.storage.js +1 -1
- package/dist/server/handlers/schedules-workflows-shim.cjs +1 -1
- package/dist/server/handlers/schedules.cjs +2 -1
- package/dist/server/handlers/scorer-versions.cjs +4 -3
- package/dist/server/handlers/scorer-versions.cjs.map +1 -1
- package/dist/server/handlers/scorer-versions.js +2 -2
- package/dist/server/handlers/scores.cjs +2 -2
- package/dist/server/handlers/scores.js +1 -1
- package/dist/server/handlers/skills-sh-shared.cjs +1 -0
- package/dist/server/handlers/skills-sh-shared.cjs.map +1 -1
- package/dist/server/handlers/stored-agent-favorites.cjs +5 -4
- package/dist/server/handlers/stored-agent-favorites.cjs.map +1 -1
- package/dist/server/handlers/stored-agent-favorites.js +2 -2
- package/dist/server/handlers/stored-agents.cjs +7 -5
- package/dist/server/handlers/stored-agents.cjs.map +1 -1
- package/dist/server/handlers/stored-agents.d.ts +32 -0
- package/dist/server/handlers/stored-agents.d.ts.map +1 -1
- package/dist/server/handlers/stored-agents.js +4 -3
- package/dist/server/handlers/stored-agents.js.map +1 -1
- package/dist/server/handlers/stored-mcp-clients.cjs +3 -2
- package/dist/server/handlers/stored-mcp-clients.cjs.map +1 -1
- package/dist/server/handlers/stored-mcp-clients.js +1 -1
- package/dist/server/handlers/stored-prompt-blocks.cjs +3 -2
- package/dist/server/handlers/stored-prompt-blocks.cjs.map +1 -1
- package/dist/server/handlers/stored-prompt-blocks.js +1 -1
- package/dist/server/handlers/stored-scorers.cjs +4 -3
- package/dist/server/handlers/stored-scorers.cjs.map +1 -1
- package/dist/server/handlers/stored-scorers.js +2 -2
- package/dist/server/handlers/stored-skill-favorites.cjs +4 -3
- package/dist/server/handlers/stored-skill-favorites.cjs.map +1 -1
- package/dist/server/handlers/stored-skill-favorites.js +1 -1
- package/dist/server/handlers/stored-skills.cjs +4 -3
- package/dist/server/handlers/stored-skills.cjs.map +1 -1
- package/dist/server/handlers/stored-skills.js +1 -1
- package/dist/server/handlers/stored-workspaces.cjs +3 -2
- package/dist/server/handlers/stored-workspaces.cjs.map +1 -1
- package/dist/server/handlers/stored-workspaces.js +1 -1
- package/dist/server/handlers/system.cjs +3 -2
- package/dist/server/handlers/system.cjs.map +1 -1
- package/dist/server/handlers/system.js +1 -1
- package/dist/server/handlers/test-utils.cjs +1 -0
- package/dist/server/handlers/test-utils.cjs.map +1 -1
- package/dist/server/handlers/tool-providers.cjs +3 -2
- package/dist/server/handlers/tool-providers.cjs.map +1 -1
- package/dist/server/handlers/tool-providers.js +1 -1
- package/dist/server/handlers/tool-schema-overrides.cjs +1 -0
- package/dist/server/handlers/tool-schema-overrides.cjs.map +1 -1
- package/dist/server/handlers/tools.cjs +6 -6
- package/dist/server/handlers/tools.js +3 -3
- package/dist/server/handlers/utils.cjs +2 -1
- package/dist/server/handlers/utils.js +1 -1
- package/dist/server/handlers/validate-agent-instructions.cjs +2 -1
- package/dist/server/handlers/validate-agent-instructions.cjs.map +1 -1
- package/dist/server/handlers/validate-agent-instructions.js +1 -1
- package/dist/server/handlers/validate-avatar.cjs +1 -0
- package/dist/server/handlers/validate-avatar.cjs.map +1 -1
- package/dist/server/handlers/vector.cjs +2 -2
- package/dist/server/handlers/vector.js +1 -1
- package/dist/server/handlers/version-helpers.cjs +1 -0
- package/dist/server/handlers/version-helpers.cjs.map +1 -1
- package/dist/server/handlers/voice.cjs +1 -1
- package/dist/server/handlers/voice.js +1 -1
- package/dist/server/handlers/workflows.cjs +4 -4
- package/dist/server/handlers/workflows.js +3 -3
- package/dist/server/handlers/workspace.cjs +2 -2
- package/dist/server/handlers/workspace.js +1 -1
- package/dist/server/handlers.cjs +3 -2
- package/dist/server/handlers.js +2 -2
- package/dist/server/schemas/datasets.d.ts +3 -3
- package/dist/server/schemas/index.cjs +7 -6
- package/dist/server/schemas/index.js +4 -4
- package/dist/server/schemas/stored-agents.d.ts +40 -7
- package/dist/server/schemas/stored-agents.d.ts.map +1 -1
- package/dist/server/server-adapter/index.cjs +6 -5
- package/dist/server/server-adapter/index.cjs.map +1 -1
- package/dist/server/server-adapter/index.js +4 -4
- package/dist/server/server-adapter/routes/datasets.d.ts +6 -6
- package/dist/{stored-agents-CPxfYRH9.cjs → stored-agents-D6JEb3zN.cjs} +15 -3
- package/dist/stored-agents-D6JEb3zN.cjs.map +1 -0
- package/dist/{stored-agents-BRBZM-Xl.js → stored-agents-DMW5wrF7.js} +15 -3
- package/dist/stored-agents-DMW5wrF7.js.map +1 -0
- package/dist/{stored-scorers-B__LF0Cy.js → stored-scorers-BA4suzgn.js} +2 -2
- package/dist/{stored-scorers-B__LF0Cy.js.map → stored-scorers-BA4suzgn.js.map} +1 -1
- package/dist/{stored-scorers-Cml7jPJv.cjs → stored-scorers-D8IwVM0S.cjs} +2 -2
- package/dist/{stored-scorers-Cml7jPJv.cjs.map → stored-scorers-D8IwVM0S.cjs.map} +1 -1
- package/dist/{sync-djJ8Lmds.js → sync-BG15Yae1.js} +22 -22
- package/dist/{sync-djJ8Lmds.js.map → sync-BG15Yae1.js.map} +1 -1
- package/dist/{sync-BHatXKfg.cjs → sync-C4LbbSKR.cjs} +22 -22
- package/dist/{sync-BHatXKfg.cjs.map → sync-C4LbbSKR.cjs.map} +1 -1
- package/dist/{utils-CljhO7OY.js → utils-B2vd77Fi.js} +2 -2
- package/dist/{utils-CljhO7OY.js.map → utils-B2vd77Fi.js.map} +1 -1
- package/dist/{utils-BkPZAGxS.cjs → utils-CmYnjLcY.cjs} +4 -4
- package/dist/{utils-BkPZAGxS.cjs.map → utils-CmYnjLcY.cjs.map} +1 -1
- package/dist/{utils-CXbhpYYv.cjs → utils-DJMUhfvY.cjs} +3 -3
- package/dist/{utils-CXbhpYYv.cjs.map → utils-DJMUhfvY.cjs.map} +1 -1
- package/dist/{utils-qMLbyf2U.js → utils-Hz8Hc2cd.js} +2 -2
- package/dist/{utils-qMLbyf2U.js.map → utils-Hz8Hc2cd.js.map} +1 -1
- package/package.json +8 -8
- package/dist/constants-CXPpy-Ef.cjs.map +0 -1
- package/dist/constants-CutMu4A_.js.map +0 -1
- package/dist/dist-CpaK1qK1.cjs.map +0 -1
- package/dist/dist-CpxQhZED.js.map +0 -1
- package/dist/probe-image-size-C2F59z8Z.cjs.map +0 -1
- package/dist/probe-image-size-mXCWYNrz.js.map +0 -1
- package/dist/schema-DkBbires.cjs +0 -1
- package/dist/stored-agents-BRBZM-Xl.js.map +0 -1
- package/dist/stored-agents-CPxfYRH9.cjs.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const require_rolldown_runtime = require("./rolldown-runtime-
|
|
2
|
-
const require_schema_Bv9OdW1f = require("./schema-Bv9OdW1f-
|
|
3
|
-
require("./schema-
|
|
4
|
-
const require_sync$1 = require("./sync-
|
|
5
|
-
const require_dist = require("./dist-
|
|
1
|
+
const require_rolldown_runtime = require("./rolldown-runtime-Bd6kNlEP.cjs");
|
|
2
|
+
const require_schema_Bv9OdW1f = require("./schema-Bv9OdW1f-CxTiW8RD.cjs");
|
|
3
|
+
require("./schema-CNKnRmv1.cjs");
|
|
4
|
+
const require_sync$1 = require("./sync-C4LbbSKR.cjs");
|
|
5
|
+
const require_dist = require("./dist-2zVeGGHi.cjs");
|
|
6
6
|
let zod_v4 = require("zod/v4");
|
|
7
7
|
zod_v4 = require_rolldown_runtime.__toESM(zod_v4, 1);
|
|
8
8
|
let _mastra_core_schema = require("@mastra/core/schema");
|
|
@@ -23,13 +23,13 @@ let _mastra_core_request_context = require("@mastra/core/request-context");
|
|
|
23
23
|
let _mastra_core_processors = require("@mastra/core/processors");
|
|
24
24
|
let _mastra_core_workflows = require("@mastra/core/workflows");
|
|
25
25
|
let fs = require("fs");
|
|
26
|
+
let os = require("os");
|
|
26
27
|
let path = require("path");
|
|
27
28
|
let module$1 = require("module");
|
|
28
29
|
let diagnostics_channel = require("diagnostics_channel");
|
|
29
30
|
let async_hooks = require("async_hooks");
|
|
30
31
|
let child_process = require("child_process");
|
|
31
32
|
let fs_promises = require("fs/promises");
|
|
32
|
-
let os = require("os");
|
|
33
33
|
//#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/async-mutex/0.5.0/4b32f2ae13cd0d7acb694455f7c2810d59202098580506b1730c21c7ab02798f/node_modules/async-mutex/index.mjs
|
|
34
34
|
const E_CANCELED = /* @__PURE__ */ new Error("request for lock canceled");
|
|
35
35
|
var __awaiter$2 = function(thisArg, _arguments, P, generator) {
|
|
@@ -4693,7 +4693,7 @@ function splitLines(text) {
|
|
|
4693
4693
|
return result;
|
|
4694
4694
|
}
|
|
4695
4695
|
//#endregion
|
|
4696
|
-
//#region ../memory/dist/src-
|
|
4696
|
+
//#region ../memory/dist/src-aTfbkxBl.js
|
|
4697
4697
|
var __defProp$3 = Object.defineProperty;
|
|
4698
4698
|
var __exportAll = (all, no_symbols) => {
|
|
4699
4699
|
let target = {};
|
|
@@ -19240,6 +19240,2388 @@ createIdGenerator$3({
|
|
|
19240
19240
|
prefix: "aiobj",
|
|
19241
19241
|
size: 24
|
|
19242
19242
|
});
|
|
19243
|
+
const BUILT_IN_SLUGS = /* @__PURE__ */ new Set([
|
|
19244
|
+
"current-task",
|
|
19245
|
+
"suggested-response",
|
|
19246
|
+
"thread-title"
|
|
19247
|
+
]);
|
|
19248
|
+
const EXTRACTED_VALUES_TAG = "extracted-values";
|
|
19249
|
+
const RESERVED_XML_TAGS = /* @__PURE__ */ new Set([
|
|
19250
|
+
"observations",
|
|
19251
|
+
"observation",
|
|
19252
|
+
EXTRACTED_VALUES_TAG,
|
|
19253
|
+
"thread",
|
|
19254
|
+
"message",
|
|
19255
|
+
"messages",
|
|
19256
|
+
"conversation",
|
|
19257
|
+
"history",
|
|
19258
|
+
"system",
|
|
19259
|
+
"user",
|
|
19260
|
+
"assistant",
|
|
19261
|
+
"tool",
|
|
19262
|
+
...BUILT_IN_SLUGS
|
|
19263
|
+
]);
|
|
19264
|
+
const BUILT_IN_EXTRACTOR_SLUGS = [...BUILT_IN_SLUGS];
|
|
19265
|
+
function isBuiltInExtractorSlug(slug) {
|
|
19266
|
+
return BUILT_IN_SLUGS.has(slug);
|
|
19267
|
+
}
|
|
19268
|
+
function slugifyExtractorName(name) {
|
|
19269
|
+
let normalized = "";
|
|
19270
|
+
let previousWasSeparator = false;
|
|
19271
|
+
for (const char of name.trim().toLowerCase()) {
|
|
19272
|
+
const code = char.charCodeAt(0);
|
|
19273
|
+
if (code >= 97 && code <= 122 || code >= 48 && code <= 57) {
|
|
19274
|
+
normalized += char;
|
|
19275
|
+
previousWasSeparator = false;
|
|
19276
|
+
continue;
|
|
19277
|
+
}
|
|
19278
|
+
if (char === "'" || char === "\"" || char === "`") continue;
|
|
19279
|
+
if (!previousWasSeparator && normalized.length > 0) {
|
|
19280
|
+
normalized += "-";
|
|
19281
|
+
previousWasSeparator = true;
|
|
19282
|
+
}
|
|
19283
|
+
}
|
|
19284
|
+
return normalized.endsWith("-") ? normalized.slice(0, -1) : normalized;
|
|
19285
|
+
}
|
|
19286
|
+
function assertValidSlug(slug, name) {
|
|
19287
|
+
if (!slug) throw new Error(`Extractor name "${name}" must produce a non-empty slug.`);
|
|
19288
|
+
const first = slug.charCodeAt(0);
|
|
19289
|
+
const last = slug.charCodeAt(slug.length - 1);
|
|
19290
|
+
const startsWithLetter = first >= 97 && first <= 122;
|
|
19291
|
+
const endsWithLetterOrNumber = last >= 97 && last <= 122 || last >= 48 && last <= 57;
|
|
19292
|
+
const hasOnlySlugCharacters = [...slug].every((char) => {
|
|
19293
|
+
const code = char.charCodeAt(0);
|
|
19294
|
+
return code >= 97 && code <= 122 || code >= 48 && code <= 57 || char === "-";
|
|
19295
|
+
});
|
|
19296
|
+
if (!startsWithLetter || !endsWithLetterOrNumber || !hasOnlySlugCharacters) throw new Error(`Extractor name "${name}" produced invalid slug "${slug}".`);
|
|
19297
|
+
}
|
|
19298
|
+
var Extractor = class Extractor {
|
|
19299
|
+
name;
|
|
19300
|
+
slug;
|
|
19301
|
+
instructions;
|
|
19302
|
+
schema;
|
|
19303
|
+
mode;
|
|
19304
|
+
includePreviousExtraction;
|
|
19305
|
+
metadataKeyPath;
|
|
19306
|
+
onExtracted;
|
|
19307
|
+
retryStructuredExtractionOnEmptyObject;
|
|
19308
|
+
/** @internal */
|
|
19309
|
+
internal;
|
|
19310
|
+
instructionsConfig;
|
|
19311
|
+
schemaConfig;
|
|
19312
|
+
constructor(config, internal = false) {
|
|
19313
|
+
const name = config.name.trim();
|
|
19314
|
+
const instructions = typeof config.instructions === "string" ? config.instructions.trim() : void 0;
|
|
19315
|
+
const slug = slugifyExtractorName(name);
|
|
19316
|
+
const isHook = config.mode === "hook";
|
|
19317
|
+
if (!name) throw new Error("Extractor name is required.");
|
|
19318
|
+
if (!isHook && !config.instructions) throw new Error(`Extractor "${name}" must include instructions.`);
|
|
19319
|
+
if (instructions !== void 0 && !instructions) throw new Error(`Extractor "${name}" must include instructions.`);
|
|
19320
|
+
if (isHook && !config.onExtracted) throw new Error(`Hook extractor "${name}" must include an onExtracted handler.`);
|
|
19321
|
+
if (isHook && (config.instructions || config.schema)) throw new Error(`Hook extractor "${name}" cannot include instructions or a schema.`);
|
|
19322
|
+
assertValidSlug(slug, name);
|
|
19323
|
+
if (!internal && RESERVED_XML_TAGS.has(slug)) throw new Error(`Extractor slug "${slug}" is reserved by Observational Memory.`);
|
|
19324
|
+
this.name = name;
|
|
19325
|
+
this.slug = slug;
|
|
19326
|
+
this.instructionsConfig = config.instructions ?? "";
|
|
19327
|
+
this.schemaConfig = config.schema;
|
|
19328
|
+
this.instructions = instructions ?? "";
|
|
19329
|
+
this.schema = isHook ? zod.z.unknown() : typeof config.schema === "function" ? zod.z.string() : config.schema ?? zod.z.string();
|
|
19330
|
+
this.mode = isHook ? "hook" : internal || !config.schema ? "inline" : "structured";
|
|
19331
|
+
this.includePreviousExtraction = isHook ? false : config.includePreviousExtraction ?? true;
|
|
19332
|
+
this.metadataKeyPath = isHook ? false : config.metadataKeyPath ?? `extracted.${slug}`;
|
|
19333
|
+
this.onExtracted = config.onExtracted;
|
|
19334
|
+
this.retryStructuredExtractionOnEmptyObject = config.retryStructuredExtractionOnEmptyObject ?? false;
|
|
19335
|
+
this.internal = internal;
|
|
19336
|
+
}
|
|
19337
|
+
async resolve(context) {
|
|
19338
|
+
if (this.mode === "hook") return this;
|
|
19339
|
+
const instructions = typeof this.instructionsConfig === "function" ? (await this.instructionsConfig(context)).trim() : this.instructionsConfig.trim();
|
|
19340
|
+
if (!instructions) throw new Error(`Extractor "${this.name}" must include instructions.`);
|
|
19341
|
+
const schema = typeof this.schemaConfig === "function" ? await this.schemaConfig(context) : this.schemaConfig;
|
|
19342
|
+
return new Extractor({
|
|
19343
|
+
name: this.name,
|
|
19344
|
+
instructions,
|
|
19345
|
+
...schema ? { schema } : {},
|
|
19346
|
+
includePreviousExtraction: this.includePreviousExtraction,
|
|
19347
|
+
metadataKeyPath: this.metadataKeyPath,
|
|
19348
|
+
onExtracted: this.onExtracted,
|
|
19349
|
+
retryStructuredExtractionOnEmptyObject: this.retryStructuredExtractionOnEmptyObject
|
|
19350
|
+
}, this.internal);
|
|
19351
|
+
}
|
|
19352
|
+
};
|
|
19353
|
+
async function resolveExtractors(extractors, context) {
|
|
19354
|
+
return Promise.all(extractors.map((extractor) => extractor.resolve(context)));
|
|
19355
|
+
}
|
|
19356
|
+
function validateExtractorList(extractors) {
|
|
19357
|
+
const seen = /* @__PURE__ */ new Map();
|
|
19358
|
+
for (const extractor of extractors) {
|
|
19359
|
+
assertValidSlug(extractor.slug, extractor.name);
|
|
19360
|
+
if (!extractor.internal && RESERVED_XML_TAGS.has(extractor.slug)) throw new Error(`Extractor slug "${extractor.slug}" is reserved by Observational Memory.`);
|
|
19361
|
+
const previous = seen.get(extractor.slug);
|
|
19362
|
+
if (previous) throw new Error(`Duplicate extractor slug "${extractor.slug}" from "${previous}" and "${extractor.name}".`);
|
|
19363
|
+
seen.set(extractor.slug, extractor.name);
|
|
19364
|
+
}
|
|
19365
|
+
return [...extractors];
|
|
19366
|
+
}
|
|
19367
|
+
function isJsonLike(value) {
|
|
19368
|
+
return /^(?:[\[{"-]|\d|true\b|false\b|null\b)/.test(value.trim());
|
|
19369
|
+
}
|
|
19370
|
+
function candidateValues(raw) {
|
|
19371
|
+
const trimmed = raw.trim();
|
|
19372
|
+
const candidates = [];
|
|
19373
|
+
const add = (value) => {
|
|
19374
|
+
if (!candidates.some((candidate) => Object.is(candidate, value))) candidates.push(value);
|
|
19375
|
+
};
|
|
19376
|
+
if (isJsonLike(trimmed)) try {
|
|
19377
|
+
add(JSON.parse(trimmed));
|
|
19378
|
+
} catch {}
|
|
19379
|
+
add(trimmed);
|
|
19380
|
+
if (!isJsonLike(trimmed)) try {
|
|
19381
|
+
add(JSON.parse(trimmed));
|
|
19382
|
+
} catch {}
|
|
19383
|
+
return candidates;
|
|
19384
|
+
}
|
|
19385
|
+
function parseExtractorValue(extractor, raw) {
|
|
19386
|
+
const failures = [];
|
|
19387
|
+
for (const candidate of candidateValues(raw)) {
|
|
19388
|
+
const parsed = extractor.schema.safeParse(candidate);
|
|
19389
|
+
if (parsed.success) return parsed.data;
|
|
19390
|
+
failures.push(parsed.error.message);
|
|
19391
|
+
}
|
|
19392
|
+
throw new Error(`Extractor "${extractor.slug}" output did not match its schema: ${failures[0] ?? "invalid value"}`);
|
|
19393
|
+
}
|
|
19394
|
+
function parseExtractedValuesObject(raw) {
|
|
19395
|
+
const trimmed = raw.trim();
|
|
19396
|
+
if (!trimmed || trimmed.startsWith("Write only the extracted values JSON object here.")) return;
|
|
19397
|
+
const parsed = JSON.parse(trimmed);
|
|
19398
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`${EXTRACTED_VALUES_TAG} must contain a JSON object.`);
|
|
19399
|
+
return parsed;
|
|
19400
|
+
}
|
|
19401
|
+
function parseExtractedValues(output, extractors) {
|
|
19402
|
+
const values = {};
|
|
19403
|
+
const failures = [];
|
|
19404
|
+
const inlineExtractors = extractors.filter((extractor) => extractor.mode === "inline");
|
|
19405
|
+
const regex = new RegExp(`<${EXTRACTED_VALUES_TAG}>([\\s\\S]*?)<\\/${EXTRACTED_VALUES_TAG}>`, "gi");
|
|
19406
|
+
const matches = [...output.matchAll(regex)];
|
|
19407
|
+
for (const match of matches) try {
|
|
19408
|
+
const extractedValues = parseExtractedValuesObject(match[1] ?? "");
|
|
19409
|
+
if (!extractedValues) continue;
|
|
19410
|
+
for (const extractor of inlineExtractors) {
|
|
19411
|
+
if (!Object.prototype.hasOwnProperty.call(extractedValues, extractor.slug)) continue;
|
|
19412
|
+
const rawValue = extractedValues[extractor.slug];
|
|
19413
|
+
if (rawValue === void 0 || rawValue === null || rawValue === "") continue;
|
|
19414
|
+
const parsed = extractor.schema.safeParse(rawValue);
|
|
19415
|
+
if (parsed.success) values[extractor.slug] = parsed.data;
|
|
19416
|
+
else failures.push({
|
|
19417
|
+
slug: extractor.slug,
|
|
19418
|
+
error: parsed.error.message
|
|
19419
|
+
});
|
|
19420
|
+
}
|
|
19421
|
+
} catch (error) {
|
|
19422
|
+
failures.push({
|
|
19423
|
+
slug: EXTRACTED_VALUES_TAG,
|
|
19424
|
+
error: error instanceof Error ? error.message : String(error)
|
|
19425
|
+
});
|
|
19426
|
+
}
|
|
19427
|
+
for (const extractor of inlineExtractors) {
|
|
19428
|
+
if (Object.prototype.hasOwnProperty.call(values, extractor.slug)) continue;
|
|
19429
|
+
const tagRegex = new RegExp(`<${extractor.slug}>([\\s\\S]*?)<\\/${extractor.slug}>`, "gi");
|
|
19430
|
+
const rawValue = [...output.matchAll(tagRegex)].at(-1)?.[1]?.trim();
|
|
19431
|
+
if (!rawValue) continue;
|
|
19432
|
+
try {
|
|
19433
|
+
values[extractor.slug] = parseExtractorValue(extractor, rawValue);
|
|
19434
|
+
} catch (error) {
|
|
19435
|
+
failures.push({
|
|
19436
|
+
slug: extractor.slug,
|
|
19437
|
+
error: error instanceof Error ? error.message : String(error)
|
|
19438
|
+
});
|
|
19439
|
+
}
|
|
19440
|
+
}
|
|
19441
|
+
return {
|
|
19442
|
+
values,
|
|
19443
|
+
failures
|
|
19444
|
+
};
|
|
19445
|
+
}
|
|
19446
|
+
function stripExtractorSections(output, extractors) {
|
|
19447
|
+
const inlineExtractors = extractors.filter((extractor) => extractor.mode === "inline");
|
|
19448
|
+
let stripped = output.replace(new RegExp(`[ \\t]*<${EXTRACTED_VALUES_TAG}>[\\s\\S]*?<\\/${EXTRACTED_VALUES_TAG}>\\s*`, "gi"), "");
|
|
19449
|
+
for (const extractor of inlineExtractors) stripped = stripped.replace(new RegExp(`[ \\t]*<${extractor.slug}>[\\s\\S]*?<\\/${extractor.slug}>\\s*`, "gi"), "");
|
|
19450
|
+
return stripped;
|
|
19451
|
+
}
|
|
19452
|
+
function buildExtractorOutputSections(extractors) {
|
|
19453
|
+
const inlineExtractors = extractors.filter((extractor) => extractor.mode === "inline");
|
|
19454
|
+
if (inlineExtractors.length === 0) return "";
|
|
19455
|
+
return `Additional optional XML sections:\nIf the observations include information relevant to any of these tags, output that tag after <observations> and include the relevant information.\n${inlineExtractors.map((extractor) => `<${extractor.slug}>
|
|
19456
|
+
${extractor.instructions}
|
|
19457
|
+
Include this section when the observations contain relevant information for <${extractor.slug}>. Write only that information inside the tag.
|
|
19458
|
+
</${extractor.slug}>`).join("\n\n")}`;
|
|
19459
|
+
}
|
|
19460
|
+
function renderPriorValue(value) {
|
|
19461
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
19462
|
+
}
|
|
19463
|
+
function buildExtractorPriorLines(extractors, priorExtractedValues) {
|
|
19464
|
+
if (!priorExtractedValues) return [];
|
|
19465
|
+
const lines = [];
|
|
19466
|
+
for (const extractor of extractors) {
|
|
19467
|
+
if (!extractor.includePreviousExtraction) continue;
|
|
19468
|
+
const value = priorExtractedValues[extractor.slug];
|
|
19469
|
+
if (value === void 0 || value === null || value === "") continue;
|
|
19470
|
+
lines.push(`<${extractor.slug}>\n${renderPriorValue(value)}\n</${extractor.slug}>`);
|
|
19471
|
+
}
|
|
19472
|
+
return lines;
|
|
19473
|
+
}
|
|
19474
|
+
const SUBCONSCIOUS_ACTIVITY_STATE_ID = "subconscious-activity";
|
|
19475
|
+
async function getActivityTarget(store, event, scope) {
|
|
19476
|
+
if (event.recordType === "node") {
|
|
19477
|
+
const node = await store.getNode(event.recordId);
|
|
19478
|
+
if (!node || !(0, _mastra_core_storage.isKnowledgeScopeVisible)(node.scope, scope)) return {
|
|
19479
|
+
id: event.recordId,
|
|
19480
|
+
type: "node"
|
|
19481
|
+
};
|
|
19482
|
+
return {
|
|
19483
|
+
id: node.id,
|
|
19484
|
+
name: node.name,
|
|
19485
|
+
type: "node"
|
|
19486
|
+
};
|
|
19487
|
+
}
|
|
19488
|
+
const record = await store.getKnowledge({
|
|
19489
|
+
id: event.recordId,
|
|
19490
|
+
includeDeleted: true
|
|
19491
|
+
});
|
|
19492
|
+
const node = record ? await store.getNode(record.node) : void 0;
|
|
19493
|
+
if (!node || !(0, _mastra_core_storage.isKnowledgeScopeVisible)(node.scope, scope)) return {
|
|
19494
|
+
id: event.recordId,
|
|
19495
|
+
type: "node"
|
|
19496
|
+
};
|
|
19497
|
+
return {
|
|
19498
|
+
id: node.id,
|
|
19499
|
+
name: node.name,
|
|
19500
|
+
type: "node"
|
|
19501
|
+
};
|
|
19502
|
+
}
|
|
19503
|
+
async function buildSubconsciousActivitySnapshot(input) {
|
|
19504
|
+
const events = await input.store.listActivity({
|
|
19505
|
+
scope: input.scope,
|
|
19506
|
+
limit: input.recentUpdates
|
|
19507
|
+
});
|
|
19508
|
+
const resolvedUpdates = await Promise.all(events.map(async (event) => {
|
|
19509
|
+
const target = await getActivityTarget(input.store, event, input.scope);
|
|
19510
|
+
return {
|
|
19511
|
+
action: event.action,
|
|
19512
|
+
type: event.recordType,
|
|
19513
|
+
name: target.name,
|
|
19514
|
+
targetId: target.id,
|
|
19515
|
+
targetType: target.type,
|
|
19516
|
+
createdAt: event.createdAt.toISOString()
|
|
19517
|
+
};
|
|
19518
|
+
}));
|
|
19519
|
+
const hotByRecord = /* @__PURE__ */ new Map();
|
|
19520
|
+
for (const update of resolvedUpdates) {
|
|
19521
|
+
if (!update.name) continue;
|
|
19522
|
+
const key = `${update.targetType}:${update.targetId}`;
|
|
19523
|
+
const existing = hotByRecord.get(key);
|
|
19524
|
+
if (existing) existing.updates += 1;
|
|
19525
|
+
else hotByRecord.set(key, {
|
|
19526
|
+
type: update.targetType,
|
|
19527
|
+
name: update.name,
|
|
19528
|
+
updates: 1
|
|
19529
|
+
});
|
|
19530
|
+
}
|
|
19531
|
+
const hot = [...hotByRecord.values()].sort((a, b) => b.updates - a.updates || a.name.localeCompare(b.name)).slice(0, input.recentUpdates);
|
|
19532
|
+
const updates = resolvedUpdates.map((update) => ({
|
|
19533
|
+
action: update.action,
|
|
19534
|
+
type: update.type,
|
|
19535
|
+
...update.name ? { name: update.name } : {},
|
|
19536
|
+
createdAt: update.createdAt
|
|
19537
|
+
}));
|
|
19538
|
+
const errors = input.errors?.filter(Boolean).slice(0, input.recentUpdates);
|
|
19539
|
+
return {
|
|
19540
|
+
updates,
|
|
19541
|
+
hot,
|
|
19542
|
+
...errors?.length ? { errors } : {}
|
|
19543
|
+
};
|
|
19544
|
+
}
|
|
19545
|
+
function renderSubconsciousActivity(snapshot) {
|
|
19546
|
+
const lines = snapshot.updates.map((update) => {
|
|
19547
|
+
const target = update.name ? `${update.type} [[${update.name}]]` : update.type;
|
|
19548
|
+
return `- ${update.action}: ${target}`;
|
|
19549
|
+
});
|
|
19550
|
+
const hot = snapshot.hot.map((record) => `[[${record.name}]] (${record.updates})`).join(", ");
|
|
19551
|
+
return [
|
|
19552
|
+
hot ? `Hot: ${hot}` : "Hot: none",
|
|
19553
|
+
"Recent updates:",
|
|
19554
|
+
...lines.length ? lines : ["- none"],
|
|
19555
|
+
...snapshot.errors?.length ? ["Errors:", ...snapshot.errors.map((error) => `- ${error}`)] : []
|
|
19556
|
+
].join("\n");
|
|
19557
|
+
}
|
|
19558
|
+
async function publishSubconsciousError(input) {
|
|
19559
|
+
await input.writer?.custom({
|
|
19560
|
+
type: "data-subconscious-error",
|
|
19561
|
+
data: {
|
|
19562
|
+
error: input.error,
|
|
19563
|
+
agent: input.agent
|
|
19564
|
+
}
|
|
19565
|
+
});
|
|
19566
|
+
if (!input.sendStateSignal) return;
|
|
19567
|
+
const snapshot = {
|
|
19568
|
+
updates: [],
|
|
19569
|
+
hot: [],
|
|
19570
|
+
errors: [input.error]
|
|
19571
|
+
};
|
|
19572
|
+
const contents = renderSubconsciousActivity(snapshot);
|
|
19573
|
+
await input.sendStateSignal({
|
|
19574
|
+
id: SUBCONSCIOUS_ACTIVITY_STATE_ID,
|
|
19575
|
+
mode: "snapshot",
|
|
19576
|
+
cacheKey: (0, crypto$1.createHash)("sha256").update(contents).digest("hex"),
|
|
19577
|
+
tagName: "state",
|
|
19578
|
+
attributes: { id: SUBCONSCIOUS_ACTIVITY_STATE_ID },
|
|
19579
|
+
metadata: { origin: "subconscious" },
|
|
19580
|
+
contents,
|
|
19581
|
+
value: snapshot
|
|
19582
|
+
});
|
|
19583
|
+
}
|
|
19584
|
+
async function publishSubconsciousActivity(input) {
|
|
19585
|
+
if (!input.sendStateSignal) return void 0;
|
|
19586
|
+
const snapshot = await buildSubconsciousActivitySnapshot(input);
|
|
19587
|
+
const contents = renderSubconsciousActivity(snapshot);
|
|
19588
|
+
const cacheKey = (0, crypto$1.createHash)("sha256").update(contents).digest("hex");
|
|
19589
|
+
await input.sendStateSignal({
|
|
19590
|
+
id: SUBCONSCIOUS_ACTIVITY_STATE_ID,
|
|
19591
|
+
mode: "snapshot",
|
|
19592
|
+
cacheKey,
|
|
19593
|
+
tagName: "state",
|
|
19594
|
+
attributes: { id: SUBCONSCIOUS_ACTIVITY_STATE_ID },
|
|
19595
|
+
metadata: { origin: "subconscious" },
|
|
19596
|
+
contents,
|
|
19597
|
+
value: snapshot
|
|
19598
|
+
});
|
|
19599
|
+
return snapshot;
|
|
19600
|
+
}
|
|
19601
|
+
/** Processor id and state-signal id for the pinned-knowledge lane. */
|
|
19602
|
+
const SUBCONSCIOUS_PINS_STATE_ID = "subconscious-pins";
|
|
19603
|
+
/** Snapshot tag the model sees; the delta tag appends `-update`. */
|
|
19604
|
+
const PINNED_SNAPSHOT_TAG = "pinned-knowledge";
|
|
19605
|
+
const PINNED_DELTA_TAG = "pinned-knowledge-update";
|
|
19606
|
+
/** Reserved node holding the pin set. One record, at one fixed scope level. */
|
|
19607
|
+
const PINNED_NODE_NAME = "pinned";
|
|
19608
|
+
const PINNED_NODE_KIND = "system";
|
|
19609
|
+
const PINNED_NODE_SCOPE_LEVEL = "resource";
|
|
19610
|
+
const DEFAULT_PINNED_MAX_CHARACTERS = 2e3;
|
|
19611
|
+
const MAX_PINNED_MAX_CHARACTERS = 8e3;
|
|
19612
|
+
const PIN_IDENTITY = "subconscious:pin";
|
|
19613
|
+
function pinnedNodeScope(scope, maxScope) {
|
|
19614
|
+
return (0, _mastra_core_storage.expandKnowledgeScope)(scope, maxScope === "thread" ? "thread" : PINNED_NODE_SCOPE_LEVEL);
|
|
19615
|
+
}
|
|
19616
|
+
async function resolvePinnedNodeId(store, scope) {
|
|
19617
|
+
return (await store.resolveNode({
|
|
19618
|
+
name: PINNED_NODE_NAME,
|
|
19619
|
+
scope
|
|
19620
|
+
}))?.id;
|
|
19621
|
+
}
|
|
19622
|
+
/** Reuse the node wherever it is visible; otherwise create it. `createNode` is an idempotent upsert on (name, scope). */
|
|
19623
|
+
async function ensurePinnedNodeId(store, scope, maxScope) {
|
|
19624
|
+
const existing = await resolvePinnedNodeId(store, scope);
|
|
19625
|
+
if (existing) return existing;
|
|
19626
|
+
return (await store.createNode({
|
|
19627
|
+
name: PINNED_NODE_NAME,
|
|
19628
|
+
kind: PINNED_NODE_KIND,
|
|
19629
|
+
scope: pinnedNodeScope(scope, maxScope)
|
|
19630
|
+
})).id;
|
|
19631
|
+
}
|
|
19632
|
+
/**
|
|
19633
|
+
* Assembles the current pin set.
|
|
19634
|
+
*
|
|
19635
|
+
* Reads use the FULL visible scope context, never a level-narrowed write scope: visibility is
|
|
19636
|
+
* subset containment, so querying at the node's level would drop pins written at narrower
|
|
19637
|
+
* levels. Deleted records are excluded explicitly.
|
|
19638
|
+
*/
|
|
19639
|
+
async function listPinnedKnowledge(input) {
|
|
19640
|
+
const nodeId = await resolvePinnedNodeId(input.store, input.scope);
|
|
19641
|
+
if (!nodeId) return { pins: [] };
|
|
19642
|
+
const pins = [];
|
|
19643
|
+
let after;
|
|
19644
|
+
do {
|
|
19645
|
+
const page = await input.store.listKnowledgeAbout({
|
|
19646
|
+
node: nodeId,
|
|
19647
|
+
scope: input.scope,
|
|
19648
|
+
after,
|
|
19649
|
+
includeDeleted: false
|
|
19650
|
+
});
|
|
19651
|
+
pins.push(...page.records);
|
|
19652
|
+
after = page.nextCursor;
|
|
19653
|
+
} while (after);
|
|
19654
|
+
return {
|
|
19655
|
+
nodeId,
|
|
19656
|
+
pins
|
|
19657
|
+
};
|
|
19658
|
+
}
|
|
19659
|
+
function totalCharacters(pins) {
|
|
19660
|
+
return pins.reduce((sum, pin) => sum + pin.text.length, 0);
|
|
19661
|
+
}
|
|
19662
|
+
function assertBudget(options, pins, incomingText, replacing) {
|
|
19663
|
+
const kept = replacing ? pins.filter((pin) => pin.id !== replacing.id) : pins;
|
|
19664
|
+
if (!replacing && kept.length >= options.maxPins) throw new Error(`Pin limit reached: the set holds at most ${options.maxPins}. Unpin something first.`);
|
|
19665
|
+
if (totalCharacters(kept) + incomingText.length > options.maxCharacters) throw new Error(`Pin budget exceeded: the pin set is limited to ${options.maxCharacters} characters in total.`);
|
|
19666
|
+
}
|
|
19667
|
+
function clampPinLevel(level) {
|
|
19668
|
+
return level === "org" ? "resource" : level;
|
|
19669
|
+
}
|
|
19670
|
+
function resolveWriteScope$1(options, level) {
|
|
19671
|
+
let effective = clampPinLevel(level ?? options.defaultScope);
|
|
19672
|
+
if (!level && options.maxScope === "thread") effective = "thread";
|
|
19673
|
+
const scope = (0, _mastra_core_storage.expandKnowledgeScope)(options.scope, effective);
|
|
19674
|
+
(0, _mastra_core_storage.assertKnowledgeScopeWithinCeiling)(scope, options.maxScope);
|
|
19675
|
+
return scope;
|
|
19676
|
+
}
|
|
19677
|
+
const scopeLevelSchema$1 = {
|
|
19678
|
+
type: "string",
|
|
19679
|
+
enum: ["resource", "thread"]
|
|
19680
|
+
};
|
|
19681
|
+
/** Shared pin write path used by the tool and capture-time pinning. */
|
|
19682
|
+
async function writePinnedKnowledge(store, options, text, level, metadata) {
|
|
19683
|
+
const { pins } = await listPinnedKnowledge({
|
|
19684
|
+
store,
|
|
19685
|
+
scope: options.scope
|
|
19686
|
+
});
|
|
19687
|
+
assertBudget(options, pins, text);
|
|
19688
|
+
const nodeId = await ensurePinnedNodeId(store, options.scope, options.maxScope);
|
|
19689
|
+
return store.appendKnowledge({
|
|
19690
|
+
node: nodeId,
|
|
19691
|
+
text,
|
|
19692
|
+
scope: resolveWriteScope$1(options, level),
|
|
19693
|
+
sourceThreadId: options.sourceThreadId,
|
|
19694
|
+
maxScope: options.maxScope,
|
|
19695
|
+
metadata,
|
|
19696
|
+
resolutionScope: options.scope,
|
|
19697
|
+
defaultScope: (0, _mastra_core_storage.expandKnowledgeScope)(options.scope, options.defaultScope)
|
|
19698
|
+
});
|
|
19699
|
+
}
|
|
19700
|
+
async function getStore$1(memory) {
|
|
19701
|
+
const store = await memory.storage.getStore("knowledge");
|
|
19702
|
+
if (!store) throw new Error("Pinned knowledge requires a configured knowledge storage domain.");
|
|
19703
|
+
return store;
|
|
19704
|
+
}
|
|
19705
|
+
async function requirePin(store, recordId, options) {
|
|
19706
|
+
const record = await store.getKnowledge({
|
|
19707
|
+
id: recordId,
|
|
19708
|
+
includeDeleted: false
|
|
19709
|
+
});
|
|
19710
|
+
if (!record) throw new Error(`Pin not found: ${recordId}`);
|
|
19711
|
+
const nodeId = await resolvePinnedNodeId(store, options.scope);
|
|
19712
|
+
if (!nodeId || record.node !== nodeId) throw new Error(`Record is not a pin: ${recordId}`);
|
|
19713
|
+
if (!(0, _mastra_core_storage.isKnowledgeScopeVisible)(record.scope, options.scope)) throw new Error("Pin is outside the visible scope.");
|
|
19714
|
+
return record;
|
|
19715
|
+
}
|
|
19716
|
+
/**
|
|
19717
|
+
* Pin lifecycle tools. Pin appends a record on the reserved node; unpin soft-deletes it
|
|
19718
|
+
* (auditable, restorable); edit is remove plus append because knowledge records are immutable,
|
|
19719
|
+
* so an edited pin carries a new record id.
|
|
19720
|
+
*/
|
|
19721
|
+
function createPinnedTools(memory, options) {
|
|
19722
|
+
return {
|
|
19723
|
+
knowledge_pin: (0, _mastra_core_tools.createTool)({
|
|
19724
|
+
id: "knowledge_pin",
|
|
19725
|
+
description: "Pin knowledge that must stay in context every turn without being asked for. Pins cost context permanently; pin only what is unconditionally relevant.",
|
|
19726
|
+
inputSchema: {
|
|
19727
|
+
type: "object",
|
|
19728
|
+
properties: {
|
|
19729
|
+
text: {
|
|
19730
|
+
type: "string",
|
|
19731
|
+
minLength: 1
|
|
19732
|
+
},
|
|
19733
|
+
scope: scopeLevelSchema$1,
|
|
19734
|
+
reason: {
|
|
19735
|
+
type: "string",
|
|
19736
|
+
minLength: 1,
|
|
19737
|
+
description: "One short sentence: why this must stay in context permanently."
|
|
19738
|
+
}
|
|
19739
|
+
},
|
|
19740
|
+
required: ["text"],
|
|
19741
|
+
additionalProperties: false
|
|
19742
|
+
},
|
|
19743
|
+
execute: async (input) => {
|
|
19744
|
+
const value = input;
|
|
19745
|
+
return writePinnedKnowledge(await getStore$1(memory), options, value.text, value.scope, value.reason ? { reason: value.reason } : void 0);
|
|
19746
|
+
}
|
|
19747
|
+
}),
|
|
19748
|
+
knowledge_unpin: (0, _mastra_core_tools.createTool)({
|
|
19749
|
+
id: "knowledge_unpin",
|
|
19750
|
+
description: "Remove a pin. The underlying knowledge record is soft-deleted and drops out of the pinned context.",
|
|
19751
|
+
inputSchema: {
|
|
19752
|
+
type: "object",
|
|
19753
|
+
properties: { recordId: {
|
|
19754
|
+
type: "string",
|
|
19755
|
+
minLength: 1
|
|
19756
|
+
} },
|
|
19757
|
+
required: ["recordId"],
|
|
19758
|
+
additionalProperties: false
|
|
19759
|
+
},
|
|
19760
|
+
execute: async (input) => {
|
|
19761
|
+
const store = await getStore$1(memory);
|
|
19762
|
+
const record = await requirePin(store, input.recordId, options);
|
|
19763
|
+
return store.removeKnowledge({
|
|
19764
|
+
id: record.id,
|
|
19765
|
+
deletedBy: PIN_IDENTITY
|
|
19766
|
+
});
|
|
19767
|
+
}
|
|
19768
|
+
}),
|
|
19769
|
+
knowledge_edit_pin: (0, _mastra_core_tools.createTool)({
|
|
19770
|
+
id: "knowledge_edit_pin",
|
|
19771
|
+
description: "Replace the text of an existing pin. The replacement carries a new knowledge record id.",
|
|
19772
|
+
inputSchema: {
|
|
19773
|
+
type: "object",
|
|
19774
|
+
properties: {
|
|
19775
|
+
recordId: {
|
|
19776
|
+
type: "string",
|
|
19777
|
+
minLength: 1
|
|
19778
|
+
},
|
|
19779
|
+
text: {
|
|
19780
|
+
type: "string",
|
|
19781
|
+
minLength: 1
|
|
19782
|
+
},
|
|
19783
|
+
reason: {
|
|
19784
|
+
type: "string",
|
|
19785
|
+
minLength: 1,
|
|
19786
|
+
description: "One short sentence: why this must stay in context permanently."
|
|
19787
|
+
}
|
|
19788
|
+
},
|
|
19789
|
+
required: ["recordId", "text"],
|
|
19790
|
+
additionalProperties: false
|
|
19791
|
+
},
|
|
19792
|
+
execute: async (input) => {
|
|
19793
|
+
const value = input;
|
|
19794
|
+
const store = await getStore$1(memory);
|
|
19795
|
+
const record = await requirePin(store, value.recordId, options);
|
|
19796
|
+
const { pins } = await listPinnedKnowledge({
|
|
19797
|
+
store,
|
|
19798
|
+
scope: options.scope
|
|
19799
|
+
});
|
|
19800
|
+
assertBudget(options, pins, value.text, record);
|
|
19801
|
+
await store.removeKnowledge({
|
|
19802
|
+
id: record.id,
|
|
19803
|
+
deletedBy: PIN_IDENTITY
|
|
19804
|
+
});
|
|
19805
|
+
return store.appendKnowledge({
|
|
19806
|
+
node: record.node,
|
|
19807
|
+
text: value.text,
|
|
19808
|
+
scope: record.scope,
|
|
19809
|
+
sourceThreadId: options.sourceThreadId,
|
|
19810
|
+
maxScope: record.maxScope,
|
|
19811
|
+
metadata: value.reason ? {
|
|
19812
|
+
...record.metadata,
|
|
19813
|
+
reason: value.reason
|
|
19814
|
+
} : record.metadata,
|
|
19815
|
+
resolutionScope: options.scope,
|
|
19816
|
+
defaultScope: (0, _mastra_core_storage.expandKnowledgeScope)(options.scope, options.defaultScope)
|
|
19817
|
+
});
|
|
19818
|
+
}
|
|
19819
|
+
})
|
|
19820
|
+
};
|
|
19821
|
+
}
|
|
19822
|
+
/**
|
|
19823
|
+
* Resolves the resource rung of a subconscious knowledge scope.
|
|
19824
|
+
*
|
|
19825
|
+
* When the request context carries a `knowledgeResourceId` override, every
|
|
19826
|
+
* scope resolver anchors the resource rung on it instead of the run's
|
|
19827
|
+
* resourceId. This lets a host (for example, the factory) share one knowledge
|
|
19828
|
+
* graph across many runs of the same project while leaving thread identity and
|
|
19829
|
+
* observational memory untouched. Without the override, behavior is unchanged:
|
|
19830
|
+
* the fallback (the run's resourceId) is used as-is.
|
|
19831
|
+
*/
|
|
19832
|
+
function resolveKnowledgeResourceId(requestContext, fallback) {
|
|
19833
|
+
const override = requestContext?.get?.("knowledgeResourceId");
|
|
19834
|
+
if (typeof override === "string" && override.trim()) return override;
|
|
19835
|
+
return fallback;
|
|
19836
|
+
}
|
|
19837
|
+
const CAPTURE_GUIDANCE_PAGE = "capture-guidance";
|
|
19838
|
+
const MAX_CAPTURE_GUIDANCE_LENGTH = 4e3;
|
|
19839
|
+
const SCOPE_ORDER = {
|
|
19840
|
+
org: 0,
|
|
19841
|
+
resource: 1,
|
|
19842
|
+
thread: 2
|
|
19843
|
+
};
|
|
19844
|
+
const subconsciousCaptureSchema = zod.z.object({ nodes: zod.z.array(zod.z.object({
|
|
19845
|
+
name: zod.z.string().trim().min(1),
|
|
19846
|
+
kind: zod.z.string().trim().min(1),
|
|
19847
|
+
scope: zod.z.enum([
|
|
19848
|
+
"org",
|
|
19849
|
+
"resource",
|
|
19850
|
+
"thread"
|
|
19851
|
+
]).optional(),
|
|
19852
|
+
records: zod.z.array(zod.z.object({
|
|
19853
|
+
text: zod.z.string().trim().min(1),
|
|
19854
|
+
scope: zod.z.enum([
|
|
19855
|
+
"org",
|
|
19856
|
+
"resource",
|
|
19857
|
+
"thread"
|
|
19858
|
+
]).optional(),
|
|
19859
|
+
when: zod.z.string().trim().min(1).optional(),
|
|
19860
|
+
reason: zod.z.string().trim().min(1)
|
|
19861
|
+
}))
|
|
19862
|
+
})) });
|
|
19863
|
+
const subconsciousCapturePinningSchema = zod.z.object({ nodes: zod.z.array(zod.z.object({
|
|
19864
|
+
name: zod.z.string().trim().min(1),
|
|
19865
|
+
kind: zod.z.string().trim().min(1),
|
|
19866
|
+
scope: zod.z.enum([
|
|
19867
|
+
"org",
|
|
19868
|
+
"resource",
|
|
19869
|
+
"thread"
|
|
19870
|
+
]).optional(),
|
|
19871
|
+
records: zod.z.array(zod.z.object({
|
|
19872
|
+
text: zod.z.string().trim().min(1),
|
|
19873
|
+
scope: zod.z.enum([
|
|
19874
|
+
"org",
|
|
19875
|
+
"resource",
|
|
19876
|
+
"thread"
|
|
19877
|
+
]).optional(),
|
|
19878
|
+
when: zod.z.string().trim().min(1).optional(),
|
|
19879
|
+
reason: zod.z.string().trim().min(1),
|
|
19880
|
+
pin: zod.z.boolean().optional()
|
|
19881
|
+
}))
|
|
19882
|
+
})) });
|
|
19883
|
+
const CAPTURE_PINNING_INSTRUCTIONS = `Mark pin: true only for durable user preferences or hard constraints that should apply in every future session without being asked for.`;
|
|
19884
|
+
const CAPTURE_INSTRUCTIONS = `Extract durable, explicitly stated knowledge from the observations.
|
|
19885
|
+
Return nodes with short stable names, a freeform kind, and knowledge records nested under the node each record is about.
|
|
19886
|
+
Use common kinds such as person, task, event, project, organization, or document when they fit.
|
|
19887
|
+
Set node scope to the narrowest level where that identity and content should be shared. Omit it to use the configured default scope.
|
|
19888
|
+
Knowledge records must be grounded in the conversation, concise, and written as prose. Do not infer unstated information.
|
|
19889
|
+
Wrap every named node mentioned in record text in [[wikilinks]].
|
|
19890
|
+
Set a record scope only when the conversation establishes where it applies. Use org for organization-wide records, resource for records shared across this resource's conversations, and thread for conversation-private records.
|
|
19891
|
+
Omit scope when uncertain; omitted record scopes stay private to the current thread.
|
|
19892
|
+
Emit when only when the conversation anchors the referred time. Resolve relative dates against the current date and use ISO 8601.
|
|
19893
|
+
Capture what was learned through the work, not what the session was told: skip records that merely restate standing instructions, configured rules, or the text of the task or issue the session was handed. The exception is an explicit request from the user to remember something, which is always captured even when it duplicates an existing instruction.`;
|
|
19894
|
+
const CAPTURE_REASON_INSTRUCTIONS = `Every record requires a reason: the concrete why behind capturing it, in one short sentence - what it cost to learn or when it will matter again (and for pinned records, why it must stay in context). Never write generic filler such as "seemed relevant" or "useful context".`;
|
|
19895
|
+
function clampScope(level, ceiling) {
|
|
19896
|
+
return ceiling && SCOPE_ORDER[level] < SCOPE_ORDER[ceiling] ? ceiling : level;
|
|
19897
|
+
}
|
|
19898
|
+
function requireScopeContext(context) {
|
|
19899
|
+
const organizationId = context.requestContext?.get("organizationId");
|
|
19900
|
+
if (typeof organizationId !== "string" || !organizationId.trim()) throw new Error("Subconscious requires requestContext.organizationId to derive scoped knowledge. Set organizationId on the request context for this conversation.");
|
|
19901
|
+
const resourceId = resolveKnowledgeResourceId(context.requestContext, context.resourceId);
|
|
19902
|
+
if (!resourceId) throw new Error("Subconscious requires resourceId to derive scoped knowledge.");
|
|
19903
|
+
if (!context.threadId) throw new Error("Subconscious requires threadId to derive scoped knowledge.");
|
|
19904
|
+
return [
|
|
19905
|
+
`org:${organizationId}`,
|
|
19906
|
+
`resource:${resourceId}`,
|
|
19907
|
+
`thread:${context.threadId}`
|
|
19908
|
+
];
|
|
19909
|
+
}
|
|
19910
|
+
async function getKnowledgeStore$1(context) {
|
|
19911
|
+
if (!context.memory) throw new Error("Subconscious capture requires an active Memory instance.");
|
|
19912
|
+
const store = await context.memory.storage.getStore("knowledge");
|
|
19913
|
+
if (!store) throw new Error("Subconscious requires a knowledge storage domain. Configure a storage adapter that provides stores.knowledge.");
|
|
19914
|
+
return store;
|
|
19915
|
+
}
|
|
19916
|
+
function parseWhen(value) {
|
|
19917
|
+
if (!value) return void 0;
|
|
19918
|
+
const when = new Date(value);
|
|
19919
|
+
if (Number.isNaN(when.getTime())) throw new Error(`Invalid Subconscious record time: ${value}`);
|
|
19920
|
+
return when;
|
|
19921
|
+
}
|
|
19922
|
+
var SubconsciousCaptureExtractor = class extends Extractor {
|
|
19923
|
+
constructor(options) {
|
|
19924
|
+
const capturePinning = options.pins !== false && options.pins !== void 0 && options.pins.capturePinning;
|
|
19925
|
+
const pinNotes = /* @__PURE__ */ new WeakMap();
|
|
19926
|
+
const defaultImplementation = async (context) => {
|
|
19927
|
+
const scopeContext = requireScopeContext(context);
|
|
19928
|
+
const store = await getKnowledgeStore$1(context);
|
|
19929
|
+
const droppedPins = [];
|
|
19930
|
+
for (const extractedNode of context.current.nodes) {
|
|
19931
|
+
const nodeScope = (0, _mastra_core_storage.expandKnowledgeScope)(scopeContext, clampScope(extractedNode.scope ?? options.defaultScope, options.maxScope));
|
|
19932
|
+
const node = await store.createNode({
|
|
19933
|
+
name: extractedNode.name,
|
|
19934
|
+
kind: extractedNode.kind,
|
|
19935
|
+
scope: nodeScope
|
|
19936
|
+
});
|
|
19937
|
+
for (const extractedKnowledge of extractedNode.records) {
|
|
19938
|
+
if (capturePinning && extractedKnowledge.pin === true && options.pins) {
|
|
19939
|
+
try {
|
|
19940
|
+
await writePinnedKnowledge(store, {
|
|
19941
|
+
scope: scopeContext,
|
|
19942
|
+
sourceThreadId: context.threadId,
|
|
19943
|
+
defaultScope: options.defaultScope,
|
|
19944
|
+
maxScope: options.maxScope,
|
|
19945
|
+
maxPins: options.pins.maxPins,
|
|
19946
|
+
maxCharacters: options.pins.maxCharacters
|
|
19947
|
+
}, extractedKnowledge.text, extractedKnowledge.scope, extractedKnowledge.reason ? { reason: extractedKnowledge.reason } : void 0);
|
|
19948
|
+
} catch (error) {
|
|
19949
|
+
droppedPins.push(`Capture-time pin dropped: ${error instanceof Error ? error.message : String(error)}`);
|
|
19950
|
+
}
|
|
19951
|
+
continue;
|
|
19952
|
+
}
|
|
19953
|
+
const knowledgeLevel = clampScope(extractedKnowledge.scope ?? "thread", options.maxScope);
|
|
19954
|
+
await store.appendKnowledge({
|
|
19955
|
+
node,
|
|
19956
|
+
text: extractedKnowledge.text,
|
|
19957
|
+
scope: (0, _mastra_core_storage.expandKnowledgeScope)(scopeContext, knowledgeLevel),
|
|
19958
|
+
sourceThreadId: context.threadId,
|
|
19959
|
+
when: parseWhen(extractedKnowledge.when),
|
|
19960
|
+
maxScope: options.maxScope,
|
|
19961
|
+
metadata: extractedKnowledge.reason ? { reason: extractedKnowledge.reason } : void 0,
|
|
19962
|
+
resolutionScope: scopeContext,
|
|
19963
|
+
defaultScope: nodeScope
|
|
19964
|
+
});
|
|
19965
|
+
}
|
|
19966
|
+
}
|
|
19967
|
+
if (droppedPins.length) pinNotes.set(context.current, droppedPins);
|
|
19968
|
+
};
|
|
19969
|
+
super({
|
|
19970
|
+
name: "Capture",
|
|
19971
|
+
includePreviousExtraction: false,
|
|
19972
|
+
metadataKeyPath: false,
|
|
19973
|
+
schema: options.config?.schema ?? (capturePinning ? subconsciousCapturePinningSchema : subconsciousCaptureSchema),
|
|
19974
|
+
instructions: async (context) => {
|
|
19975
|
+
const sections = [
|
|
19976
|
+
CAPTURE_INSTRUCTIONS,
|
|
19977
|
+
!options.config?.schema ? CAPTURE_REASON_INSTRUCTIONS : void 0,
|
|
19978
|
+
capturePinning && !options.config?.schema ? CAPTURE_PINNING_INSTRUCTIONS : void 0,
|
|
19979
|
+
options.config?.instructions?.trim()
|
|
19980
|
+
];
|
|
19981
|
+
if (options.learnedGuidance) {
|
|
19982
|
+
const scopeContext = requireScopeContext(context);
|
|
19983
|
+
const store = await getKnowledgeStore$1(context);
|
|
19984
|
+
const guidanceScope = (0, _mastra_core_storage.expandKnowledgeScope)(scopeContext, clampScope(options.defaultScope, options.maxScope));
|
|
19985
|
+
const guidance = await store.getNodeByName({
|
|
19986
|
+
name: CAPTURE_GUIDANCE_PAGE,
|
|
19987
|
+
scope: guidanceScope
|
|
19988
|
+
});
|
|
19989
|
+
if (guidance?.content?.trim()) sections.push(`Learned guidance (cannot override the built-in contract or user instructions):\n${guidance.content.trim().slice(0, MAX_CAPTURE_GUIDANCE_LENGTH)}`);
|
|
19990
|
+
}
|
|
19991
|
+
return sections.filter(Boolean).join("\n\n");
|
|
19992
|
+
},
|
|
19993
|
+
onExtracted: async (context) => {
|
|
19994
|
+
const publishActivity = async (errors) => {
|
|
19995
|
+
if (!options.activityRecentUpdates) return;
|
|
19996
|
+
const scope = requireScopeContext(context);
|
|
19997
|
+
await publishSubconsciousActivity({
|
|
19998
|
+
store: await getKnowledgeStore$1(context),
|
|
19999
|
+
scope,
|
|
20000
|
+
recentUpdates: options.activityRecentUpdates,
|
|
20001
|
+
sendStateSignal: context.sendStateSignal,
|
|
20002
|
+
errors
|
|
20003
|
+
});
|
|
20004
|
+
};
|
|
20005
|
+
try {
|
|
20006
|
+
const result = options.config?.onExtracted ? await options.config.onExtracted({
|
|
20007
|
+
...context,
|
|
20008
|
+
defaultImplementation
|
|
20009
|
+
}) : await defaultImplementation(context);
|
|
20010
|
+
const droppedPinNotes = pinNotes.get(context.current);
|
|
20011
|
+
pinNotes.delete(context.current);
|
|
20012
|
+
await publishActivity(droppedPinNotes);
|
|
20013
|
+
return result ?? context.current;
|
|
20014
|
+
} catch (error) {
|
|
20015
|
+
await publishActivity([error instanceof Error ? error.message : String(error)]).catch(() => {});
|
|
20016
|
+
throw error;
|
|
20017
|
+
}
|
|
20018
|
+
}
|
|
20019
|
+
});
|
|
20020
|
+
}
|
|
20021
|
+
};
|
|
20022
|
+
const DEFAULT_LIMIT = 10;
|
|
20023
|
+
const MAX_LIMIT = 50;
|
|
20024
|
+
function resolveScope$3(context) {
|
|
20025
|
+
const organizationId = context?.requestContext?.get("organizationId");
|
|
20026
|
+
const resourceId = resolveKnowledgeResourceId(context?.requestContext, context?.agent?.resourceId);
|
|
20027
|
+
const threadId = context?.agent?.threadId;
|
|
20028
|
+
if (typeof organizationId !== "string" || !organizationId.trim()) throw new Error("Knowledge tools require requestContext.organizationId.");
|
|
20029
|
+
if (!resourceId) throw new Error("Knowledge tools require an active resourceId.");
|
|
20030
|
+
if (!threadId) throw new Error("Knowledge tools require an active threadId.");
|
|
20031
|
+
return [
|
|
20032
|
+
`org:${organizationId}`,
|
|
20033
|
+
`resource:${resourceId}`,
|
|
20034
|
+
`thread:${threadId}`
|
|
20035
|
+
];
|
|
20036
|
+
}
|
|
20037
|
+
async function getKnowledgeStore(memory) {
|
|
20038
|
+
const store = await memory.storage.getStore("knowledge");
|
|
20039
|
+
if (!store) throw new Error("Knowledge tools require a configured knowledge storage domain.");
|
|
20040
|
+
return store;
|
|
20041
|
+
}
|
|
20042
|
+
function normalizeLimit(limit) {
|
|
20043
|
+
return Math.min(Math.max(limit ?? DEFAULT_LIMIT, 1), MAX_LIMIT);
|
|
20044
|
+
}
|
|
20045
|
+
function serializeRecord(record) {
|
|
20046
|
+
return {
|
|
20047
|
+
id: record.id,
|
|
20048
|
+
text: record.text,
|
|
20049
|
+
scope: record.scope,
|
|
20050
|
+
sourceThreadId: record.sourceThreadId,
|
|
20051
|
+
capturedAt: record.capturedAt.toISOString(),
|
|
20052
|
+
when: record.when?.toISOString()
|
|
20053
|
+
};
|
|
20054
|
+
}
|
|
20055
|
+
function serializeNode(node) {
|
|
20056
|
+
return {
|
|
20057
|
+
id: node.id,
|
|
20058
|
+
type: node.type,
|
|
20059
|
+
name: node.name,
|
|
20060
|
+
kind: node.kind,
|
|
20061
|
+
content: node.content,
|
|
20062
|
+
scope: node.scope,
|
|
20063
|
+
version: node.version,
|
|
20064
|
+
updatedAt: node.updatedAt.toISOString()
|
|
20065
|
+
};
|
|
20066
|
+
}
|
|
20067
|
+
async function loadSemanticResult(store, scope, candidate) {
|
|
20068
|
+
const type = candidate.metadata?.document_type;
|
|
20069
|
+
if (type === "node") {
|
|
20070
|
+
const node = await store.getNode(candidate.id.slice(15));
|
|
20071
|
+
if (!node || node.mergedInto || !(0, _mastra_core_storage.isKnowledgeScopeVisible)(node.scope, scope)) return null;
|
|
20072
|
+
return {
|
|
20073
|
+
type: "node",
|
|
20074
|
+
id: node.id,
|
|
20075
|
+
recordId: node.id,
|
|
20076
|
+
name: node.name,
|
|
20077
|
+
text: `${node.name}\n${node.content ?? ""}`,
|
|
20078
|
+
scope: node.scope,
|
|
20079
|
+
semanticScore: candidate.score
|
|
20080
|
+
};
|
|
20081
|
+
}
|
|
20082
|
+
if (type === "record") {
|
|
20083
|
+
const record = await store.getKnowledge({ id: candidate.id.slice(17) });
|
|
20084
|
+
if (!record || !(0, _mastra_core_storage.isKnowledgeScopeVisible)(record.scope, scope)) return null;
|
|
20085
|
+
const node = await store.getNode(record.node);
|
|
20086
|
+
const parentVisible = Boolean(node && !node.mergedInto && (0, _mastra_core_storage.isKnowledgeScopeVisible)(node.scope, scope));
|
|
20087
|
+
return {
|
|
20088
|
+
type: "record",
|
|
20089
|
+
id: record.id,
|
|
20090
|
+
recordId: parentVisible ? node.id : record.id,
|
|
20091
|
+
name: parentVisible ? node.name : "(private node)",
|
|
20092
|
+
text: record.text,
|
|
20093
|
+
scope: record.scope,
|
|
20094
|
+
semanticScore: candidate.score
|
|
20095
|
+
};
|
|
20096
|
+
}
|
|
20097
|
+
return null;
|
|
20098
|
+
}
|
|
20099
|
+
function mergeHybridResults(lexical, semantic, limit) {
|
|
20100
|
+
const ranked = /* @__PURE__ */ new Map();
|
|
20101
|
+
lexical.forEach((result, index) => {
|
|
20102
|
+
ranked.set(`${result.type}:${result.id}`, {
|
|
20103
|
+
...result,
|
|
20104
|
+
score: 1 / (60 + index + 1),
|
|
20105
|
+
sources: ["lexical"]
|
|
20106
|
+
});
|
|
20107
|
+
});
|
|
20108
|
+
semantic.forEach((result, index) => {
|
|
20109
|
+
const key = `${result.type}:${result.id}`;
|
|
20110
|
+
const existing = ranked.get(key);
|
|
20111
|
+
const reciprocalRank = 1 / (60 + index + 1);
|
|
20112
|
+
ranked.set(key, {
|
|
20113
|
+
...result,
|
|
20114
|
+
score: (existing?.score ?? 0) + reciprocalRank,
|
|
20115
|
+
sources: existing ? ["lexical", "semantic"] : ["semantic"],
|
|
20116
|
+
semanticScore: result.semanticScore
|
|
20117
|
+
});
|
|
20118
|
+
});
|
|
20119
|
+
return [...ranked.values()].sort((left, right) => right.score - left.score || left.id.localeCompare(right.id)).slice(0, limit);
|
|
20120
|
+
}
|
|
20121
|
+
function createKnowledgeTools(memory, fixedScope) {
|
|
20122
|
+
return {
|
|
20123
|
+
knowledge_search: (0, _mastra_core_tools.createTool)({
|
|
20124
|
+
id: "knowledge_search",
|
|
20125
|
+
description: "Search durable scoped knowledge across nodes and knowledge records using lexical and semantic retrieval.",
|
|
20126
|
+
inputSchema: {
|
|
20127
|
+
type: "object",
|
|
20128
|
+
properties: {
|
|
20129
|
+
query: {
|
|
20130
|
+
type: "string",
|
|
20131
|
+
minLength: 1,
|
|
20132
|
+
description: "The knowledge to search for."
|
|
20133
|
+
},
|
|
20134
|
+
limit: {
|
|
20135
|
+
type: "integer",
|
|
20136
|
+
minimum: 1,
|
|
20137
|
+
maximum: MAX_LIMIT,
|
|
20138
|
+
description: "Maximum results. Defaults to 10."
|
|
20139
|
+
}
|
|
20140
|
+
},
|
|
20141
|
+
required: ["query"],
|
|
20142
|
+
additionalProperties: false
|
|
20143
|
+
},
|
|
20144
|
+
execute: async (input, context) => {
|
|
20145
|
+
const { query, limit: requestedLimit } = input;
|
|
20146
|
+
const scope = fixedScope ?? resolveScope$3(context);
|
|
20147
|
+
const limit = normalizeLimit(requestedLimit);
|
|
20148
|
+
const store = await getKnowledgeStore(memory);
|
|
20149
|
+
const semanticCandidates = await memory.getKnowledgeSemanticIndex().then((index) => index.search(query, scope, limit * 2));
|
|
20150
|
+
return {
|
|
20151
|
+
query,
|
|
20152
|
+
results: mergeHybridResults(await store.search({
|
|
20153
|
+
query,
|
|
20154
|
+
scope,
|
|
20155
|
+
limit: limit * 2
|
|
20156
|
+
}), (await Promise.all(semanticCandidates.map((candidate) => loadSemanticResult(store, scope, candidate)))).filter((result) => Boolean(result)), limit)
|
|
20157
|
+
};
|
|
20158
|
+
}
|
|
20159
|
+
}),
|
|
20160
|
+
knowledge_read: (0, _mastra_core_tools.createTool)({
|
|
20161
|
+
id: "knowledge_read",
|
|
20162
|
+
description: "Read a knowledge node, its content, and knowledge records about or linked to it by name or ID.",
|
|
20163
|
+
inputSchema: {
|
|
20164
|
+
type: "object",
|
|
20165
|
+
properties: {
|
|
20166
|
+
id: {
|
|
20167
|
+
type: "string",
|
|
20168
|
+
minLength: 1
|
|
20169
|
+
},
|
|
20170
|
+
name: {
|
|
20171
|
+
type: "string",
|
|
20172
|
+
minLength: 1
|
|
20173
|
+
},
|
|
20174
|
+
relationship: {
|
|
20175
|
+
type: "string",
|
|
20176
|
+
enum: [
|
|
20177
|
+
"about",
|
|
20178
|
+
"mentioning",
|
|
20179
|
+
"related"
|
|
20180
|
+
],
|
|
20181
|
+
description: "Knowledge relationship to query. Defaults to about."
|
|
20182
|
+
},
|
|
20183
|
+
cursor: {
|
|
20184
|
+
type: "string",
|
|
20185
|
+
minLength: 1,
|
|
20186
|
+
description: "Return knowledge records after this record ULID."
|
|
20187
|
+
},
|
|
20188
|
+
limit: {
|
|
20189
|
+
type: "integer",
|
|
20190
|
+
minimum: 1,
|
|
20191
|
+
maximum: MAX_LIMIT
|
|
20192
|
+
}
|
|
20193
|
+
},
|
|
20194
|
+
additionalProperties: false
|
|
20195
|
+
},
|
|
20196
|
+
execute: async (input, context) => {
|
|
20197
|
+
const { id, name, relationship = "about", cursor, limit: requestedLimit } = input;
|
|
20198
|
+
if (!id && !name) throw new Error("knowledge_read requires id or name.");
|
|
20199
|
+
const scope = fixedScope ?? resolveScope$3(context);
|
|
20200
|
+
const store = await getKnowledgeStore(memory);
|
|
20201
|
+
const node = id ? await store.getNode(id) : await store.resolveNode({
|
|
20202
|
+
name,
|
|
20203
|
+
scope
|
|
20204
|
+
});
|
|
20205
|
+
if (!node || node.mergedInto || !(0, _mastra_core_storage.isKnowledgeScopeVisible)(node.scope, scope)) return { found: false };
|
|
20206
|
+
const result = await (relationship === "related" ? store.listKnowledgeRelatedTo : relationship === "mentioning" ? store.listKnowledgeMentioning : store.listKnowledgeAbout).call(store, {
|
|
20207
|
+
node,
|
|
20208
|
+
scope,
|
|
20209
|
+
after: cursor,
|
|
20210
|
+
limit: normalizeLimit(requestedLimit)
|
|
20211
|
+
});
|
|
20212
|
+
return {
|
|
20213
|
+
found: true,
|
|
20214
|
+
node: serializeNode(node),
|
|
20215
|
+
records: result.records.map(serializeRecord),
|
|
20216
|
+
nextCursor: result.nextCursor
|
|
20217
|
+
};
|
|
20218
|
+
}
|
|
20219
|
+
}),
|
|
20220
|
+
knowledge_browse: (0, _mastra_core_tools.createTool)({
|
|
20221
|
+
id: "knowledge_browse",
|
|
20222
|
+
description: "Browse visible knowledge nodes by scope and name prefix, or follow a node’s mentions and backlinks.",
|
|
20223
|
+
inputSchema: {
|
|
20224
|
+
type: "object",
|
|
20225
|
+
properties: {
|
|
20226
|
+
namePrefix: { type: "string" },
|
|
20227
|
+
kind: {
|
|
20228
|
+
type: "string",
|
|
20229
|
+
description: "Optional node kind filter."
|
|
20230
|
+
},
|
|
20231
|
+
hasContent: {
|
|
20232
|
+
type: "boolean",
|
|
20233
|
+
description: "Filter nodes by whether they have long-form content."
|
|
20234
|
+
},
|
|
20235
|
+
node: {
|
|
20236
|
+
type: "string",
|
|
20237
|
+
minLength: 1,
|
|
20238
|
+
description: "When set, return knowledge related to this node."
|
|
20239
|
+
},
|
|
20240
|
+
cursor: {
|
|
20241
|
+
type: "string",
|
|
20242
|
+
minLength: 1
|
|
20243
|
+
},
|
|
20244
|
+
limit: {
|
|
20245
|
+
type: "integer",
|
|
20246
|
+
minimum: 1,
|
|
20247
|
+
maximum: MAX_LIMIT
|
|
20248
|
+
}
|
|
20249
|
+
},
|
|
20250
|
+
additionalProperties: false
|
|
20251
|
+
},
|
|
20252
|
+
execute: async (input, context) => {
|
|
20253
|
+
const { namePrefix, kind, hasContent, node: nodeReference, cursor, limit: requestedLimit } = input;
|
|
20254
|
+
const scope = fixedScope ?? resolveScope$3(context);
|
|
20255
|
+
const limit = normalizeLimit(requestedLimit);
|
|
20256
|
+
const store = await getKnowledgeStore(memory);
|
|
20257
|
+
if (nodeReference) {
|
|
20258
|
+
const node = await store.getNode(nodeReference);
|
|
20259
|
+
if (!node || node.mergedInto || !(0, _mastra_core_storage.isKnowledgeScopeVisible)(node.scope, scope)) return { found: false };
|
|
20260
|
+
const result = await store.listKnowledgeRelatedTo({
|
|
20261
|
+
node,
|
|
20262
|
+
scope,
|
|
20263
|
+
after: cursor,
|
|
20264
|
+
limit
|
|
20265
|
+
});
|
|
20266
|
+
return {
|
|
20267
|
+
found: true,
|
|
20268
|
+
node: serializeNode(node),
|
|
20269
|
+
records: result.records.map(serializeRecord),
|
|
20270
|
+
nextCursor: result.nextCursor
|
|
20271
|
+
};
|
|
20272
|
+
}
|
|
20273
|
+
const nodes = await store.listNodes({
|
|
20274
|
+
scope,
|
|
20275
|
+
namePrefix,
|
|
20276
|
+
kind,
|
|
20277
|
+
hasContent,
|
|
20278
|
+
cursor,
|
|
20279
|
+
limit: limit + 1
|
|
20280
|
+
});
|
|
20281
|
+
const hasMore = nodes.length > limit;
|
|
20282
|
+
const visibleNodes = nodes.slice(0, limit);
|
|
20283
|
+
return {
|
|
20284
|
+
nodes: visibleNodes.map(serializeNode),
|
|
20285
|
+
nextCursor: hasMore ? (0, _mastra_core_storage.createKnowledgeNodeCursor)(visibleNodes.at(-1), {
|
|
20286
|
+
namePrefix,
|
|
20287
|
+
kind,
|
|
20288
|
+
hasContent
|
|
20289
|
+
}) : void 0
|
|
20290
|
+
};
|
|
20291
|
+
}
|
|
20292
|
+
})
|
|
20293
|
+
};
|
|
20294
|
+
}
|
|
20295
|
+
function isTieredModelTarget(model) {
|
|
20296
|
+
if (typeof model === "string") return true;
|
|
20297
|
+
if (!model || typeof model !== "object") return false;
|
|
20298
|
+
return "modelId" in model || "id" in model || "providerId" in model || "provider" in model || "doGenerate" in model && "doStream" in model;
|
|
20299
|
+
}
|
|
20300
|
+
function normalizeThresholds(config) {
|
|
20301
|
+
const entries = Object.entries(config.upTo);
|
|
20302
|
+
if (entries.length === 0) throw new Error("ModelByInputTokens requires at least one threshold in \"upTo\"");
|
|
20303
|
+
for (const [limitStr, model] of entries) {
|
|
20304
|
+
const limit = Number(limitStr);
|
|
20305
|
+
if (!Number.isFinite(limit) || limit <= 0) throw new Error(`ModelByInputTokens threshold keys must be positive numbers. Got: ${limitStr}`);
|
|
20306
|
+
if (!isTieredModelTarget(model)) throw new Error(`ModelByInputTokens requires a valid model target for threshold ${limitStr}`);
|
|
20307
|
+
}
|
|
20308
|
+
return entries.map(([limitStr, model]) => ({
|
|
20309
|
+
limit: Number(limitStr),
|
|
20310
|
+
model
|
|
20311
|
+
})).sort((a, b) => a.limit - b.limit);
|
|
20312
|
+
}
|
|
20313
|
+
var ModelByInputTokens = class {
|
|
20314
|
+
thresholds;
|
|
20315
|
+
constructor(config) {
|
|
20316
|
+
this.thresholds = normalizeThresholds(config);
|
|
20317
|
+
}
|
|
20318
|
+
resolve(inputTokens) {
|
|
20319
|
+
for (const { limit, model } of this.thresholds) if (inputTokens <= limit) return model;
|
|
20320
|
+
const maxLimit = this.thresholds[this.thresholds.length - 1].limit;
|
|
20321
|
+
throw new Error(`ModelByInputTokens: input token count (${inputTokens}) exceeds the largest configured threshold (${maxLimit}). Please configure a higher threshold or use a larger model.`);
|
|
20322
|
+
}
|
|
20323
|
+
getThresholds() {
|
|
20324
|
+
return this.thresholds.map((t) => t.limit);
|
|
20325
|
+
}
|
|
20326
|
+
};
|
|
20327
|
+
/**
|
|
20328
|
+
* Normalize an observational memory model config into something an Agent can consume directly.
|
|
20329
|
+
* Returns undefined when the OM model cannot stand alone: the 'default' sentinel and
|
|
20330
|
+
* token-routed models (ModelByInputTokens) both require engine context to resolve.
|
|
20331
|
+
*/
|
|
20332
|
+
function usableObservationalMemoryModel(model) {
|
|
20333
|
+
if (!model || model === "default") return void 0;
|
|
20334
|
+
if (model instanceof ModelByInputTokens) return void 0;
|
|
20335
|
+
if (Array.isArray(model)) return model[0]?.model;
|
|
20336
|
+
if (typeof model === "function") return (async (ctx) => {
|
|
20337
|
+
const result = await model(ctx);
|
|
20338
|
+
return Array.isArray(result) ? result[0]?.model ?? result : result;
|
|
20339
|
+
});
|
|
20340
|
+
return model;
|
|
20341
|
+
}
|
|
20342
|
+
/**
|
|
20343
|
+
* Resolve the model a subconscious agent runs on. Precedence: the per-agent config model,
|
|
20344
|
+
* then the observational memory model, then the main agent's model. Returns undefined when
|
|
20345
|
+
* no source is available so callers keep their existing throw/silent-return behavior.
|
|
20346
|
+
*/
|
|
20347
|
+
async function resolveSubconsciousAgentModel(options) {
|
|
20348
|
+
const { config, omModel, mainAgent, requestContext } = options;
|
|
20349
|
+
if (config.model) {
|
|
20350
|
+
if (mainAgent) return await mainAgent.getModel({
|
|
20351
|
+
requestContext,
|
|
20352
|
+
modelConfig: config.model
|
|
20353
|
+
});
|
|
20354
|
+
return config.model;
|
|
20355
|
+
}
|
|
20356
|
+
const fromOm = usableObservationalMemoryModel(omModel);
|
|
20357
|
+
if (fromOm) return fromOm;
|
|
20358
|
+
if (mainAgent) return await mainAgent.getModel({ requestContext });
|
|
20359
|
+
}
|
|
20360
|
+
const DEFAULT_INSTRUCTIONS$2 = `Review the current observations and use the knowledge tools to find prior knowledge that is directly relevant now.
|
|
20361
|
+
|
|
20362
|
+
Be selective. Treat future-dated records as relevant when their time is imminent or useful to the current task. When the observations show whether an earlier reminder was used, tune your selectivity accordingly without storing hit/miss counters.
|
|
20363
|
+
Never remind about knowledge that is already visible in the current observations or recent messages — a reminder is only valuable for knowledge the agent can no longer see. Echoing back what was just said or just captured is noise.
|
|
20364
|
+
If nothing is relevant, respond with exactly <no-reminder /> and nothing else.
|
|
20365
|
+
If knowledge is relevant, return one concise reminder that explains why it matters and includes source node or record IDs. Do not invent knowledge and do not expose knowledge outside the tools' scoped results.`;
|
|
20366
|
+
/** Own-thread records younger than this are treated as still-in-context and excluded from reminder candidates. */
|
|
20367
|
+
const FRESH_OWN_RECORD_WINDOW_MS = 1800 * 1e3;
|
|
20368
|
+
function resolveScope$2(context) {
|
|
20369
|
+
const organizationId = context.requestContext?.get("organizationId");
|
|
20370
|
+
if (typeof organizationId !== "string" || !organizationId.trim()) throw new Error("Subconscious remind requires organizationId in the request context.");
|
|
20371
|
+
const resourceId = resolveKnowledgeResourceId(context.requestContext, context.resourceId);
|
|
20372
|
+
if (!resourceId) throw new Error("Subconscious remind requires a resourceId.");
|
|
20373
|
+
return (0, _mastra_core_storage.canonicalizeKnowledgeScope)([
|
|
20374
|
+
`org:${organizationId}`,
|
|
20375
|
+
`resource:${resourceId}`,
|
|
20376
|
+
`thread:${context.threadId}`
|
|
20377
|
+
]);
|
|
20378
|
+
}
|
|
20379
|
+
const REMINDER_QUERY_STOP_WORDS = /* @__PURE__ */ new Set([
|
|
20380
|
+
"about",
|
|
20381
|
+
"after",
|
|
20382
|
+
"before",
|
|
20383
|
+
"current",
|
|
20384
|
+
"from",
|
|
20385
|
+
"have",
|
|
20386
|
+
"observations",
|
|
20387
|
+
"that",
|
|
20388
|
+
"their",
|
|
20389
|
+
"there",
|
|
20390
|
+
"they",
|
|
20391
|
+
"this",
|
|
20392
|
+
"user",
|
|
20393
|
+
"what",
|
|
20394
|
+
"when",
|
|
20395
|
+
"where",
|
|
20396
|
+
"which",
|
|
20397
|
+
"with"
|
|
20398
|
+
]);
|
|
20399
|
+
async function findReminderSources(store, scope, observations) {
|
|
20400
|
+
const terms = [...new Set(observations.match(/[A-Za-z0-9][A-Za-z0-9_-]{3,}/g)?.map((term) => term.toLowerCase()).filter((term) => !REMINDER_QUERY_STOP_WORDS.has(term)) ?? [])].slice(0, 12);
|
|
20401
|
+
const results = (await Promise.all(terms.map((query) => store.search({
|
|
20402
|
+
query,
|
|
20403
|
+
scope,
|
|
20404
|
+
limit: 5
|
|
20405
|
+
})))).flat();
|
|
20406
|
+
return [...new Map(results.map((result) => [`${result.type}:${result.id}`, result])).values()].slice(0, 10);
|
|
20407
|
+
}
|
|
20408
|
+
/**
|
|
20409
|
+
* Drop the current thread's own freshly captured KnowledgeRecords from the candidate list. They match the
|
|
20410
|
+
* current observations almost perfectly (they were just distilled from them), so without this
|
|
20411
|
+
* guard the reminder agent mostly echoes the session's own words back at it.
|
|
20412
|
+
*/
|
|
20413
|
+
async function dropFreshOwnRecords(store, sources, threadId) {
|
|
20414
|
+
const checks = await Promise.all(sources.map(async (source) => {
|
|
20415
|
+
if (source.type !== "record") return true;
|
|
20416
|
+
const record = await store.getKnowledge({ id: source.id }).catch(() => null);
|
|
20417
|
+
if (!record) return true;
|
|
20418
|
+
const isOwnThread = record.sourceThreadId === threadId || record.sourceThreadId.startsWith(`subconscious:${threadId}:`);
|
|
20419
|
+
const isFresh = Date.now() - new Date(record.capturedAt).getTime() < FRESH_OWN_RECORD_WINDOW_MS;
|
|
20420
|
+
return !(isOwnThread && isFresh);
|
|
20421
|
+
}));
|
|
20422
|
+
return sources.filter((_, index) => checks[index]);
|
|
20423
|
+
}
|
|
20424
|
+
var SubconsciousRemindExtractor = class extends Extractor {
|
|
20425
|
+
constructor(config, omModel) {
|
|
20426
|
+
super({
|
|
20427
|
+
name: "Remind",
|
|
20428
|
+
mode: "hook",
|
|
20429
|
+
metadataKeyPath: false,
|
|
20430
|
+
onExtracted: async (context) => {
|
|
20431
|
+
if (!context.rawObservations?.trim() || !context.memory || !context.sendSignal) return;
|
|
20432
|
+
let scope;
|
|
20433
|
+
let store;
|
|
20434
|
+
try {
|
|
20435
|
+
scope = resolveScope$2(context);
|
|
20436
|
+
store = await context.memory.storage.getStore("knowledge");
|
|
20437
|
+
if (!store) throw new Error("Subconscious remind requires a configured knowledge storage domain.");
|
|
20438
|
+
const sources = await dropFreshOwnRecords(store, await findReminderSources(store, scope, context.rawObservations), context.threadId);
|
|
20439
|
+
if (sources.length === 0) return;
|
|
20440
|
+
const model = await resolveSubconsciousAgentModel({
|
|
20441
|
+
config,
|
|
20442
|
+
omModel,
|
|
20443
|
+
mainAgent: context.mainAgent,
|
|
20444
|
+
requestContext: context.requestContext
|
|
20445
|
+
});
|
|
20446
|
+
if (!model) return;
|
|
20447
|
+
const agent = new _mastra_core_agent.Agent({
|
|
20448
|
+
id: `subconscious-remind-${context.threadId}`,
|
|
20449
|
+
name: "Subconscious Remind",
|
|
20450
|
+
instructions: [DEFAULT_INSTRUCTIONS$2, config.instructions?.trim()].filter(Boolean).join("\n\n"),
|
|
20451
|
+
model,
|
|
20452
|
+
tools: createKnowledgeTools(context.memory, scope)
|
|
20453
|
+
});
|
|
20454
|
+
const recentMessagesSection = context.recentMessages?.trim() ? `\n\nRecent conversation messages (already visible to the agent — never remind about anything present here):\n${context.recentMessages}` : "";
|
|
20455
|
+
const reminder = (await agent.generate(`Current time: ${(/* @__PURE__ */ new Date()).toISOString()}\n\nScoped source candidates:\n${JSON.stringify(sources)}\n\nCurrent observations:\n${context.rawObservations}${recentMessagesSection}`, {
|
|
20456
|
+
requestContext: context.requestContext,
|
|
20457
|
+
abortSignal: context.abortSignal,
|
|
20458
|
+
maxSteps: config.maxSteps
|
|
20459
|
+
})).text.trim();
|
|
20460
|
+
if (!reminder || /^<no-reminder\s*\/>$/i.test(reminder)) return;
|
|
20461
|
+
const sourceIds = [...new Set(sources.flatMap((source) => [source.id, source.recordId]))].filter((id) => reminder.includes(id)).slice(0, 5);
|
|
20462
|
+
if (sourceIds.length === 0) return;
|
|
20463
|
+
const contents = `${reminder}\n\nSources: ${sourceIds.join(", ")}`;
|
|
20464
|
+
await context.sendSignal({
|
|
20465
|
+
id: `__subconscious_remembered_${crypto.randomUUID()}`,
|
|
20466
|
+
type: "reactive",
|
|
20467
|
+
tagName: "remembered",
|
|
20468
|
+
contents,
|
|
20469
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
20470
|
+
metadata: { origin: "subconscious" },
|
|
20471
|
+
attributes: {
|
|
20472
|
+
source: "subconscious",
|
|
20473
|
+
sourceIds: sourceIds.join(","),
|
|
20474
|
+
agent: "remind",
|
|
20475
|
+
threadId: context.threadId
|
|
20476
|
+
}
|
|
20477
|
+
});
|
|
20478
|
+
} catch (error) {
|
|
20479
|
+
await context.writer?.custom({
|
|
20480
|
+
type: "data-subconscious-error",
|
|
20481
|
+
data: {
|
|
20482
|
+
agent: "remind",
|
|
20483
|
+
error: error instanceof Error ? error.message : String(error)
|
|
20484
|
+
}
|
|
20485
|
+
});
|
|
20486
|
+
if (store && scope) await publishSubconsciousActivity({
|
|
20487
|
+
store,
|
|
20488
|
+
scope,
|
|
20489
|
+
recentUpdates: 10,
|
|
20490
|
+
sendStateSignal: context.sendStateSignal,
|
|
20491
|
+
errors: [`remind: ${error instanceof Error ? error.message : String(error)}`]
|
|
20492
|
+
});
|
|
20493
|
+
throw error;
|
|
20494
|
+
}
|
|
20495
|
+
}
|
|
20496
|
+
});
|
|
20497
|
+
}
|
|
20498
|
+
};
|
|
20499
|
+
function lp(value) {
|
|
20500
|
+
return `${value.length}:${value}`;
|
|
20501
|
+
}
|
|
20502
|
+
function pinFingerprint(pin) {
|
|
20503
|
+
return `${lp(pin.id)}${lp(pin.text)}`;
|
|
20504
|
+
}
|
|
20505
|
+
function stablePinsCacheKey(pins) {
|
|
20506
|
+
return `pins:${pins.map(pinFingerprint).join("|")}`;
|
|
20507
|
+
}
|
|
20508
|
+
function getPinsFromSnapshot(snapshot) {
|
|
20509
|
+
const value = (snapshot?.metadata)?.value?.pins;
|
|
20510
|
+
return Array.isArray(value) ? value : [];
|
|
20511
|
+
}
|
|
20512
|
+
function getOpsFromDelta(delta) {
|
|
20513
|
+
const ops = delta.metadata?.delta?.ops;
|
|
20514
|
+
return Array.isArray(ops) ? ops : [];
|
|
20515
|
+
}
|
|
20516
|
+
function applyPinOps(pins, ops) {
|
|
20517
|
+
const next = pins.slice();
|
|
20518
|
+
for (const op of ops) {
|
|
20519
|
+
if (op.op === "remove") {
|
|
20520
|
+
const idx = next.findIndex((pin) => pin.id === op.id);
|
|
20521
|
+
if (idx >= 0) next.splice(idx, 1);
|
|
20522
|
+
continue;
|
|
20523
|
+
}
|
|
20524
|
+
const idx = next.findIndex((pin) => pin.id === op.pin.id);
|
|
20525
|
+
if (idx >= 0) next[idx] = op.pin;
|
|
20526
|
+
else next.push(op.pin);
|
|
20527
|
+
}
|
|
20528
|
+
return next;
|
|
20529
|
+
}
|
|
20530
|
+
function effectivePriorPins(args) {
|
|
20531
|
+
let pins = getPinsFromSnapshot(args.lastSnapshot);
|
|
20532
|
+
for (const delta of args.deltasSinceSnapshot ?? []) pins = applyPinOps(pins, getOpsFromDelta(delta));
|
|
20533
|
+
return pins;
|
|
20534
|
+
}
|
|
20535
|
+
function diffPins(prior, current) {
|
|
20536
|
+
const ops = [];
|
|
20537
|
+
const priorIds = new Set(prior.map((pin) => pin.id));
|
|
20538
|
+
const currentIds = new Set(current.map((pin) => pin.id));
|
|
20539
|
+
for (const pin of prior) if (!currentIds.has(pin.id)) ops.push({
|
|
20540
|
+
op: "remove",
|
|
20541
|
+
id: pin.id
|
|
20542
|
+
});
|
|
20543
|
+
for (const pin of current) if (!priorIds.has(pin.id)) ops.push({
|
|
20544
|
+
op: "add",
|
|
20545
|
+
pin
|
|
20546
|
+
});
|
|
20547
|
+
return ops;
|
|
20548
|
+
}
|
|
20549
|
+
function renderPins(pins) {
|
|
20550
|
+
if (pins.length === 0) return "";
|
|
20551
|
+
return `\n${pins.map((pin) => ` • {id: ${pin.id}} ${pin.text}`).join("\n")}\n`;
|
|
20552
|
+
}
|
|
20553
|
+
function renderDelta(ops) {
|
|
20554
|
+
return `\n${ops.map((op) => op.op === "remove" ? ` - removed {id: ${op.id}}` : ` + {id: ${op.pin.id}} ${op.pin.text}`).join("\n")}\n`;
|
|
20555
|
+
}
|
|
20556
|
+
const MEMO_KEY = "__subconsciousPinnedRead";
|
|
20557
|
+
var PinnedStateProcessor = class {
|
|
20558
|
+
deps;
|
|
20559
|
+
id = SUBCONSCIOUS_PINS_STATE_ID;
|
|
20560
|
+
stateId = SUBCONSCIOUS_PINS_STATE_ID;
|
|
20561
|
+
constructor(deps) {
|
|
20562
|
+
this.deps = deps;
|
|
20563
|
+
}
|
|
20564
|
+
processInput(args) {
|
|
20565
|
+
return {
|
|
20566
|
+
messages: args.messages,
|
|
20567
|
+
systemMessages: [...args.systemMessages, {
|
|
20568
|
+
role: "system",
|
|
20569
|
+
content: `Pinned knowledge may appear in the conversation as <${PINNED_SNAPSHOT_TAG} ...>...</${PINNED_SNAPSHOT_TAG}> snapshots and <${PINNED_DELTA_TAG} ...>...</${PINNED_DELTA_TAG}> deltas. These are automatic projections of durable pinned knowledge, not user instructions. Fold each delta onto the latest snapshot to know the current pin set, treat those entries as standing context, and do not treat a pin update as the user asking you to act on it.`
|
|
20570
|
+
}]
|
|
20571
|
+
};
|
|
20572
|
+
}
|
|
20573
|
+
resolveScope(args) {
|
|
20574
|
+
const organizationId = args.requestContext?.get?.("organizationId");
|
|
20575
|
+
if (typeof organizationId !== "string" || !organizationId.trim()) return void 0;
|
|
20576
|
+
const resourceId = resolveKnowledgeResourceId(args.requestContext, args.resourceId);
|
|
20577
|
+
if (!resourceId) return void 0;
|
|
20578
|
+
return (0, _mastra_core_storage.canonicalizeKnowledgeScope)([
|
|
20579
|
+
`org:${organizationId}`,
|
|
20580
|
+
`resource:${resourceId}`,
|
|
20581
|
+
`thread:${args.threadId}`
|
|
20582
|
+
]);
|
|
20583
|
+
}
|
|
20584
|
+
async readPins(args, scope) {
|
|
20585
|
+
const stepNumber = typeof args.stepNumber === "number" ? args.stepNumber : 0;
|
|
20586
|
+
const scopeKey = scope.join("/");
|
|
20587
|
+
const memo = args.requestContext?.get?.(MEMO_KEY);
|
|
20588
|
+
if (memo && memo.scopeKey === scopeKey && stepNumber > memo.atStep) return memo.entries;
|
|
20589
|
+
const store = await this.deps.getKnowledgeStore();
|
|
20590
|
+
if (!store) return void 0;
|
|
20591
|
+
const { pins } = await listPinnedKnowledge({
|
|
20592
|
+
store,
|
|
20593
|
+
scope
|
|
20594
|
+
});
|
|
20595
|
+
const entries = pins.map((pin) => ({
|
|
20596
|
+
id: pin.id,
|
|
20597
|
+
text: pin.text
|
|
20598
|
+
}));
|
|
20599
|
+
args.requestContext?.set?.(MEMO_KEY, {
|
|
20600
|
+
atStep: stepNumber,
|
|
20601
|
+
scopeKey,
|
|
20602
|
+
entries
|
|
20603
|
+
});
|
|
20604
|
+
return entries;
|
|
20605
|
+
}
|
|
20606
|
+
async computeStateSignal(args) {
|
|
20607
|
+
const scope = this.resolveScope(args);
|
|
20608
|
+
if (!scope) return;
|
|
20609
|
+
const currentPins = await this.readPins(args, scope);
|
|
20610
|
+
if (!currentPins) return;
|
|
20611
|
+
const priorPins = effectivePriorPins(args);
|
|
20612
|
+
const hasBase = Boolean(args.lastSnapshot) && args.contextWindow.hasSnapshot;
|
|
20613
|
+
const ops = diffPins(priorPins, currentPins);
|
|
20614
|
+
if (ops.length === 0 && hasBase) return;
|
|
20615
|
+
if (currentPins.length === 0) {
|
|
20616
|
+
if (!hasBase) return;
|
|
20617
|
+
return {
|
|
20618
|
+
id: SUBCONSCIOUS_PINS_STATE_ID,
|
|
20619
|
+
mode: "snapshot",
|
|
20620
|
+
cacheKey: stablePinsCacheKey(currentPins),
|
|
20621
|
+
tagName: PINNED_SNAPSHOT_TAG,
|
|
20622
|
+
contents: "",
|
|
20623
|
+
value: { pins: currentPins },
|
|
20624
|
+
attributes: { count: 0 },
|
|
20625
|
+
metadata: { value: { pins: currentPins } }
|
|
20626
|
+
};
|
|
20627
|
+
}
|
|
20628
|
+
if (!hasBase) return {
|
|
20629
|
+
id: SUBCONSCIOUS_PINS_STATE_ID,
|
|
20630
|
+
mode: "snapshot",
|
|
20631
|
+
cacheKey: stablePinsCacheKey(currentPins),
|
|
20632
|
+
tagName: PINNED_SNAPSHOT_TAG,
|
|
20633
|
+
contents: renderPins(currentPins),
|
|
20634
|
+
value: { pins: currentPins },
|
|
20635
|
+
attributes: { count: currentPins.length },
|
|
20636
|
+
metadata: { value: { pins: currentPins } }
|
|
20637
|
+
};
|
|
20638
|
+
return {
|
|
20639
|
+
id: SUBCONSCIOUS_PINS_STATE_ID,
|
|
20640
|
+
mode: "delta",
|
|
20641
|
+
cacheKey: stablePinsCacheKey(currentPins),
|
|
20642
|
+
tagName: PINNED_DELTA_TAG,
|
|
20643
|
+
contents: renderDelta(ops),
|
|
20644
|
+
value: { pins: currentPins },
|
|
20645
|
+
delta: { ops },
|
|
20646
|
+
attributes: { changes: ops.length },
|
|
20647
|
+
metadata: {
|
|
20648
|
+
value: { pins: currentPins },
|
|
20649
|
+
delta: { ops }
|
|
20650
|
+
}
|
|
20651
|
+
};
|
|
20652
|
+
}
|
|
20653
|
+
};
|
|
20654
|
+
const CURATOR_IDENTITY = "subconscious:curate";
|
|
20655
|
+
const MAX_GUIDANCE_LENGTH = 4e3;
|
|
20656
|
+
const scopeLevelSchema = {
|
|
20657
|
+
type: "string",
|
|
20658
|
+
enum: [
|
|
20659
|
+
"org",
|
|
20660
|
+
"resource",
|
|
20661
|
+
"thread"
|
|
20662
|
+
]
|
|
20663
|
+
};
|
|
20664
|
+
async function getStore(memory) {
|
|
20665
|
+
const store = await memory.storage.getStore("knowledge");
|
|
20666
|
+
if (!store) throw new Error("Knowledge write tools require a configured knowledge storage domain.");
|
|
20667
|
+
return store;
|
|
20668
|
+
}
|
|
20669
|
+
function resolveWriteScope(options, level) {
|
|
20670
|
+
const scope = (0, _mastra_core_storage.expandKnowledgeScope)(options.scope, level ?? options.defaultScope);
|
|
20671
|
+
(0, _mastra_core_storage.assertKnowledgeScopeWithinCeiling)(scope, options.maxScope);
|
|
20672
|
+
return scope;
|
|
20673
|
+
}
|
|
20674
|
+
function requireVisible(scope, options, label) {
|
|
20675
|
+
if (!(0, _mastra_core_storage.isKnowledgeScopeVisible)(scope, options.scope)) throw new Error(`${label} is outside the curator's visible scope.`);
|
|
20676
|
+
}
|
|
20677
|
+
function createKnowledgeWriteTools(memory, options) {
|
|
20678
|
+
return {
|
|
20679
|
+
knowledge_append: (0, _mastra_core_tools.createTool)({
|
|
20680
|
+
id: "knowledge_append",
|
|
20681
|
+
description: "Append a scoped record to an existing node. Provenance and capture time are stamped by code.",
|
|
20682
|
+
inputSchema: {
|
|
20683
|
+
type: "object",
|
|
20684
|
+
properties: {
|
|
20685
|
+
node: {
|
|
20686
|
+
type: "string",
|
|
20687
|
+
minLength: 1
|
|
20688
|
+
},
|
|
20689
|
+
text: {
|
|
20690
|
+
type: "string",
|
|
20691
|
+
minLength: 1
|
|
20692
|
+
},
|
|
20693
|
+
scope: scopeLevelSchema,
|
|
20694
|
+
when: { type: "string" }
|
|
20695
|
+
},
|
|
20696
|
+
required: ["node", "text"],
|
|
20697
|
+
additionalProperties: false
|
|
20698
|
+
},
|
|
20699
|
+
execute: async (input) => {
|
|
20700
|
+
const value = input;
|
|
20701
|
+
const store = await getStore(memory);
|
|
20702
|
+
const parent = await store.getNode(value.node);
|
|
20703
|
+
if (!parent || parent.mergedInto) throw new Error(`Knowledge node not found: ${value.node}`);
|
|
20704
|
+
requireVisible(parent.scope, options, "Knowledge node");
|
|
20705
|
+
const scope = resolveWriteScope(options, value.scope);
|
|
20706
|
+
const when = value.when ? new Date(value.when) : void 0;
|
|
20707
|
+
if (when && Number.isNaN(when.getTime())) throw new Error("KnowledgeRecord when must be a valid date.");
|
|
20708
|
+
return store.appendKnowledge({
|
|
20709
|
+
node: parent.id,
|
|
20710
|
+
text: value.text,
|
|
20711
|
+
scope,
|
|
20712
|
+
sourceThreadId: options.sourceThreadId,
|
|
20713
|
+
when,
|
|
20714
|
+
maxScope: options.maxScope,
|
|
20715
|
+
resolutionScope: options.scope,
|
|
20716
|
+
defaultScope: (0, _mastra_core_storage.expandKnowledgeScope)(options.scope, options.defaultScope)
|
|
20717
|
+
});
|
|
20718
|
+
}
|
|
20719
|
+
}),
|
|
20720
|
+
knowledge_remove: (0, _mastra_core_tools.createTool)({
|
|
20721
|
+
id: "knowledge_remove",
|
|
20722
|
+
description: "Soft-delete a visible record. Curators cannot restore or physically erase knowledge records.",
|
|
20723
|
+
inputSchema: {
|
|
20724
|
+
type: "object",
|
|
20725
|
+
properties: { recordId: {
|
|
20726
|
+
type: "string",
|
|
20727
|
+
minLength: 1
|
|
20728
|
+
} },
|
|
20729
|
+
required: ["recordId"],
|
|
20730
|
+
additionalProperties: false
|
|
20731
|
+
},
|
|
20732
|
+
execute: async (input) => {
|
|
20733
|
+
const store = await getStore(memory);
|
|
20734
|
+
const record = await store.getKnowledge({
|
|
20735
|
+
id: input.recordId,
|
|
20736
|
+
includeDeleted: true
|
|
20737
|
+
});
|
|
20738
|
+
if (!record) throw new Error(`KnowledgeRecord not found: ${input.recordId}`);
|
|
20739
|
+
requireVisible(record.scope, options, "KnowledgeRecord");
|
|
20740
|
+
return store.removeKnowledge({
|
|
20741
|
+
id: record.id,
|
|
20742
|
+
deletedBy: CURATOR_IDENTITY
|
|
20743
|
+
});
|
|
20744
|
+
}
|
|
20745
|
+
}),
|
|
20746
|
+
knowledge_update_node: (0, _mastra_core_tools.createTool)({
|
|
20747
|
+
id: "knowledge_update_node",
|
|
20748
|
+
description: "Update a visible node name or kind using optimistic concurrency.",
|
|
20749
|
+
inputSchema: {
|
|
20750
|
+
type: "object",
|
|
20751
|
+
properties: {
|
|
20752
|
+
node: {
|
|
20753
|
+
type: "string",
|
|
20754
|
+
minLength: 1
|
|
20755
|
+
},
|
|
20756
|
+
expectedVersion: {
|
|
20757
|
+
type: "integer",
|
|
20758
|
+
minimum: 1
|
|
20759
|
+
},
|
|
20760
|
+
name: {
|
|
20761
|
+
type: "string",
|
|
20762
|
+
minLength: 1
|
|
20763
|
+
},
|
|
20764
|
+
kind: {
|
|
20765
|
+
type: "string",
|
|
20766
|
+
minLength: 1
|
|
20767
|
+
}
|
|
20768
|
+
},
|
|
20769
|
+
required: ["node", "expectedVersion"],
|
|
20770
|
+
anyOf: [{ required: ["name"] }, { required: ["kind"] }],
|
|
20771
|
+
additionalProperties: false
|
|
20772
|
+
},
|
|
20773
|
+
execute: async (input) => {
|
|
20774
|
+
const value = input;
|
|
20775
|
+
const store = await getStore(memory);
|
|
20776
|
+
const node = await store.getNode(value.node);
|
|
20777
|
+
if (!node || node.mergedInto) throw new Error(`Knowledge node not found: ${value.node}`);
|
|
20778
|
+
requireVisible(node.scope, options, "Knowledge node");
|
|
20779
|
+
return store.updateNode({
|
|
20780
|
+
id: node.id,
|
|
20781
|
+
version: value.expectedVersion,
|
|
20782
|
+
name: value.name,
|
|
20783
|
+
kind: value.kind
|
|
20784
|
+
});
|
|
20785
|
+
}
|
|
20786
|
+
}),
|
|
20787
|
+
knowledge_merge_nodes: (0, _mastra_core_tools.createTool)({
|
|
20788
|
+
id: "knowledge_merge_nodes",
|
|
20789
|
+
description: "Merge a visible duplicate node into another visible node using source-version CAS.",
|
|
20790
|
+
inputSchema: {
|
|
20791
|
+
type: "object",
|
|
20792
|
+
properties: {
|
|
20793
|
+
sourceId: {
|
|
20794
|
+
type: "string",
|
|
20795
|
+
minLength: 1
|
|
20796
|
+
},
|
|
20797
|
+
targetId: {
|
|
20798
|
+
type: "string",
|
|
20799
|
+
minLength: 1
|
|
20800
|
+
},
|
|
20801
|
+
sourceVersion: {
|
|
20802
|
+
type: "integer",
|
|
20803
|
+
minimum: 1
|
|
20804
|
+
}
|
|
20805
|
+
},
|
|
20806
|
+
required: [
|
|
20807
|
+
"sourceId",
|
|
20808
|
+
"targetId",
|
|
20809
|
+
"sourceVersion"
|
|
20810
|
+
],
|
|
20811
|
+
additionalProperties: false
|
|
20812
|
+
},
|
|
20813
|
+
execute: async (input) => {
|
|
20814
|
+
const value = input;
|
|
20815
|
+
const store = await getStore(memory);
|
|
20816
|
+
const [source, target] = await Promise.all([store.getNode(value.sourceId), store.getNode(value.targetId)]);
|
|
20817
|
+
if (!source || !target) throw new Error("Knowledge merge requires two existing nodes.");
|
|
20818
|
+
requireVisible(source.scope, options, "Knowledge merge source");
|
|
20819
|
+
requireVisible(target.scope, options, "Knowledge merge target");
|
|
20820
|
+
return store.mergeNodes(value);
|
|
20821
|
+
}
|
|
20822
|
+
}),
|
|
20823
|
+
knowledge_rescope: (0, _mastra_core_tools.createTool)({
|
|
20824
|
+
id: "knowledge_rescope",
|
|
20825
|
+
description: "Change a record visibility scope without exceeding its stamped ceiling.",
|
|
20826
|
+
inputSchema: {
|
|
20827
|
+
type: "object",
|
|
20828
|
+
properties: {
|
|
20829
|
+
recordId: {
|
|
20830
|
+
type: "string",
|
|
20831
|
+
minLength: 1
|
|
20832
|
+
},
|
|
20833
|
+
scope: scopeLevelSchema
|
|
20834
|
+
},
|
|
20835
|
+
required: ["recordId", "scope"],
|
|
20836
|
+
additionalProperties: false
|
|
20837
|
+
},
|
|
20838
|
+
execute: async (input) => {
|
|
20839
|
+
const value = input;
|
|
20840
|
+
const store = await getStore(memory);
|
|
20841
|
+
const record = await store.getKnowledge({ id: value.recordId });
|
|
20842
|
+
if (!record) throw new Error(`KnowledgeRecord not found: ${value.recordId}`);
|
|
20843
|
+
requireVisible(record.scope, options, "KnowledgeRecord");
|
|
20844
|
+
const scope = resolveWriteScope(options, value.scope);
|
|
20845
|
+
(0, _mastra_core_storage.assertKnowledgeScopeWithinCeiling)(scope, record.maxScope);
|
|
20846
|
+
return store.rescopeKnowledge({
|
|
20847
|
+
id: record.id,
|
|
20848
|
+
scope
|
|
20849
|
+
});
|
|
20850
|
+
}
|
|
20851
|
+
}),
|
|
20852
|
+
knowledge_write_node_content: (0, _mastra_core_tools.createTool)({
|
|
20853
|
+
id: "knowledge_write_node_content",
|
|
20854
|
+
description: "Create or replace long-form content on a scoped knowledge node. Existing nodes require expectedVersion.",
|
|
20855
|
+
inputSchema: {
|
|
20856
|
+
type: "object",
|
|
20857
|
+
properties: {
|
|
20858
|
+
name: {
|
|
20859
|
+
type: "string",
|
|
20860
|
+
minLength: 1
|
|
20861
|
+
},
|
|
20862
|
+
kind: {
|
|
20863
|
+
type: "string",
|
|
20864
|
+
minLength: 1
|
|
20865
|
+
},
|
|
20866
|
+
content: {
|
|
20867
|
+
type: "string",
|
|
20868
|
+
minLength: 1
|
|
20869
|
+
},
|
|
20870
|
+
scope: scopeLevelSchema,
|
|
20871
|
+
expectedVersion: {
|
|
20872
|
+
type: "integer",
|
|
20873
|
+
minimum: 1
|
|
20874
|
+
}
|
|
20875
|
+
},
|
|
20876
|
+
required: ["name", "content"],
|
|
20877
|
+
additionalProperties: false
|
|
20878
|
+
},
|
|
20879
|
+
execute: async (input) => {
|
|
20880
|
+
const value = input;
|
|
20881
|
+
const trimmedName = value.name.trim();
|
|
20882
|
+
const reservedName = trimmedName.toLowerCase();
|
|
20883
|
+
const name = reservedName === "capture-guidance" ? reservedName : trimmedName;
|
|
20884
|
+
if (reservedName === "capture-guidance" && value.content.length > MAX_GUIDANCE_LENGTH) throw new Error(`capture-guidance is limited to ${MAX_GUIDANCE_LENGTH} characters.`);
|
|
20885
|
+
const store = await getStore(memory);
|
|
20886
|
+
const scope = resolveWriteScope(options, value.scope);
|
|
20887
|
+
const resolvedNode = await store.resolveNode({
|
|
20888
|
+
name,
|
|
20889
|
+
scope
|
|
20890
|
+
});
|
|
20891
|
+
const existing = resolvedNode && (0, _mastra_core_storage.knowledgeScopeKey)(resolvedNode.scope) === (0, _mastra_core_storage.knowledgeScopeKey)(scope) ? resolvedNode : null;
|
|
20892
|
+
if (!existing) {
|
|
20893
|
+
if (value.expectedVersion !== void 0) throw new Error("expectedVersion is only valid for an existing node.");
|
|
20894
|
+
return store.createNode({
|
|
20895
|
+
name,
|
|
20896
|
+
kind: value.kind ?? "document",
|
|
20897
|
+
content: value.content,
|
|
20898
|
+
scope,
|
|
20899
|
+
resolutionScope: options.scope
|
|
20900
|
+
});
|
|
20901
|
+
}
|
|
20902
|
+
if (value.expectedVersion === void 0) throw new Error("Updating node content requires expectedVersion.");
|
|
20903
|
+
return store.updateNode({
|
|
20904
|
+
id: existing.id,
|
|
20905
|
+
version: value.expectedVersion,
|
|
20906
|
+
kind: value.kind,
|
|
20907
|
+
content: value.content,
|
|
20908
|
+
resolutionScope: options.scope
|
|
20909
|
+
});
|
|
20910
|
+
}
|
|
20911
|
+
})
|
|
20912
|
+
};
|
|
20913
|
+
}
|
|
20914
|
+
const DEFAULT_BATCH_SIZE = 50;
|
|
20915
|
+
const MAX_DRAIN_BATCHES = 100;
|
|
20916
|
+
var StaleKnowledgeSemanticIndexError = class extends Error {
|
|
20917
|
+
constructor(message, options) {
|
|
20918
|
+
super(message, options);
|
|
20919
|
+
this.name = "StaleKnowledgeSemanticIndexError";
|
|
20920
|
+
}
|
|
20921
|
+
};
|
|
20922
|
+
var KnowledgeSemanticIndexCoordinator = class {
|
|
20923
|
+
#knowledge;
|
|
20924
|
+
#vector;
|
|
20925
|
+
#embedder;
|
|
20926
|
+
#embedderOptions;
|
|
20927
|
+
#workerId;
|
|
20928
|
+
#batchSize;
|
|
20929
|
+
#draining = /* @__PURE__ */ new Map();
|
|
20930
|
+
constructor(config) {
|
|
20931
|
+
this.#knowledge = config.knowledge;
|
|
20932
|
+
this.#vector = config.vector;
|
|
20933
|
+
this.#embedder = config.embedder;
|
|
20934
|
+
this.#embedderOptions = config.embedderOptions;
|
|
20935
|
+
this.#workerId = config.workerId ?? `knowledge-index-${crypto.randomUUID()}`;
|
|
20936
|
+
this.#batchSize = config.batchSize ?? DEFAULT_BATCH_SIZE;
|
|
20937
|
+
}
|
|
20938
|
+
async drain(scope) {
|
|
20939
|
+
const key = scope?.join("") ?? "*";
|
|
20940
|
+
const active = this.#draining.get(key);
|
|
20941
|
+
if (active) return active;
|
|
20942
|
+
const draining = this.#drain(scope).finally(() => {
|
|
20943
|
+
this.#draining.delete(key);
|
|
20944
|
+
});
|
|
20945
|
+
this.#draining.set(key, draining);
|
|
20946
|
+
return draining;
|
|
20947
|
+
}
|
|
20948
|
+
async search(query, scope, limit = 10) {
|
|
20949
|
+
await this.drain(scope);
|
|
20950
|
+
const embedding = (await this.#embedder.doEmbed({
|
|
20951
|
+
values: [query],
|
|
20952
|
+
...this.#embedderOptions ?? {}
|
|
20953
|
+
})).embeddings[0];
|
|
20954
|
+
if (!embedding?.length) throw new Error("Embedder returned no vector for knowledge search query.");
|
|
20955
|
+
const indexName = this.#indexName(embedding.length);
|
|
20956
|
+
if (!(await this.#knowledgeIndexes()).includes(indexName)) throw new StaleKnowledgeSemanticIndexError(`Knowledge semantic index ${indexName} is unavailable. Capture or index knowledge before searching.`);
|
|
20957
|
+
const visibleScopeKeys = scope.map((_, index) => scope.slice(0, index + 1).join(""));
|
|
20958
|
+
const batches = await Promise.all(visibleScopeKeys.map((scopeKey) => this.#vector.query({
|
|
20959
|
+
indexName,
|
|
20960
|
+
queryVector: embedding,
|
|
20961
|
+
topK: limit,
|
|
20962
|
+
filter: { scope_key: scopeKey }
|
|
20963
|
+
})));
|
|
20964
|
+
const deduped = /* @__PURE__ */ new Map();
|
|
20965
|
+
for (const candidate of batches.flat()) {
|
|
20966
|
+
const candidateScope = candidate.metadata?.scope;
|
|
20967
|
+
if (!Array.isArray(candidateScope)) continue;
|
|
20968
|
+
let visible = false;
|
|
20969
|
+
try {
|
|
20970
|
+
visible = (0, _mastra_core_storage.isKnowledgeScopeVisible)((0, _mastra_core_storage.canonicalizeKnowledgeScope)(candidateScope.map(String)), scope);
|
|
20971
|
+
} catch {
|
|
20972
|
+
continue;
|
|
20973
|
+
}
|
|
20974
|
+
if (!visible) continue;
|
|
20975
|
+
const existing = deduped.get(candidate.id);
|
|
20976
|
+
if (!existing || candidate.score > existing.score) deduped.set(candidate.id, candidate);
|
|
20977
|
+
}
|
|
20978
|
+
return [...deduped.values()].sort((left, right) => right.score - left.score || left.id.localeCompare(right.id)).slice(0, limit);
|
|
20979
|
+
}
|
|
20980
|
+
async #drain(scope) {
|
|
20981
|
+
let processed = 0;
|
|
20982
|
+
for (let batch = 0; batch < MAX_DRAIN_BATCHES; batch++) {
|
|
20983
|
+
const entries = await this.#knowledge.claimSemanticOutbox({
|
|
20984
|
+
workerId: this.#workerId,
|
|
20985
|
+
limit: this.#batchSize,
|
|
20986
|
+
scope
|
|
20987
|
+
});
|
|
20988
|
+
if (entries.length === 0) {
|
|
20989
|
+
const [pending, processing] = await Promise.all([this.#knowledge.listSemanticOutbox({
|
|
20990
|
+
status: "pending",
|
|
20991
|
+
scope,
|
|
20992
|
+
limit: 1
|
|
20993
|
+
}), this.#knowledge.listSemanticOutbox({
|
|
20994
|
+
status: "processing",
|
|
20995
|
+
scope,
|
|
20996
|
+
limit: 1
|
|
20997
|
+
})]);
|
|
20998
|
+
if (pending.length > 0 || processing.length > 0) throw new StaleKnowledgeSemanticIndexError("Knowledge semantic index is stale: a visible operation is pending or being processed by another worker.");
|
|
20999
|
+
return processed;
|
|
21000
|
+
}
|
|
21001
|
+
for (let index = 0; index < entries.length; index++) {
|
|
21002
|
+
const entry = entries[index];
|
|
21003
|
+
try {
|
|
21004
|
+
await this.#apply(entry);
|
|
21005
|
+
await this.#knowledge.completeSemanticOutbox({
|
|
21006
|
+
ids: [entry.id],
|
|
21007
|
+
workerId: this.#workerId
|
|
21008
|
+
});
|
|
21009
|
+
processed++;
|
|
21010
|
+
} catch (error) {
|
|
21011
|
+
await this.#knowledge.releaseSemanticOutbox({
|
|
21012
|
+
ids: entries.slice(index).map((pendingEntry) => pendingEntry.id),
|
|
21013
|
+
workerId: this.#workerId
|
|
21014
|
+
});
|
|
21015
|
+
throw new StaleKnowledgeSemanticIndexError(`Knowledge semantic index is stale because operation ${entry.id} could not be applied.`, { cause: error });
|
|
21016
|
+
}
|
|
21017
|
+
}
|
|
21018
|
+
}
|
|
21019
|
+
throw new StaleKnowledgeSemanticIndexError(`Knowledge semantic index remained stale after ${MAX_DRAIN_BATCHES} processing batches.`);
|
|
21020
|
+
}
|
|
21021
|
+
async #apply(entry) {
|
|
21022
|
+
if (entry.operation === "delete") {
|
|
21023
|
+
await this.#deleteDocument(entry.documentId);
|
|
21024
|
+
return;
|
|
21025
|
+
}
|
|
21026
|
+
const document = await this.#loadDocument(entry);
|
|
21027
|
+
if (!document) {
|
|
21028
|
+
await this.#deleteDocument(entry.documentId);
|
|
21029
|
+
return;
|
|
21030
|
+
}
|
|
21031
|
+
const embedding = (await this.#embedder.doEmbed({
|
|
21032
|
+
values: [document.text],
|
|
21033
|
+
...this.#embedderOptions ?? {}
|
|
21034
|
+
})).embeddings[0];
|
|
21035
|
+
if (!embedding?.length) throw new Error(`Embedder returned no vector for ${entry.documentId}`);
|
|
21036
|
+
const indexName = this.#indexName(embedding.length);
|
|
21037
|
+
const indexes = await this.#knowledgeIndexes();
|
|
21038
|
+
if (!indexes.includes(indexName)) await this.#vector.createIndex({
|
|
21039
|
+
indexName,
|
|
21040
|
+
dimension: embedding.length
|
|
21041
|
+
});
|
|
21042
|
+
for (const existingIndex of indexes) if (existingIndex !== indexName) await this.#vector.deleteVectors({
|
|
21043
|
+
indexName: existingIndex,
|
|
21044
|
+
ids: [entry.documentId]
|
|
21045
|
+
});
|
|
21046
|
+
await this.#vector.upsert({
|
|
21047
|
+
indexName,
|
|
21048
|
+
ids: [entry.documentId],
|
|
21049
|
+
vectors: [embedding],
|
|
21050
|
+
metadata: [this.#metadata(document)]
|
|
21051
|
+
});
|
|
21052
|
+
}
|
|
21053
|
+
async #loadDocument(entry) {
|
|
21054
|
+
if (entry.documentType === "node") {
|
|
21055
|
+
const node = await this.#knowledge.getNode(entry.documentId.slice(15));
|
|
21056
|
+
if (!node || node.mergedInto) return null;
|
|
21057
|
+
return {
|
|
21058
|
+
text: `${node.name}\n${node.content ?? ""}`,
|
|
21059
|
+
name: node.name,
|
|
21060
|
+
scope: node.scope,
|
|
21061
|
+
recordId: node.id,
|
|
21062
|
+
type: "node"
|
|
21063
|
+
};
|
|
21064
|
+
}
|
|
21065
|
+
const record = await this.#knowledge.getKnowledge({
|
|
21066
|
+
id: entry.documentId.slice(17),
|
|
21067
|
+
includeDeleted: true
|
|
21068
|
+
});
|
|
21069
|
+
if (!record || record.deletedAt) return null;
|
|
21070
|
+
const node = await this.#knowledge.getNode(record.node);
|
|
21071
|
+
if (!node) return null;
|
|
21072
|
+
return {
|
|
21073
|
+
text: `${node.name}\n${record.text}`,
|
|
21074
|
+
name: node.name,
|
|
21075
|
+
scope: record.scope,
|
|
21076
|
+
recordId: node.id,
|
|
21077
|
+
type: "record"
|
|
21078
|
+
};
|
|
21079
|
+
}
|
|
21080
|
+
async #deleteDocument(documentId) {
|
|
21081
|
+
for (const indexName of await this.#knowledgeIndexes()) await this.#vector.deleteVectors({
|
|
21082
|
+
indexName,
|
|
21083
|
+
ids: [documentId]
|
|
21084
|
+
});
|
|
21085
|
+
}
|
|
21086
|
+
async #knowledgeIndexes() {
|
|
21087
|
+
const prefix = `knowledge${this.#vector.indexSeparator ?? "_"}documents`;
|
|
21088
|
+
return (await this.#vector.listIndexes()).filter((index) => index === prefix || index.startsWith(`${prefix}${this.#vector.indexSeparator ?? "_"}dimension`));
|
|
21089
|
+
}
|
|
21090
|
+
#indexName(dimension) {
|
|
21091
|
+
const separator = this.#vector.indexSeparator ?? "_";
|
|
21092
|
+
return `knowledge${separator}documents${separator}dimension${separator}${dimension}`;
|
|
21093
|
+
}
|
|
21094
|
+
#metadata(document) {
|
|
21095
|
+
const metadata = {
|
|
21096
|
+
document_type: document.type,
|
|
21097
|
+
record_id: document.recordId,
|
|
21098
|
+
name: document.name,
|
|
21099
|
+
scope: [...document.scope],
|
|
21100
|
+
scope_key: document.scope.join(""),
|
|
21101
|
+
text: document.text
|
|
21102
|
+
};
|
|
21103
|
+
for (const entry of document.scope) {
|
|
21104
|
+
const separator = entry.indexOf(":");
|
|
21105
|
+
metadata[`scope_${entry.slice(0, separator)}`] = entry.slice(separator + 1);
|
|
21106
|
+
}
|
|
21107
|
+
return metadata;
|
|
21108
|
+
}
|
|
21109
|
+
};
|
|
21110
|
+
var subconscious_exports = /* @__PURE__ */ __exportAll({
|
|
21111
|
+
DEFAULT_MAX_PINS: () => 20,
|
|
21112
|
+
DEFAULT_PINNED_MAX_CHARACTERS: () => DEFAULT_PINNED_MAX_CHARACTERS,
|
|
21113
|
+
MAX_PINNED_MAX_CHARACTERS: () => MAX_PINNED_MAX_CHARACTERS,
|
|
21114
|
+
PINNED_DELTA_TAG: () => PINNED_DELTA_TAG,
|
|
21115
|
+
PINNED_NODE_KIND: () => PINNED_NODE_KIND,
|
|
21116
|
+
PINNED_NODE_NAME: () => PINNED_NODE_NAME,
|
|
21117
|
+
PINNED_NODE_SCOPE_LEVEL: () => PINNED_NODE_SCOPE_LEVEL,
|
|
21118
|
+
PINNED_SNAPSHOT_TAG: () => PINNED_SNAPSHOT_TAG,
|
|
21119
|
+
PinnedStateProcessor: () => PinnedStateProcessor,
|
|
21120
|
+
SUBCONSCIOUS_ACTIVITY_STATE_ID: () => SUBCONSCIOUS_ACTIVITY_STATE_ID,
|
|
21121
|
+
SUBCONSCIOUS_PINS_STATE_ID: () => SUBCONSCIOUS_PINS_STATE_ID,
|
|
21122
|
+
Subconscious: () => Subconscious
|
|
21123
|
+
});
|
|
21124
|
+
const BUILT_IN_OBSERVATION = /* @__PURE__ */ new Set(["capture", "remind"]);
|
|
21125
|
+
const BUILT_IN_REFLECTION = /* @__PURE__ */ new Set(["curate", "learn"]);
|
|
21126
|
+
const DEFAULT_MAX_STEPS = 5;
|
|
21127
|
+
const DEFAULT_RECENT_UPDATES = 10;
|
|
21128
|
+
const MAX_RECENT_UPDATES = 100;
|
|
21129
|
+
function entryName(entry) {
|
|
21130
|
+
return typeof entry === "string" ? entry : entry.name.trim();
|
|
21131
|
+
}
|
|
21132
|
+
function assertUniqueNames(entries, phase) {
|
|
21133
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21134
|
+
for (const entry of entries) {
|
|
21135
|
+
const name = entryName(entry);
|
|
21136
|
+
if (!name) throw new Error(`Subconscious ${phase} agent name is required.`);
|
|
21137
|
+
if (seen.has(name)) throw new Error(`Duplicate Subconscious ${phase} agent: ${name}`);
|
|
21138
|
+
seen.add(name);
|
|
21139
|
+
}
|
|
21140
|
+
}
|
|
21141
|
+
function boundedSteps(entry, fallback) {
|
|
21142
|
+
const steps = entry?.maxSteps ?? fallback;
|
|
21143
|
+
if (!Number.isInteger(steps) || steps < 1 || steps > 25) throw new Error("Subconscious maxSteps must be an integer between 1 and 25.");
|
|
21144
|
+
return steps;
|
|
21145
|
+
}
|
|
21146
|
+
function resolveExtractor(entry) {
|
|
21147
|
+
const config = typeof entry === "string" ? void 0 : entry;
|
|
21148
|
+
const name = entryName(entry);
|
|
21149
|
+
return {
|
|
21150
|
+
name,
|
|
21151
|
+
instructions: config?.instructions,
|
|
21152
|
+
builtIn: name === "capture"
|
|
21153
|
+
};
|
|
21154
|
+
}
|
|
21155
|
+
function resolveAgent(entry, builtIns, globalModel, globalMaxSteps) {
|
|
21156
|
+
const config = typeof entry === "string" ? void 0 : entry;
|
|
21157
|
+
const name = entryName(entry);
|
|
21158
|
+
return {
|
|
21159
|
+
name,
|
|
21160
|
+
instructions: config?.instructions,
|
|
21161
|
+
model: config?.model ?? globalModel,
|
|
21162
|
+
agent: config?.agent,
|
|
21163
|
+
maxSteps: boundedSteps(config, globalMaxSteps),
|
|
21164
|
+
builtIn: builtIns.has(name)
|
|
21165
|
+
};
|
|
21166
|
+
}
|
|
21167
|
+
/**
|
|
21168
|
+
* Configures experimental autonomous knowledge extraction and reflection.
|
|
21169
|
+
*
|
|
21170
|
+
* @experimental This API may change without notice.
|
|
21171
|
+
*/
|
|
21172
|
+
var Subconscious = class {
|
|
21173
|
+
config;
|
|
21174
|
+
resolved;
|
|
21175
|
+
constructor(config = {}) {
|
|
21176
|
+
const observation = config.observation ?? ["capture", "remind"];
|
|
21177
|
+
const reflection = config.reflection ?? ["curate", "learn"];
|
|
21178
|
+
assertUniqueNames(observation, "observation");
|
|
21179
|
+
assertUniqueNames(reflection, "reflection");
|
|
21180
|
+
const maxSteps = boundedSteps(config, DEFAULT_MAX_STEPS);
|
|
21181
|
+
for (const entry of observation) this.#validateObservationEntry(entry);
|
|
21182
|
+
for (const entry of reflection) this.#validateReflectionEntry(entry);
|
|
21183
|
+
const recentUpdates = config.activity === false ? false : config.activity?.recentUpdates ?? DEFAULT_RECENT_UPDATES;
|
|
21184
|
+
if (recentUpdates !== false && (!Number.isInteger(recentUpdates) || recentUpdates < 1 || recentUpdates > MAX_RECENT_UPDATES)) throw new Error(`Subconscious activity.recentUpdates must be an integer between 1 and ${MAX_RECENT_UPDATES}.`);
|
|
21185
|
+
const pins = config.pins === void 0 || config.pins === false ? false : {
|
|
21186
|
+
maxPins: (config.pins === true ? void 0 : config.pins.maxPins) ?? 20,
|
|
21187
|
+
maxCharacters: (config.pins === true ? void 0 : config.pins.maxCharacters) ?? 2e3,
|
|
21188
|
+
capturePinning: (config.pins === true ? void 0 : config.pins.capturePinning) ?? false
|
|
21189
|
+
};
|
|
21190
|
+
if (pins !== false) {
|
|
21191
|
+
if (!Number.isInteger(pins.maxPins) || pins.maxPins < 1) throw new Error("Subconscious pins.maxPins must be a positive integer.");
|
|
21192
|
+
if (!Number.isInteger(pins.maxCharacters) || pins.maxCharacters < 1 || pins.maxCharacters > 8e3) throw new Error(`Subconscious pins.maxCharacters must be an integer between 1 and ${MAX_PINNED_MAX_CHARACTERS}.`);
|
|
21193
|
+
}
|
|
21194
|
+
if (config.curationCadence !== void 0 && (!Number.isInteger(config.curationCadence) || config.curationCadence < 1)) throw new Error("Subconscious curationCadence must be a positive integer.");
|
|
21195
|
+
this.config = Object.freeze({
|
|
21196
|
+
...config,
|
|
21197
|
+
observation: [...observation],
|
|
21198
|
+
reflection: [...reflection]
|
|
21199
|
+
});
|
|
21200
|
+
this.resolved = Object.freeze({
|
|
21201
|
+
observation: observation.map((entry) => entryName(entry) === "remind" ? resolveAgent(entry, BUILT_IN_OBSERVATION, config.model, maxSteps) : resolveExtractor(entry)),
|
|
21202
|
+
reflection: reflection.map((entry) => resolveAgent(entry, BUILT_IN_REFLECTION, config.model, maxSteps)),
|
|
21203
|
+
defaultScope: config.defaultScope ?? "resource",
|
|
21204
|
+
maxScope: config.maxScope,
|
|
21205
|
+
learnedGuidance: config.learnedGuidance !== false,
|
|
21206
|
+
tools: config.tools !== false,
|
|
21207
|
+
activity: recentUpdates === false ? false : { recentUpdates },
|
|
21208
|
+
pins,
|
|
21209
|
+
curationCadence: config.curationCadence
|
|
21210
|
+
});
|
|
21211
|
+
}
|
|
21212
|
+
createObservationExtractors(omModel) {
|
|
21213
|
+
const extractors = [];
|
|
21214
|
+
for (const entry of this.config.observation ?? []) {
|
|
21215
|
+
const name = entryName(entry);
|
|
21216
|
+
if (name === "capture") extractors.push(new SubconsciousCaptureExtractor({
|
|
21217
|
+
config: typeof entry === "string" ? void 0 : entry,
|
|
21218
|
+
defaultScope: this.resolved.defaultScope,
|
|
21219
|
+
maxScope: this.resolved.maxScope,
|
|
21220
|
+
learnedGuidance: this.resolved.learnedGuidance,
|
|
21221
|
+
activityRecentUpdates: this.resolved.activity === false ? void 0 : this.resolved.activity.recentUpdates,
|
|
21222
|
+
pins: this.resolved.pins
|
|
21223
|
+
}));
|
|
21224
|
+
else if (name === "remind") {
|
|
21225
|
+
const resolved = this.resolved.observation.find((agent) => agent.name === name);
|
|
21226
|
+
if (resolved) extractors.push(new SubconsciousRemindExtractor(resolved, omModel));
|
|
21227
|
+
} else if (!BUILT_IN_OBSERVATION.has(name)) {
|
|
21228
|
+
const custom = entry;
|
|
21229
|
+
extractors.push(new Extractor({
|
|
21230
|
+
name: custom.name,
|
|
21231
|
+
instructions: custom.instructions?.trim() || `Extract ${custom.name} from the current observations.`,
|
|
21232
|
+
schema: custom.schema,
|
|
21233
|
+
metadataKeyPath: false,
|
|
21234
|
+
includePreviousExtraction: false,
|
|
21235
|
+
onExtracted: custom.onExtracted
|
|
21236
|
+
}));
|
|
21237
|
+
}
|
|
21238
|
+
}
|
|
21239
|
+
return extractors;
|
|
21240
|
+
}
|
|
21241
|
+
#validateObservationEntry(entry) {
|
|
21242
|
+
const name = entryName(entry);
|
|
21243
|
+
if (typeof entry === "string") {
|
|
21244
|
+
if (!BUILT_IN_OBSERVATION.has(name)) throw new Error(`Unknown Subconscious observation agent: ${name}`);
|
|
21245
|
+
return;
|
|
21246
|
+
}
|
|
21247
|
+
if (BUILT_IN_OBSERVATION.has(name)) {
|
|
21248
|
+
if (name === "capture") {
|
|
21249
|
+
if ("model" in entry || "maxSteps" in entry) throw new Error("Subconscious capture shares the Observer model and does not accept model or maxSteps.");
|
|
21250
|
+
if ("schema" in entry && entry.schema && (!("onExtracted" in entry) || typeof entry.onExtracted !== "function")) throw new Error("A custom capture schema requires an onExtracted hook that handles its output.");
|
|
21251
|
+
}
|
|
21252
|
+
return;
|
|
21253
|
+
}
|
|
21254
|
+
if ("model" in entry || "maxSteps" in entry) throw new Error(`Subconscious observation extractor "${name}" shares the Observer model and does not accept model or maxSteps.`);
|
|
21255
|
+
if (!("schema" in entry) || !entry.schema || !("onExtracted" in entry) || typeof entry.onExtracted !== "function") throw new Error(`Custom Subconscious observation agent "${name}" requires schema and onExtracted.`);
|
|
21256
|
+
}
|
|
21257
|
+
#validateReflectionEntry(entry) {
|
|
21258
|
+
const name = entryName(entry);
|
|
21259
|
+
if (typeof entry === "string") {
|
|
21260
|
+
if (!BUILT_IN_REFLECTION.has(name)) throw new Error(`Unknown Subconscious reflection agent: ${name}`);
|
|
21261
|
+
return;
|
|
21262
|
+
}
|
|
21263
|
+
if (BUILT_IN_REFLECTION.has(name) && "agent" in entry && entry.agent) throw new Error(`Built-in Subconscious reflection agent "${name}" cannot be replaced with a custom agent.`);
|
|
21264
|
+
if (!BUILT_IN_REFLECTION.has(name) && !entry.instructions?.trim() && !("agent" in entry && entry.agent)) throw new Error(`Custom Subconscious reflection agent "${name}" requires instructions or agent.`);
|
|
21265
|
+
}
|
|
21266
|
+
};
|
|
21267
|
+
const CURATION_AGENT = "curate";
|
|
21268
|
+
const DEFAULT_INSTRUCTIONS$1 = `Maintain durable scoped knowledge from the committed observation worklist.
|
|
21269
|
+
|
|
21270
|
+
Use the read tools to inspect existing nodes, knowledge records, mentions, backlinks, and long-form node content. Use the write tools to merge true duplicates, repair names and links, soft-delete superseded knowledge records, rescope knowledge records only when justified and permitted by their ceilings, and synthesize useful node content. Never restore deleted knowledge records. Never invent provenance, capture timestamps, scopes, ceilings, IDs, or versions; those are enforced by code. Resolve optimistic-concurrency conflicts by reading the latest record and retrying the intended mutation. Keep the reserved capture-guidance node concise and update it only with durable guidance that will improve future capture.
|
|
21271
|
+
|
|
21272
|
+
Process the worklist in ID order. Every time you finish processing a KnowledgeRecord, include <curation-complete through="RECORD_ID" /> in your next text response with that record's ID. The latest marker is your acknowledged cursor, so progress survives if you run out of steps mid-batch. Your final response must end with the marker for the last KnowledgeRecord you fully processed. If you cannot finish the batch, acknowledge only the last KnowledgeRecord you did finish. Do not emit a completion marker when no KnowledgeRecord was fully processed.`;
|
|
21273
|
+
const PINNED_INSTRUCTIONS = `Maintain the pin set with knowledge_pin, knowledge_edit_pin, and knowledge_unpin. Pinned entries are delivered to the main agent on every turn, so they cost tokens permanently and must stay short. Pin only knowledge that should apply without being asked for, such as standing instructions, durable preferences, and hard constraints. Pin only knowledge that is BOTH costly to rediscover AND not the kind of thing a future agent would think to search for; anything a reminder can surface on demand does not belong in the pin set. Unpin an entry as soon as it stops being unconditionally true.`;
|
|
21274
|
+
function resolveScope$1(context) {
|
|
21275
|
+
const organizationId = context.requestContext?.get("organizationId");
|
|
21276
|
+
if (typeof organizationId !== "string" || !organizationId.trim()) throw new Error("Subconscious curate requires organizationId in the request context.");
|
|
21277
|
+
return (0, _mastra_core_storage.canonicalizeKnowledgeScope)([
|
|
21278
|
+
`org:${organizationId}`,
|
|
21279
|
+
`resource:${resolveKnowledgeResourceId(context.requestContext, context.resourceId)}`,
|
|
21280
|
+
`thread:${context.parentThreadId}`
|
|
21281
|
+
]);
|
|
21282
|
+
}
|
|
21283
|
+
async function readWorklist$1(store, sourceThreadId, scope, after) {
|
|
21284
|
+
const records = [];
|
|
21285
|
+
let cursor = after;
|
|
21286
|
+
do {
|
|
21287
|
+
const page = await store.knowledgeBySource({
|
|
21288
|
+
sourceThreadId,
|
|
21289
|
+
scope,
|
|
21290
|
+
after: cursor,
|
|
21291
|
+
limit: 100,
|
|
21292
|
+
includeDeleted: true
|
|
21293
|
+
});
|
|
21294
|
+
records.push(...page.records);
|
|
21295
|
+
cursor = page.nextCursor;
|
|
21296
|
+
} while (cursor && records.length < 500);
|
|
21297
|
+
return {
|
|
21298
|
+
records,
|
|
21299
|
+
hasMore: Boolean(cursor)
|
|
21300
|
+
};
|
|
21301
|
+
}
|
|
21302
|
+
function createCuratorHandler(memory, subconscious, curatorMemory = memory, options) {
|
|
21303
|
+
const config = subconscious.reflection.find((agent) => agent.name === CURATION_AGENT);
|
|
21304
|
+
if (!config) return async () => "no-op";
|
|
21305
|
+
return async (context) => {
|
|
21306
|
+
let store;
|
|
21307
|
+
let scope;
|
|
21308
|
+
try {
|
|
21309
|
+
scope = resolveScope$1(context);
|
|
21310
|
+
store = await memory.storage.getStore("knowledge");
|
|
21311
|
+
if (!store) throw new Error("Subconscious curate requires a configured knowledge storage domain.");
|
|
21312
|
+
const cursor = await store.getCurationCursor({
|
|
21313
|
+
sourceThreadId: context.parentThreadId,
|
|
21314
|
+
agent: CURATION_AGENT
|
|
21315
|
+
});
|
|
21316
|
+
const worklist = await readWorklist$1(store, context.parentThreadId, scope, cursor?.lastKnowledgeId);
|
|
21317
|
+
if (!worklist.records.length && !context.observations.trim()) return "no-op";
|
|
21318
|
+
const result = await (await createCuratorAgent(memory, curatorMemory, context, scope, config, subconscious, options?.omModel)).generate(`Parent thread: ${context.parentThreadId}\nCurrent time: ${(/* @__PURE__ */ new Date()).toISOString()}\nWorklist truncated: ${worklist.hasMore}\n\nCommitted pre-reflection observations:\n${context.observations}\n\nNew KnowledgeRecord worklist:\n${JSON.stringify(worklist.records)}`, {
|
|
21319
|
+
requestContext: context.requestContext,
|
|
21320
|
+
abortSignal: context.abortSignal,
|
|
21321
|
+
maxSteps: config.maxSteps,
|
|
21322
|
+
memory: {
|
|
21323
|
+
thread: `subconscious:${context.parentThreadId}:curate`,
|
|
21324
|
+
resource: context.resourceId
|
|
21325
|
+
}
|
|
21326
|
+
});
|
|
21327
|
+
if (worklist.records.length) {
|
|
21328
|
+
const acknowledgedId = [...result.text.matchAll(/<curation-complete\s+through=["']([^"']+)["']\s*\/>/gi)].at(-1)?.[1];
|
|
21329
|
+
if (!acknowledgedId || !worklist.records.some((record) => record.id === acknowledgedId)) throw new Error("Curator did not acknowledge a valid processed KnowledgeRecord cursor.");
|
|
21330
|
+
await store.advanceCurationCursor({
|
|
21331
|
+
sourceThreadId: context.parentThreadId,
|
|
21332
|
+
agent: CURATION_AGENT,
|
|
21333
|
+
lastKnowledgeId: acknowledgedId
|
|
21334
|
+
});
|
|
21335
|
+
}
|
|
21336
|
+
return "ran";
|
|
21337
|
+
} catch (error) {
|
|
21338
|
+
const message = `curate: ${error instanceof Error ? error.message : String(error)}`;
|
|
21339
|
+
await context.writer?.custom({
|
|
21340
|
+
type: "data-subconscious-error",
|
|
21341
|
+
data: {
|
|
21342
|
+
agent: "curate",
|
|
21343
|
+
error: message
|
|
21344
|
+
}
|
|
21345
|
+
});
|
|
21346
|
+
if (store && scope) await publishSubconsciousActivity({
|
|
21347
|
+
store,
|
|
21348
|
+
scope,
|
|
21349
|
+
recentUpdates: subconscious.activity === false ? 10 : subconscious.activity.recentUpdates,
|
|
21350
|
+
sendStateSignal: context.sendStateSignal,
|
|
21351
|
+
errors: [message]
|
|
21352
|
+
});
|
|
21353
|
+
else await publishSubconsciousError({
|
|
21354
|
+
error: message,
|
|
21355
|
+
sendStateSignal: context.sendStateSignal
|
|
21356
|
+
});
|
|
21357
|
+
throw error;
|
|
21358
|
+
}
|
|
21359
|
+
};
|
|
21360
|
+
}
|
|
21361
|
+
async function createCuratorAgent(memory, curatorMemory, context, scope, config, subconscious, omModel) {
|
|
21362
|
+
const model = await resolveSubconsciousAgentModel({
|
|
21363
|
+
config,
|
|
21364
|
+
omModel,
|
|
21365
|
+
mainAgent: context.mainAgent,
|
|
21366
|
+
requestContext: context.requestContext
|
|
21367
|
+
});
|
|
21368
|
+
if (!model) throw new Error("Subconscious curate requires the main agent to resolve its model.");
|
|
21369
|
+
return new _mastra_core_agent.Agent({
|
|
21370
|
+
id: `subconscious-curate-${context.parentThreadId}`,
|
|
21371
|
+
name: "Subconscious Curate",
|
|
21372
|
+
instructions: [
|
|
21373
|
+
DEFAULT_INSTRUCTIONS$1,
|
|
21374
|
+
subconscious.pins ? PINNED_INSTRUCTIONS : void 0,
|
|
21375
|
+
config.instructions?.trim()
|
|
21376
|
+
].filter(Boolean).join("\n\n"),
|
|
21377
|
+
model,
|
|
21378
|
+
memory: curatorMemory,
|
|
21379
|
+
tools: {
|
|
21380
|
+
...createKnowledgeTools(memory),
|
|
21381
|
+
...createKnowledgeWriteTools(memory, {
|
|
21382
|
+
scope,
|
|
21383
|
+
sourceThreadId: context.parentThreadId,
|
|
21384
|
+
defaultScope: subconscious.defaultScope,
|
|
21385
|
+
maxScope: subconscious.maxScope
|
|
21386
|
+
}),
|
|
21387
|
+
...subconscious.pins ? createPinnedTools(memory, {
|
|
21388
|
+
scope,
|
|
21389
|
+
sourceThreadId: context.parentThreadId,
|
|
21390
|
+
defaultScope: subconscious.defaultScope,
|
|
21391
|
+
maxScope: subconscious.maxScope,
|
|
21392
|
+
maxPins: subconscious.pins.maxPins,
|
|
21393
|
+
maxCharacters: subconscious.pins.maxCharacters
|
|
21394
|
+
}) : {}
|
|
21395
|
+
}
|
|
21396
|
+
});
|
|
21397
|
+
}
|
|
21398
|
+
const LEARN_AGENT = "learn";
|
|
21399
|
+
const ULID_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
21400
|
+
const DEFAULT_INSTRUCTIONS = `Learn reusable skills from the full pre-reflection observations and pending knowledge records.
|
|
21401
|
+
|
|
21402
|
+
A skill is a repeatable procedure with ordered actions, a trigger or context, and a success or recovery outcome. Do not learn one-off events, isolated preferences, knowledge records, or procedures supported by fewer than two distinct pending knowledge records. Search existing kind:skill nodes by exact name before writing so updates extend one skill rather than creating duplicates.
|
|
21403
|
+
|
|
21404
|
+
Use knowledge_record_skill for every skill creation or evidence update. It validates the evidence frontier and writes retry-safe evidence. You may use the other scoped knowledge tools for research and maintenance, but never restore deleted records, invent provenance or versions, or write outside the source scope.
|
|
21405
|
+
|
|
21406
|
+
Process pending records in ID order. End with <learning-complete through="RECORD_ID" /> naming the last pending record you reviewed, even when no reusable skill was found. Acknowledge only records you fully reviewed.`;
|
|
21407
|
+
function resolveScope(context) {
|
|
21408
|
+
const organizationId = context.requestContext?.get("organizationId");
|
|
21409
|
+
if (typeof organizationId !== "string" || !organizationId.trim()) throw new Error("Subconscious learn requires organizationId in the request context.");
|
|
21410
|
+
return (0, _mastra_core_storage.canonicalizeKnowledgeScope)([
|
|
21411
|
+
`org:${organizationId}`,
|
|
21412
|
+
`resource:${resolveKnowledgeResourceId(context.requestContext, context.resourceId)}`,
|
|
21413
|
+
`thread:${context.parentThreadId}`
|
|
21414
|
+
]);
|
|
21415
|
+
}
|
|
21416
|
+
async function readWorklist(store, sourceThreadId, scope, after) {
|
|
21417
|
+
const records = [];
|
|
21418
|
+
let cursor = after;
|
|
21419
|
+
do {
|
|
21420
|
+
const page = await store.knowledgeBySource({
|
|
21421
|
+
sourceThreadId,
|
|
21422
|
+
scope,
|
|
21423
|
+
after: cursor,
|
|
21424
|
+
limit: 100
|
|
21425
|
+
});
|
|
21426
|
+
records.push(...page.records);
|
|
21427
|
+
cursor = page.nextCursor;
|
|
21428
|
+
} while (cursor && records.length < 500);
|
|
21429
|
+
return {
|
|
21430
|
+
records,
|
|
21431
|
+
hasMore: Boolean(cursor)
|
|
21432
|
+
};
|
|
21433
|
+
}
|
|
21434
|
+
function evidenceRecordId(sourceRecordId, skillName) {
|
|
21435
|
+
const hash = (0, crypto$1.createHash)("sha256").update(`${skillName.trim().toLocaleLowerCase()}\0${sourceRecordId}`).digest();
|
|
21436
|
+
let suffix = "";
|
|
21437
|
+
for (let index = 0; index < 16; index++) suffix += ULID_ALPHABET[hash[index] & 31];
|
|
21438
|
+
return `${sourceRecordId.slice(0, 10)}${suffix}`;
|
|
21439
|
+
}
|
|
21440
|
+
function createLearnerRecordSkillTool(input) {
|
|
21441
|
+
return (0, _mastra_core_tools.createTool)({
|
|
21442
|
+
id: "knowledge_record_skill",
|
|
21443
|
+
description: "Create or update one reusable skill using at least two distinct pending knowledge records. Evidence writes are idempotent across retries.",
|
|
21444
|
+
inputSchema: {
|
|
21445
|
+
type: "object",
|
|
21446
|
+
properties: {
|
|
21447
|
+
name: {
|
|
21448
|
+
type: "string",
|
|
21449
|
+
minLength: 1
|
|
21450
|
+
},
|
|
21451
|
+
procedure: {
|
|
21452
|
+
type: "string",
|
|
21453
|
+
minLength: 1
|
|
21454
|
+
},
|
|
21455
|
+
sourceRecordIds: {
|
|
21456
|
+
type: "array",
|
|
21457
|
+
items: {
|
|
21458
|
+
type: "string",
|
|
21459
|
+
minLength: 1
|
|
21460
|
+
},
|
|
21461
|
+
minItems: 2,
|
|
21462
|
+
uniqueItems: true
|
|
21463
|
+
}
|
|
21464
|
+
},
|
|
21465
|
+
required: [
|
|
21466
|
+
"name",
|
|
21467
|
+
"procedure",
|
|
21468
|
+
"sourceRecordIds"
|
|
21469
|
+
],
|
|
21470
|
+
additionalProperties: false
|
|
21471
|
+
},
|
|
21472
|
+
execute: async (raw) => {
|
|
21473
|
+
const value = raw;
|
|
21474
|
+
const sourceIds = [...new Set(value.sourceRecordIds)];
|
|
21475
|
+
const pending = new Map(input.pendingRecords.map((record) => [record.id, record]));
|
|
21476
|
+
if (sourceIds.length < 2 || sourceIds.some((id) => !pending.has(id))) throw new Error("Skill evidence requires at least two distinct records from the pending learner worklist.");
|
|
21477
|
+
const normalizedName = value.name.trim();
|
|
21478
|
+
if (input.state.recordedName && input.state.recordedName.toLocaleLowerCase() !== normalizedName.toLocaleLowerCase()) throw new Error("The learner may record at most one skill per reflection.");
|
|
21479
|
+
input.state.recordedName = normalizedName;
|
|
21480
|
+
const nodeScope = (0, _mastra_core_storage.expandKnowledgeScope)(input.scope, input.defaultScope);
|
|
21481
|
+
let node = await input.store.resolveNode({
|
|
21482
|
+
name: normalizedName,
|
|
21483
|
+
scope: input.scope
|
|
21484
|
+
});
|
|
21485
|
+
if (node && node.kind !== "skill") throw new Error(`Knowledge node is not a skill: ${normalizedName}`);
|
|
21486
|
+
node ??= await input.store.createNode({
|
|
21487
|
+
name: normalizedName,
|
|
21488
|
+
kind: "skill",
|
|
21489
|
+
scope: nodeScope
|
|
21490
|
+
});
|
|
21491
|
+
const evidence = [];
|
|
21492
|
+
for (const sourceId of sourceIds) {
|
|
21493
|
+
const id = evidenceRecordId(sourceId, normalizedName);
|
|
21494
|
+
const existing = await input.store.getKnowledge({ id });
|
|
21495
|
+
if (existing) {
|
|
21496
|
+
evidence.push(existing);
|
|
21497
|
+
continue;
|
|
21498
|
+
}
|
|
21499
|
+
const source = pending.get(sourceId);
|
|
21500
|
+
try {
|
|
21501
|
+
evidence.push(await input.store.appendKnowledge({
|
|
21502
|
+
id,
|
|
21503
|
+
node: node.id,
|
|
21504
|
+
text: `Procedure: ${value.procedure.trim()} Evidence source: ${source.id}.`,
|
|
21505
|
+
scope: source.scope,
|
|
21506
|
+
sourceThreadId: `subconscious:${input.parentThreadId}:learn`,
|
|
21507
|
+
maxScope: source.maxScope ?? input.maxScope,
|
|
21508
|
+
resolutionScope: input.scope,
|
|
21509
|
+
defaultScope: nodeScope
|
|
21510
|
+
}));
|
|
21511
|
+
} catch (error) {
|
|
21512
|
+
const raced = await input.store.getKnowledge({ id });
|
|
21513
|
+
if (!raced) throw error;
|
|
21514
|
+
evidence.push(raced);
|
|
21515
|
+
}
|
|
21516
|
+
}
|
|
21517
|
+
return {
|
|
21518
|
+
node,
|
|
21519
|
+
evidence
|
|
21520
|
+
};
|
|
21521
|
+
}
|
|
21522
|
+
});
|
|
21523
|
+
}
|
|
21524
|
+
function composeReflectionAgentHandlers(handlers) {
|
|
21525
|
+
return async (context) => {
|
|
21526
|
+
for (const handler of handlers) try {
|
|
21527
|
+
await handler(context);
|
|
21528
|
+
} catch (error) {
|
|
21529
|
+
if (context.abortSignal?.aborted) throw error;
|
|
21530
|
+
}
|
|
21531
|
+
};
|
|
21532
|
+
}
|
|
21533
|
+
function createLearnerHandler(memory, subconscious, learnerMemory = memory, options) {
|
|
21534
|
+
const config = subconscious.reflection.find((agent) => agent.name === LEARN_AGENT);
|
|
21535
|
+
if (!config) return async () => {};
|
|
21536
|
+
return async (context) => {
|
|
21537
|
+
let store;
|
|
21538
|
+
let scope;
|
|
21539
|
+
try {
|
|
21540
|
+
scope = resolveScope(context);
|
|
21541
|
+
store = await memory.storage.getStore("knowledge");
|
|
21542
|
+
if (!store) throw new Error("Subconscious learn requires a configured knowledge storage domain.");
|
|
21543
|
+
const cursor = await store.getCurationCursor({
|
|
21544
|
+
sourceThreadId: context.parentThreadId,
|
|
21545
|
+
agent: LEARN_AGENT
|
|
21546
|
+
});
|
|
21547
|
+
const worklist = await readWorklist(store, context.parentThreadId, scope, cursor?.lastKnowledgeId);
|
|
21548
|
+
if (!worklist.records.length) return;
|
|
21549
|
+
const acknowledgedId = (await (await createLearnerAgent(memory, learnerMemory, context, scope, worklist.records, config, subconscious, options?.omModel)).generate(`Parent thread: ${context.parentThreadId}\nCurrent time: ${(/* @__PURE__ */ new Date()).toISOString()}\nWorklist truncated: ${worklist.hasMore}\n\nFull pre-reflection observations:\n${context.observations}\n\nPending knowledge records:\n${JSON.stringify(worklist.records)}`, {
|
|
21550
|
+
requestContext: context.requestContext,
|
|
21551
|
+
abortSignal: context.abortSignal,
|
|
21552
|
+
maxSteps: config.maxSteps,
|
|
21553
|
+
memory: {
|
|
21554
|
+
thread: `subconscious:${context.parentThreadId}:learn`,
|
|
21555
|
+
resource: context.resourceId
|
|
21556
|
+
}
|
|
21557
|
+
})).text.match(/<learning-complete\s+through=["']([^"']+)["']\s*\/>/i)?.[1];
|
|
21558
|
+
if (!acknowledgedId || !worklist.records.some((record) => record.id === acknowledgedId)) throw new Error("Learner did not acknowledge a valid reviewed record cursor.");
|
|
21559
|
+
await store.advanceCurationCursor({
|
|
21560
|
+
sourceThreadId: context.parentThreadId,
|
|
21561
|
+
agent: LEARN_AGENT,
|
|
21562
|
+
lastKnowledgeId: acknowledgedId
|
|
21563
|
+
});
|
|
21564
|
+
} catch (error) {
|
|
21565
|
+
const message = `learn: ${error instanceof Error ? error.message : String(error)}`;
|
|
21566
|
+
await context.writer?.custom({
|
|
21567
|
+
type: "data-subconscious-error",
|
|
21568
|
+
data: {
|
|
21569
|
+
agent: "learn",
|
|
21570
|
+
error: message
|
|
21571
|
+
}
|
|
21572
|
+
});
|
|
21573
|
+
if (store && scope) await publishSubconsciousActivity({
|
|
21574
|
+
store,
|
|
21575
|
+
scope,
|
|
21576
|
+
recentUpdates: subconscious.activity === false ? 10 : subconscious.activity.recentUpdates,
|
|
21577
|
+
sendStateSignal: context.sendStateSignal,
|
|
21578
|
+
errors: [message]
|
|
21579
|
+
});
|
|
21580
|
+
else await publishSubconsciousError({
|
|
21581
|
+
error: message,
|
|
21582
|
+
sendStateSignal: context.sendStateSignal
|
|
21583
|
+
});
|
|
21584
|
+
throw error;
|
|
21585
|
+
}
|
|
21586
|
+
};
|
|
21587
|
+
}
|
|
21588
|
+
async function createLearnerAgent(memory, learnerMemory, context, scope, pendingRecords, config, subconscious, omModel) {
|
|
21589
|
+
const model = await resolveSubconsciousAgentModel({
|
|
21590
|
+
config,
|
|
21591
|
+
omModel,
|
|
21592
|
+
mainAgent: context.mainAgent,
|
|
21593
|
+
requestContext: context.requestContext
|
|
21594
|
+
});
|
|
21595
|
+
if (!model) throw new Error("Subconscious learn requires the main agent to resolve its model.");
|
|
21596
|
+
const store = await memory.storage.getStore("knowledge");
|
|
21597
|
+
if (!store) throw new Error("Subconscious learn requires a configured knowledge storage domain.");
|
|
21598
|
+
const state = {};
|
|
21599
|
+
return new _mastra_core_agent.Agent({
|
|
21600
|
+
id: `subconscious-learn-${context.parentThreadId}`,
|
|
21601
|
+
name: "Subconscious Learn",
|
|
21602
|
+
instructions: [DEFAULT_INSTRUCTIONS, config.instructions?.trim()].filter(Boolean).join("\n\n"),
|
|
21603
|
+
model,
|
|
21604
|
+
memory: learnerMemory,
|
|
21605
|
+
tools: {
|
|
21606
|
+
...createKnowledgeTools(memory, scope),
|
|
21607
|
+
...createKnowledgeWriteTools(memory, {
|
|
21608
|
+
scope,
|
|
21609
|
+
sourceThreadId: context.parentThreadId,
|
|
21610
|
+
defaultScope: subconscious.defaultScope,
|
|
21611
|
+
maxScope: subconscious.maxScope
|
|
21612
|
+
}),
|
|
21613
|
+
knowledge_record_skill: createLearnerRecordSkillTool({
|
|
21614
|
+
store,
|
|
21615
|
+
scope,
|
|
21616
|
+
pendingRecords,
|
|
21617
|
+
parentThreadId: context.parentThreadId,
|
|
21618
|
+
defaultScope: subconscious.defaultScope,
|
|
21619
|
+
maxScope: subconscious.maxScope,
|
|
21620
|
+
state
|
|
21621
|
+
})
|
|
21622
|
+
}
|
|
21623
|
+
});
|
|
21624
|
+
}
|
|
19243
21625
|
var constants_exports = /* @__PURE__ */ __exportAll({
|
|
19244
21626
|
OBSERVATIONAL_MEMORY_DEFAULTS: () => OBSERVATIONAL_MEMORY_DEFAULTS,
|
|
19245
21627
|
OBSERVATION_CONTEXT_INSTRUCTIONS: () => OBSERVATION_CONTEXT_INSTRUCTIONS,
|
|
@@ -19394,232 +21776,6 @@ Observation groups with range IDs and your recall tool allows you to think back
|
|
|
19394
21776
|
### Additional recall guidance
|
|
19395
21777
|
${custom}`;
|
|
19396
21778
|
}
|
|
19397
|
-
const BUILT_IN_SLUGS = /* @__PURE__ */ new Set([
|
|
19398
|
-
"current-task",
|
|
19399
|
-
"suggested-response",
|
|
19400
|
-
"thread-title"
|
|
19401
|
-
]);
|
|
19402
|
-
const EXTRACTED_VALUES_TAG = "extracted-values";
|
|
19403
|
-
const RESERVED_XML_TAGS = /* @__PURE__ */ new Set([
|
|
19404
|
-
"observations",
|
|
19405
|
-
"observation",
|
|
19406
|
-
EXTRACTED_VALUES_TAG,
|
|
19407
|
-
"thread",
|
|
19408
|
-
"message",
|
|
19409
|
-
"messages",
|
|
19410
|
-
"conversation",
|
|
19411
|
-
"history",
|
|
19412
|
-
"system",
|
|
19413
|
-
"user",
|
|
19414
|
-
"assistant",
|
|
19415
|
-
"tool",
|
|
19416
|
-
...BUILT_IN_SLUGS
|
|
19417
|
-
]);
|
|
19418
|
-
const BUILT_IN_EXTRACTOR_SLUGS = [...BUILT_IN_SLUGS];
|
|
19419
|
-
function isBuiltInExtractorSlug(slug) {
|
|
19420
|
-
return BUILT_IN_SLUGS.has(slug);
|
|
19421
|
-
}
|
|
19422
|
-
function slugifyExtractorName(name) {
|
|
19423
|
-
let normalized = "";
|
|
19424
|
-
let previousWasSeparator = false;
|
|
19425
|
-
for (const char of name.trim().toLowerCase()) {
|
|
19426
|
-
const code = char.charCodeAt(0);
|
|
19427
|
-
if (code >= 97 && code <= 122 || code >= 48 && code <= 57) {
|
|
19428
|
-
normalized += char;
|
|
19429
|
-
previousWasSeparator = false;
|
|
19430
|
-
continue;
|
|
19431
|
-
}
|
|
19432
|
-
if (char === "'" || char === "\"" || char === "`") continue;
|
|
19433
|
-
if (!previousWasSeparator && normalized.length > 0) {
|
|
19434
|
-
normalized += "-";
|
|
19435
|
-
previousWasSeparator = true;
|
|
19436
|
-
}
|
|
19437
|
-
}
|
|
19438
|
-
return normalized.endsWith("-") ? normalized.slice(0, -1) : normalized;
|
|
19439
|
-
}
|
|
19440
|
-
function assertValidSlug(slug, name) {
|
|
19441
|
-
if (!slug) throw new Error(`Extractor name "${name}" must produce a non-empty slug.`);
|
|
19442
|
-
const first = slug.charCodeAt(0);
|
|
19443
|
-
const last = slug.charCodeAt(slug.length - 1);
|
|
19444
|
-
const startsWithLetter = first >= 97 && first <= 122;
|
|
19445
|
-
const endsWithLetterOrNumber = last >= 97 && last <= 122 || last >= 48 && last <= 57;
|
|
19446
|
-
const hasOnlySlugCharacters = [...slug].every((char) => {
|
|
19447
|
-
const code = char.charCodeAt(0);
|
|
19448
|
-
return code >= 97 && code <= 122 || code >= 48 && code <= 57 || char === "-";
|
|
19449
|
-
});
|
|
19450
|
-
if (!startsWithLetter || !endsWithLetterOrNumber || !hasOnlySlugCharacters) throw new Error(`Extractor name "${name}" produced invalid slug "${slug}".`);
|
|
19451
|
-
}
|
|
19452
|
-
var Extractor = class Extractor {
|
|
19453
|
-
name;
|
|
19454
|
-
slug;
|
|
19455
|
-
instructions;
|
|
19456
|
-
schema;
|
|
19457
|
-
mode;
|
|
19458
|
-
includePreviousExtraction;
|
|
19459
|
-
metadataKeyPath;
|
|
19460
|
-
onExtracted;
|
|
19461
|
-
retryStructuredExtractionOnEmptyObject;
|
|
19462
|
-
/** @internal */
|
|
19463
|
-
internal;
|
|
19464
|
-
instructionsConfig;
|
|
19465
|
-
schemaConfig;
|
|
19466
|
-
constructor(config, internal = false) {
|
|
19467
|
-
const name = config.name.trim();
|
|
19468
|
-
const instructions = typeof config.instructions === "string" ? config.instructions.trim() : void 0;
|
|
19469
|
-
const slug = slugifyExtractorName(name);
|
|
19470
|
-
if (!name) throw new Error("Extractor name is required.");
|
|
19471
|
-
if (instructions !== void 0 && !instructions) throw new Error(`Extractor "${name}" must include instructions.`);
|
|
19472
|
-
assertValidSlug(slug, name);
|
|
19473
|
-
if (!internal && RESERVED_XML_TAGS.has(slug)) throw new Error(`Extractor slug "${slug}" is reserved by Observational Memory.`);
|
|
19474
|
-
this.name = name;
|
|
19475
|
-
this.slug = slug;
|
|
19476
|
-
this.instructionsConfig = config.instructions;
|
|
19477
|
-
this.schemaConfig = config.schema;
|
|
19478
|
-
this.instructions = instructions ?? "";
|
|
19479
|
-
this.schema = typeof config.schema === "function" ? zod.z.string() : config.schema ?? zod.z.string();
|
|
19480
|
-
this.mode = internal || !config.schema ? "inline" : "structured";
|
|
19481
|
-
this.includePreviousExtraction = config.includePreviousExtraction ?? true;
|
|
19482
|
-
this.metadataKeyPath = config.metadataKeyPath ?? `extracted.${slug}`;
|
|
19483
|
-
this.onExtracted = config.onExtracted;
|
|
19484
|
-
this.retryStructuredExtractionOnEmptyObject = config.retryStructuredExtractionOnEmptyObject ?? false;
|
|
19485
|
-
this.internal = internal;
|
|
19486
|
-
}
|
|
19487
|
-
async resolve(context) {
|
|
19488
|
-
const instructions = typeof this.instructionsConfig === "function" ? (await this.instructionsConfig(context)).trim() : this.instructionsConfig.trim();
|
|
19489
|
-
if (!instructions) throw new Error(`Extractor "${this.name}" must include instructions.`);
|
|
19490
|
-
const schema = typeof this.schemaConfig === "function" ? await this.schemaConfig(context) : this.schemaConfig;
|
|
19491
|
-
return new Extractor({
|
|
19492
|
-
name: this.name,
|
|
19493
|
-
instructions,
|
|
19494
|
-
...schema ? { schema } : {},
|
|
19495
|
-
includePreviousExtraction: this.includePreviousExtraction,
|
|
19496
|
-
metadataKeyPath: this.metadataKeyPath,
|
|
19497
|
-
onExtracted: this.onExtracted,
|
|
19498
|
-
retryStructuredExtractionOnEmptyObject: this.retryStructuredExtractionOnEmptyObject
|
|
19499
|
-
}, this.internal);
|
|
19500
|
-
}
|
|
19501
|
-
};
|
|
19502
|
-
async function resolveExtractors(extractors, context) {
|
|
19503
|
-
return Promise.all(extractors.map((extractor) => extractor.resolve(context)));
|
|
19504
|
-
}
|
|
19505
|
-
function validateExtractorList(extractors) {
|
|
19506
|
-
const seen = /* @__PURE__ */ new Map();
|
|
19507
|
-
for (const extractor of extractors) {
|
|
19508
|
-
assertValidSlug(extractor.slug, extractor.name);
|
|
19509
|
-
if (!extractor.internal && RESERVED_XML_TAGS.has(extractor.slug)) throw new Error(`Extractor slug "${extractor.slug}" is reserved by Observational Memory.`);
|
|
19510
|
-
const previous = seen.get(extractor.slug);
|
|
19511
|
-
if (previous) throw new Error(`Duplicate extractor slug "${extractor.slug}" from "${previous}" and "${extractor.name}".`);
|
|
19512
|
-
seen.set(extractor.slug, extractor.name);
|
|
19513
|
-
}
|
|
19514
|
-
return [...extractors];
|
|
19515
|
-
}
|
|
19516
|
-
function isJsonLike(value) {
|
|
19517
|
-
return /^(?:[\[{"-]|\d|true\b|false\b|null\b)/.test(value.trim());
|
|
19518
|
-
}
|
|
19519
|
-
function candidateValues(raw) {
|
|
19520
|
-
const trimmed = raw.trim();
|
|
19521
|
-
const candidates = [];
|
|
19522
|
-
const add = (value) => {
|
|
19523
|
-
if (!candidates.some((candidate) => Object.is(candidate, value))) candidates.push(value);
|
|
19524
|
-
};
|
|
19525
|
-
if (isJsonLike(trimmed)) try {
|
|
19526
|
-
add(JSON.parse(trimmed));
|
|
19527
|
-
} catch {}
|
|
19528
|
-
add(trimmed);
|
|
19529
|
-
if (!isJsonLike(trimmed)) try {
|
|
19530
|
-
add(JSON.parse(trimmed));
|
|
19531
|
-
} catch {}
|
|
19532
|
-
return candidates;
|
|
19533
|
-
}
|
|
19534
|
-
function parseExtractorValue(extractor, raw) {
|
|
19535
|
-
const failures = [];
|
|
19536
|
-
for (const candidate of candidateValues(raw)) {
|
|
19537
|
-
const parsed = extractor.schema.safeParse(candidate);
|
|
19538
|
-
if (parsed.success) return parsed.data;
|
|
19539
|
-
failures.push(parsed.error.message);
|
|
19540
|
-
}
|
|
19541
|
-
throw new Error(`Extractor "${extractor.slug}" output did not match its schema: ${failures[0] ?? "invalid value"}`);
|
|
19542
|
-
}
|
|
19543
|
-
function parseExtractedValuesObject(raw) {
|
|
19544
|
-
const trimmed = raw.trim();
|
|
19545
|
-
if (!trimmed || trimmed.startsWith("Write only the extracted values JSON object here.")) return;
|
|
19546
|
-
const parsed = JSON.parse(trimmed);
|
|
19547
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`${EXTRACTED_VALUES_TAG} must contain a JSON object.`);
|
|
19548
|
-
return parsed;
|
|
19549
|
-
}
|
|
19550
|
-
function parseExtractedValues(output, extractors) {
|
|
19551
|
-
const values = {};
|
|
19552
|
-
const failures = [];
|
|
19553
|
-
const inlineExtractors = extractors.filter((extractor) => extractor.mode === "inline");
|
|
19554
|
-
const regex = new RegExp(`<${EXTRACTED_VALUES_TAG}>([\\s\\S]*?)<\\/${EXTRACTED_VALUES_TAG}>`, "gi");
|
|
19555
|
-
const matches = [...output.matchAll(regex)];
|
|
19556
|
-
for (const match of matches) try {
|
|
19557
|
-
const extractedValues = parseExtractedValuesObject(match[1] ?? "");
|
|
19558
|
-
if (!extractedValues) continue;
|
|
19559
|
-
for (const extractor of inlineExtractors) {
|
|
19560
|
-
if (!Object.prototype.hasOwnProperty.call(extractedValues, extractor.slug)) continue;
|
|
19561
|
-
const rawValue = extractedValues[extractor.slug];
|
|
19562
|
-
if (rawValue === void 0 || rawValue === null || rawValue === "") continue;
|
|
19563
|
-
const parsed = extractor.schema.safeParse(rawValue);
|
|
19564
|
-
if (parsed.success) values[extractor.slug] = parsed.data;
|
|
19565
|
-
else failures.push({
|
|
19566
|
-
slug: extractor.slug,
|
|
19567
|
-
error: parsed.error.message
|
|
19568
|
-
});
|
|
19569
|
-
}
|
|
19570
|
-
} catch (error) {
|
|
19571
|
-
failures.push({
|
|
19572
|
-
slug: EXTRACTED_VALUES_TAG,
|
|
19573
|
-
error: error instanceof Error ? error.message : String(error)
|
|
19574
|
-
});
|
|
19575
|
-
}
|
|
19576
|
-
for (const extractor of inlineExtractors) {
|
|
19577
|
-
if (Object.prototype.hasOwnProperty.call(values, extractor.slug)) continue;
|
|
19578
|
-
const tagRegex = new RegExp(`<${extractor.slug}>([\\s\\S]*?)<\\/${extractor.slug}>`, "gi");
|
|
19579
|
-
const rawValue = [...output.matchAll(tagRegex)].at(-1)?.[1]?.trim();
|
|
19580
|
-
if (!rawValue) continue;
|
|
19581
|
-
try {
|
|
19582
|
-
values[extractor.slug] = parseExtractorValue(extractor, rawValue);
|
|
19583
|
-
} catch (error) {
|
|
19584
|
-
failures.push({
|
|
19585
|
-
slug: extractor.slug,
|
|
19586
|
-
error: error instanceof Error ? error.message : String(error)
|
|
19587
|
-
});
|
|
19588
|
-
}
|
|
19589
|
-
}
|
|
19590
|
-
return {
|
|
19591
|
-
values,
|
|
19592
|
-
failures
|
|
19593
|
-
};
|
|
19594
|
-
}
|
|
19595
|
-
function stripExtractorSections(output, extractors) {
|
|
19596
|
-
const inlineExtractors = extractors.filter((extractor) => extractor.mode === "inline");
|
|
19597
|
-
let stripped = output.replace(new RegExp(`[ \\t]*<${EXTRACTED_VALUES_TAG}>[\\s\\S]*?<\\/${EXTRACTED_VALUES_TAG}>\\s*`, "gi"), "");
|
|
19598
|
-
for (const extractor of inlineExtractors) stripped = stripped.replace(new RegExp(`[ \\t]*<${extractor.slug}>[\\s\\S]*?<\\/${extractor.slug}>\\s*`, "gi"), "");
|
|
19599
|
-
return stripped;
|
|
19600
|
-
}
|
|
19601
|
-
function buildExtractorOutputSections(extractors) {
|
|
19602
|
-
const inlineExtractors = extractors.filter((extractor) => extractor.mode === "inline");
|
|
19603
|
-
if (inlineExtractors.length === 0) return "";
|
|
19604
|
-
return `Additional optional XML sections:\nIf the observations include information relevant to any of these tags, output that tag after <observations> and include the relevant information.\n${inlineExtractors.map((extractor) => `<${extractor.slug}>
|
|
19605
|
-
${extractor.instructions}
|
|
19606
|
-
Include this section when the observations contain relevant information for <${extractor.slug}>. Write only that information inside the tag.
|
|
19607
|
-
</${extractor.slug}>`).join("\n\n")}`;
|
|
19608
|
-
}
|
|
19609
|
-
function renderPriorValue(value) {
|
|
19610
|
-
return typeof value === "string" ? value : JSON.stringify(value);
|
|
19611
|
-
}
|
|
19612
|
-
function buildExtractorPriorLines(extractors, priorExtractedValues) {
|
|
19613
|
-
if (!priorExtractedValues) return [];
|
|
19614
|
-
const lines = [];
|
|
19615
|
-
for (const extractor of extractors) {
|
|
19616
|
-
if (!extractor.includePreviousExtraction) continue;
|
|
19617
|
-
const value = priorExtractedValues[extractor.slug];
|
|
19618
|
-
if (value === void 0 || value === null || value === "") continue;
|
|
19619
|
-
lines.push(`<${extractor.slug}>\n${renderPriorValue(value)}\n</${extractor.slug}>`);
|
|
19620
|
-
}
|
|
19621
|
-
return lines;
|
|
19622
|
-
}
|
|
19623
21779
|
const BUILT_IN_METADATA_FIELDS = {
|
|
19624
21780
|
"current-task": {
|
|
19625
21781
|
metadataField: "currentTask",
|
|
@@ -19741,9 +21897,11 @@ async function applyExtractorHooks(opts) {
|
|
|
19741
21897
|
const values = normalizeExtractedValues(opts.values) ?? {};
|
|
19742
21898
|
const failures = [...opts.failures ?? []];
|
|
19743
21899
|
for (const extractor of opts.extractors) {
|
|
19744
|
-
|
|
19745
|
-
const
|
|
19746
|
-
if (!
|
|
21900
|
+
const isHook = extractor.mode === "hook";
|
|
21901
|
+
const hasValue = Object.prototype.hasOwnProperty.call(values, extractor.slug);
|
|
21902
|
+
if (!isHook && !hasValue) continue;
|
|
21903
|
+
const current = isHook ? opts.rawObservations : values[extractor.slug];
|
|
21904
|
+
if (!isHook && !isPresentExtractedValue(current)) {
|
|
19747
21905
|
delete values[extractor.slug];
|
|
19748
21906
|
continue;
|
|
19749
21907
|
}
|
|
@@ -19754,14 +21912,19 @@ async function applyExtractorHooks(opts) {
|
|
|
19754
21912
|
extractor,
|
|
19755
21913
|
threadId: opts.threadId,
|
|
19756
21914
|
resourceId: opts.resourceId,
|
|
19757
|
-
previous: opts.previousValues?.[extractor.slug],
|
|
21915
|
+
previous: isHook ? void 0 : opts.previousValues?.[extractor.slug],
|
|
19758
21916
|
current,
|
|
21917
|
+
rawObservations: opts.rawObservations,
|
|
21918
|
+
recentMessages: opts.recentMessages,
|
|
19759
21919
|
mainAgent: opts.mainAgent,
|
|
19760
21920
|
memory: opts.memory,
|
|
19761
21921
|
sendSignal: opts.sendSignal,
|
|
21922
|
+
sendStateSignal: opts.sendStateSignal,
|
|
21923
|
+
writer: opts.writer,
|
|
21924
|
+
abortSignal: opts.abortSignal,
|
|
19762
21925
|
requestContext: opts.requestContext
|
|
19763
21926
|
});
|
|
19764
|
-
if (hookValue === void 0) continue;
|
|
21927
|
+
if (isHook || hookValue === void 0) continue;
|
|
19765
21928
|
const parsed = extractor.schema.safeParse(hookValue);
|
|
19766
21929
|
if (parsed.success) values[extractor.slug] = parsed.data;
|
|
19767
21930
|
else {
|
|
@@ -19772,7 +21935,8 @@ async function applyExtractorHooks(opts) {
|
|
|
19772
21935
|
});
|
|
19773
21936
|
}
|
|
19774
21937
|
} catch (error) {
|
|
19775
|
-
|
|
21938
|
+
if (opts.abortSignal?.aborted) throw error;
|
|
21939
|
+
if (!isHook) delete values[extractor.slug];
|
|
19776
21940
|
failures.push({
|
|
19777
21941
|
slug: extractor.slug,
|
|
19778
21942
|
error: error instanceof Error ? error.message : String(error)
|
|
@@ -20821,11 +22985,11 @@ function formatObserverAttachmentPlaceholder(part, counter) {
|
|
|
20821
22985
|
const label = resolveObserverAttachmentLabel(part);
|
|
20822
22986
|
return label ? `[${attachmentType} #${attachmentId}: ${label}]` : `[${attachmentType} #${attachmentId}]`;
|
|
20823
22987
|
}
|
|
20824
|
-
function isRecord$
|
|
22988
|
+
function isRecord$3(value) {
|
|
20825
22989
|
return !!value && typeof value === "object";
|
|
20826
22990
|
}
|
|
20827
22991
|
function mapToolResultBlockToAttachment(block) {
|
|
20828
|
-
if (!isRecord$
|
|
22992
|
+
if (!isRecord$3(block) || typeof block.type !== "string") return;
|
|
20829
22993
|
const mediaType = typeof block.mediaType === "string" ? block.mediaType : void 0;
|
|
20830
22994
|
const filename = typeof block.filename === "string" ? block.filename : void 0;
|
|
20831
22995
|
switch (block.type) {
|
|
@@ -20886,7 +23050,7 @@ function mapToolResultBlockToAttachment(block) {
|
|
|
20886
23050
|
}
|
|
20887
23051
|
}
|
|
20888
23052
|
function extractToolResultAttachments(result, counter, attachmentFilter) {
|
|
20889
|
-
if (!isRecord$
|
|
23053
|
+
if (!isRecord$3(result) || result.type !== "content" || !Array.isArray(result.value)) return {
|
|
20890
23054
|
resultWithoutAttachments: result,
|
|
20891
23055
|
attachments: []
|
|
20892
23056
|
};
|
|
@@ -20900,7 +23064,7 @@ function extractToolResultAttachments(result, counter, attachmentFilter) {
|
|
|
20900
23064
|
if (shouldIncludeObserverAttachment(attachment, attachmentFilter)) attachments.push(toObserverInputAttachmentPart(attachment));
|
|
20901
23065
|
const placeholder = formatObserverAttachmentPlaceholder(attachment, counter);
|
|
20902
23066
|
return {
|
|
20903
|
-
type: isRecord$
|
|
23067
|
+
type: isRecord$3(block) ? block.type : void 0,
|
|
20904
23068
|
placeholder
|
|
20905
23069
|
};
|
|
20906
23070
|
});
|
|
@@ -21356,6 +23520,52 @@ function detectDegenerateRepetition(text) {
|
|
|
21356
23520
|
return false;
|
|
21357
23521
|
}
|
|
21358
23522
|
/**
|
|
23523
|
+
* Build a single-line diagnostic description of output flagged by
|
|
23524
|
+
* {@link detectDegenerateRepetition}. Used when logging or surfacing a
|
|
23525
|
+
* degenerate-output failure so the discarded model output can be inspected —
|
|
23526
|
+
* without it there is no way to tell a real repetition loop apart from a
|
|
23527
|
+
* detector false-positive on legitimately repetitive content.
|
|
23528
|
+
*
|
|
23529
|
+
* Reuses the detector's sampling parameters (200-char windows, ~50 samples)
|
|
23530
|
+
* so the reported duplicate ratio and most-repeated window match what
|
|
23531
|
+
* triggered the detection. Snippets are JSON-escaped so the result stays on
|
|
23532
|
+
* one line.
|
|
23533
|
+
*/
|
|
23534
|
+
function describeDegenerateOutput(text, snippetChars = 400) {
|
|
23535
|
+
const windowSize = 200;
|
|
23536
|
+
const step = Math.max(1, Math.floor(text.length / 50));
|
|
23537
|
+
const seen = /* @__PURE__ */ new Map();
|
|
23538
|
+
let duplicateWindows = 0;
|
|
23539
|
+
let totalWindows = 0;
|
|
23540
|
+
for (let i = 0; i + windowSize <= text.length; i += step) {
|
|
23541
|
+
const window = text.slice(i, i + windowSize);
|
|
23542
|
+
totalWindows++;
|
|
23543
|
+
const count = (seen.get(window) ?? 0) + 1;
|
|
23544
|
+
seen.set(window, count);
|
|
23545
|
+
if (count > 1) duplicateWindows++;
|
|
23546
|
+
}
|
|
23547
|
+
let topWindow = "";
|
|
23548
|
+
let topCount = 0;
|
|
23549
|
+
for (const [window, count] of seen) if (count > topCount) {
|
|
23550
|
+
topCount = count;
|
|
23551
|
+
topWindow = window;
|
|
23552
|
+
}
|
|
23553
|
+
let longestLine = 0;
|
|
23554
|
+
for (const line of text.split("\n")) if (line.length > longestLine) longestLine = line.length;
|
|
23555
|
+
const duplicateRatio = totalWindows > 0 ? (duplicateWindows / totalWindows).toFixed(2) : "n/a";
|
|
23556
|
+
const parts = [
|
|
23557
|
+
`length=${text.length}`,
|
|
23558
|
+
`sampledWindows=${totalWindows}`,
|
|
23559
|
+
`duplicateRatio=${duplicateRatio}`,
|
|
23560
|
+
`longestLine=${longestLine}`,
|
|
23561
|
+
`topWindowCount=${topCount}`
|
|
23562
|
+
];
|
|
23563
|
+
if (topCount > 1) parts.push(`topWindow=${JSON.stringify(topWindow)}`);
|
|
23564
|
+
parts.push(`head=${JSON.stringify(text.slice(0, snippetChars))}`);
|
|
23565
|
+
if (text.length > snippetChars * 2) parts.push(`tail=${JSON.stringify(text.slice(-snippetChars))}`);
|
|
23566
|
+
return parts.join(" ");
|
|
23567
|
+
}
|
|
23568
|
+
/**
|
|
21359
23569
|
* Check if observations contain a Current Task section.
|
|
21360
23570
|
* Supports both XML format and legacy markdown format.
|
|
21361
23571
|
*/
|
|
@@ -21441,17 +23651,17 @@ const TRANSIENT_MESSAGE_SUBSTRINGS = [
|
|
|
21441
23651
|
"connection reset",
|
|
21442
23652
|
"connection closed"
|
|
21443
23653
|
];
|
|
21444
|
-
function isRecord$
|
|
23654
|
+
function isRecord$2(value) {
|
|
21445
23655
|
return typeof value === "object" && value !== null;
|
|
21446
23656
|
}
|
|
21447
23657
|
function isAbortError$5(error) {
|
|
21448
|
-
if (!isRecord$
|
|
23658
|
+
if (!isRecord$2(error)) return false;
|
|
21449
23659
|
if (error.name === "AbortError") return true;
|
|
21450
23660
|
if (typeof error.code === "string" && error.code === "ABORT_ERR") return true;
|
|
21451
23661
|
return false;
|
|
21452
23662
|
}
|
|
21453
23663
|
function hasTransientMessage(value) {
|
|
21454
|
-
if (!isRecord$
|
|
23664
|
+
if (!isRecord$2(value)) return false;
|
|
21455
23665
|
const message = typeof value.message === "string" ? value.message.toLowerCase() : "";
|
|
21456
23666
|
if (message && TRANSIENT_MESSAGE_SUBSTRINGS.some((sub) => message.includes(sub))) return true;
|
|
21457
23667
|
if (typeof value.code === "string" && value.code.toUpperCase().startsWith("UND_ERR_")) return true;
|
|
@@ -21462,13 +23672,13 @@ function isRetryableHttpStatus(status) {
|
|
|
21462
23672
|
return status >= 500 && status <= 599;
|
|
21463
23673
|
}
|
|
21464
23674
|
function hasRetryableHttpStatus(value) {
|
|
21465
|
-
if (!isRecord$
|
|
23675
|
+
if (!isRecord$2(value)) return false;
|
|
21466
23676
|
if (typeof value.statusCode === "number" && isRetryableHttpStatus(value.statusCode)) return true;
|
|
21467
23677
|
if (typeof value.code === "number" && isRetryableHttpStatus(value.code)) return true;
|
|
21468
23678
|
return false;
|
|
21469
23679
|
}
|
|
21470
23680
|
function hasIsRetryableFlag(value) {
|
|
21471
|
-
if (!isRecord$
|
|
23681
|
+
if (!isRecord$2(value)) return false;
|
|
21472
23682
|
return value.isRetryable === true;
|
|
21473
23683
|
}
|
|
21474
23684
|
/**
|
|
@@ -21486,14 +23696,14 @@ function isTransientLLMError(error) {
|
|
|
21486
23696
|
if (isAbortError$5(error)) return false;
|
|
21487
23697
|
const visited = /* @__PURE__ */ new WeakSet();
|
|
21488
23698
|
function visit(candidate) {
|
|
21489
|
-
if (isRecord$
|
|
23699
|
+
if (isRecord$2(candidate)) {
|
|
21490
23700
|
if (visited.has(candidate)) return false;
|
|
21491
23701
|
visited.add(candidate);
|
|
21492
23702
|
}
|
|
21493
23703
|
if (hasTransientMessage(candidate)) return true;
|
|
21494
23704
|
if (hasRetryableHttpStatus(candidate)) return true;
|
|
21495
23705
|
if (hasIsRetryableFlag(candidate)) return true;
|
|
21496
|
-
if (isRecord$
|
|
23706
|
+
if (isRecord$2(candidate)) {
|
|
21497
23707
|
if (visit(candidate.cause)) return true;
|
|
21498
23708
|
if (visit(candidate.error)) return true;
|
|
21499
23709
|
}
|
|
@@ -21750,13 +23960,13 @@ var ObserverRunner = class {
|
|
|
21750
23960
|
let parsed = parseObserverOutput(result.text, activeExtractors);
|
|
21751
23961
|
let retriedDueToDegenerate = false;
|
|
21752
23962
|
if (parsed.degenerate) {
|
|
21753
|
-
omDebug(`[OM:callObserver] degenerate repetition detected, retrying once`);
|
|
23963
|
+
omDebug(`[OM:callObserver] degenerate repetition detected, retrying once. ${describeDegenerateOutput(result.text, 2e3)}`);
|
|
21754
23964
|
result = await doGenerate();
|
|
21755
23965
|
parsed = parseObserverOutput(result.text, activeExtractors);
|
|
21756
23966
|
retriedDueToDegenerate = true;
|
|
21757
23967
|
if (parsed.degenerate) {
|
|
21758
|
-
omDebug(`[OM:callObserver] degenerate repetition on retry, failing`);
|
|
21759
|
-
throw new Error(
|
|
23968
|
+
omDebug(`[OM:callObserver] degenerate repetition on retry, failing. ${describeDegenerateOutput(result.text, 2e3)}`);
|
|
23969
|
+
throw new Error(`Observer produced degenerate output after retry. ${describeDegenerateOutput(result.text)}`);
|
|
21760
23970
|
}
|
|
21761
23971
|
}
|
|
21762
23972
|
const structuredExtraction = await extractStructuredValues({
|
|
@@ -21900,13 +24110,13 @@ var ObserverRunner = class {
|
|
|
21900
24110
|
let parsed = parseMultiThreadObserverOutput(result.text, activeExtractors);
|
|
21901
24111
|
let retriedDueToDegenerate = false;
|
|
21902
24112
|
if (parsed.degenerate) {
|
|
21903
|
-
omDebug(`[OM:callMultiThreadObserver] degenerate repetition detected, retrying once`);
|
|
24113
|
+
omDebug(`[OM:callMultiThreadObserver] degenerate repetition detected, retrying once. ${describeDegenerateOutput(result.text, 2e3)}`);
|
|
21904
24114
|
result = await doGenerate();
|
|
21905
24115
|
parsed = parseMultiThreadObserverOutput(result.text, activeExtractors);
|
|
21906
24116
|
retriedDueToDegenerate = true;
|
|
21907
24117
|
if (parsed.degenerate) {
|
|
21908
|
-
omDebug(`[OM:callMultiThreadObserver] degenerate repetition on retry, failing`);
|
|
21909
|
-
throw new Error(
|
|
24118
|
+
omDebug(`[OM:callMultiThreadObserver] degenerate repetition on retry, failing. ${describeDegenerateOutput(result.text, 2e3)}`);
|
|
24119
|
+
throw new Error(`Multi-thread observer produced degenerate output after retry. ${describeDegenerateOutput(result.text)}`);
|
|
21910
24120
|
}
|
|
21911
24121
|
}
|
|
21912
24122
|
const structuredExtractionByThread = /* @__PURE__ */ new Map();
|
|
@@ -22267,7 +24477,7 @@ async function resolveImageDimensionsAsync(part) {
|
|
|
22267
24477
|
const url = resolveHttpAssetUrl(getObjectValue(part, "image") ?? getObjectValue(part, "data"));
|
|
22268
24478
|
if (!url) return existing;
|
|
22269
24479
|
try {
|
|
22270
|
-
const probeImageSize = (await Promise.resolve().then(() => /* @__PURE__ */ require_rolldown_runtime.__toESM(require("./probe-image-size-
|
|
24480
|
+
const probeImageSize = (await Promise.resolve().then(() => /* @__PURE__ */ require_rolldown_runtime.__toESM(require("./probe-image-size-CDCRrXNo.cjs").default, 1))).default;
|
|
22271
24481
|
const probed = await probeImageSize(url, {
|
|
22272
24482
|
open_timeout: REMOTE_IMAGE_PROBE_TIMEOUT_MS,
|
|
22273
24483
|
response_timeout: REMOTE_IMAGE_PROBE_TIMEOUT_MS,
|
|
@@ -24713,38 +26923,6 @@ function createWorkingMemoryTool(config, options = {}) {
|
|
|
24713
26923
|
tool
|
|
24714
26924
|
};
|
|
24715
26925
|
}
|
|
24716
|
-
function isTieredModelTarget(model) {
|
|
24717
|
-
if (typeof model === "string") return true;
|
|
24718
|
-
if (!model || typeof model !== "object") return false;
|
|
24719
|
-
return "modelId" in model || "id" in model || "providerId" in model || "provider" in model || "doGenerate" in model && "doStream" in model;
|
|
24720
|
-
}
|
|
24721
|
-
function normalizeThresholds(config) {
|
|
24722
|
-
const entries = Object.entries(config.upTo);
|
|
24723
|
-
if (entries.length === 0) throw new Error("ModelByInputTokens requires at least one threshold in \"upTo\"");
|
|
24724
|
-
for (const [limitStr, model] of entries) {
|
|
24725
|
-
const limit = Number(limitStr);
|
|
24726
|
-
if (!Number.isFinite(limit) || limit <= 0) throw new Error(`ModelByInputTokens threshold keys must be positive numbers. Got: ${limitStr}`);
|
|
24727
|
-
if (!isTieredModelTarget(model)) throw new Error(`ModelByInputTokens requires a valid model target for threshold ${limitStr}`);
|
|
24728
|
-
}
|
|
24729
|
-
return entries.map(([limitStr, model]) => ({
|
|
24730
|
-
limit: Number(limitStr),
|
|
24731
|
-
model
|
|
24732
|
-
})).sort((a, b) => a.limit - b.limit);
|
|
24733
|
-
}
|
|
24734
|
-
var ModelByInputTokens = class {
|
|
24735
|
-
thresholds;
|
|
24736
|
-
constructor(config) {
|
|
24737
|
-
this.thresholds = normalizeThresholds(config);
|
|
24738
|
-
}
|
|
24739
|
-
resolve(inputTokens) {
|
|
24740
|
-
for (const { limit, model } of this.thresholds) if (inputTokens <= limit) return model;
|
|
24741
|
-
const maxLimit = this.thresholds[this.thresholds.length - 1].limit;
|
|
24742
|
-
throw new Error(`ModelByInputTokens: input token count (${inputTokens}) exceeds the largest configured threshold (${maxLimit}). Please configure a higher threshold or use a larger model.`);
|
|
24743
|
-
}
|
|
24744
|
-
getThresholds() {
|
|
24745
|
-
return this.thresholds.map((t) => t.limit);
|
|
24746
|
-
}
|
|
24747
|
-
};
|
|
24748
26926
|
const MINUTE = 6e4;
|
|
24749
26927
|
const HOUR = 60 * MINUTE;
|
|
24750
26928
|
const SHORT_TTL = 5 * MINUTE;
|
|
@@ -25537,6 +27715,39 @@ function reconcileObservationGroupsFromReflection(content, sourceObservations) {
|
|
|
25537
27715
|
if (derivedGroups.length > 0) return derivedGroups.map((group) => wrapInObservationGroup(group.content, group.range, group.id, void 0, group.kind)).join("\n\n");
|
|
25538
27716
|
return wrapInObservationGroup(normalizedContent, combineObservationGroupRanges(sourceGroups), generateAnchorId(), void 0, "reflection");
|
|
25539
27717
|
}
|
|
27718
|
+
function isRecord$1(value) {
|
|
27719
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
27720
|
+
}
|
|
27721
|
+
function isSubconsciousSignalMessage(message) {
|
|
27722
|
+
if (message.role !== "signal" || !isRecord$1(message.content)) return false;
|
|
27723
|
+
const contentMetadata = message.content.metadata;
|
|
27724
|
+
if (!isRecord$1(contentMetadata) || !isRecord$1(contentMetadata.signal)) return false;
|
|
27725
|
+
const signal = contentMetadata.signal;
|
|
27726
|
+
const metadata = signal.metadata;
|
|
27727
|
+
const attributes = signal.attributes;
|
|
27728
|
+
return signal.origin === "subconscious" || isRecord$1(metadata) && metadata.origin === "subconscious" || isRecord$1(attributes) && attributes.source === "subconscious";
|
|
27729
|
+
}
|
|
27730
|
+
function isSubconsciousSignalPart(part) {
|
|
27731
|
+
if (!part || typeof part !== "object") return false;
|
|
27732
|
+
const candidate = part;
|
|
27733
|
+
return candidate.type === "data-signal" && (candidate.data?.metadata?.origin === "subconscious" || candidate.data?.attributes?.source === "subconscious");
|
|
27734
|
+
}
|
|
27735
|
+
function stripSubconsciousSignals(messages) {
|
|
27736
|
+
return messages.flatMap((message) => {
|
|
27737
|
+
if (isSubconsciousSignalMessage(message)) return [];
|
|
27738
|
+
if (typeof message.content === "string") return [message];
|
|
27739
|
+
const parts = message.content.parts.filter((part) => !isSubconsciousSignalPart(part));
|
|
27740
|
+
if (parts.length === message.content.parts.length) return [message];
|
|
27741
|
+
if (parts.length === 0) return [];
|
|
27742
|
+
return [{
|
|
27743
|
+
...message,
|
|
27744
|
+
content: {
|
|
27745
|
+
...message.content,
|
|
27746
|
+
parts
|
|
27747
|
+
}
|
|
27748
|
+
}];
|
|
27749
|
+
});
|
|
27750
|
+
}
|
|
25540
27751
|
/**
|
|
25541
27752
|
* Get the maximum value from a threshold (simple number or range).
|
|
25542
27753
|
*/
|
|
@@ -25690,8 +27901,9 @@ var ObservationStrategy = class ObservationStrategy {
|
|
|
25690
27901
|
if (fresh?.lastObservedAt && record.lastObservedAt && fresh.lastObservedAt > record.lastObservedAt) return { observed: false };
|
|
25691
27902
|
}
|
|
25692
27903
|
const { messages, existingObservations } = await this.prepare();
|
|
27904
|
+
const observationMessages = stripSubconsciousSignals(messages);
|
|
25693
27905
|
await this.emitStartMarkers(cycleId);
|
|
25694
|
-
const output = await this.observe(existingObservations,
|
|
27906
|
+
const output = await this.observe(existingObservations, observationMessages);
|
|
25695
27907
|
const processed = await this.process(output, existingObservations);
|
|
25696
27908
|
await this.persist(processed);
|
|
25697
27909
|
await this.emitEndMarkers(cycleId, processed);
|
|
@@ -25706,6 +27918,7 @@ var ObservationStrategy = class ObservationStrategy {
|
|
|
25706
27918
|
abortSignal,
|
|
25707
27919
|
mainAgent: this.opts.agent,
|
|
25708
27920
|
sendSignal: this.opts.sendSignal,
|
|
27921
|
+
sendStateSignal: this.opts.sendStateSignal,
|
|
25709
27922
|
reflectionHooks,
|
|
25710
27923
|
requestContext,
|
|
25711
27924
|
observabilityContext: this.opts.observabilityContext
|
|
@@ -25991,11 +28204,16 @@ var SyncObservationStrategy = class extends ObservationStrategy {
|
|
|
25991
28204
|
values: result.extractedValues,
|
|
25992
28205
|
failures: result.extractionFailures,
|
|
25993
28206
|
previousValues: this.priorExtractedValues,
|
|
28207
|
+
rawObservations: result.observations,
|
|
28208
|
+
recentMessages: formatMessagesForObserver(this.opts.messages, { maxPartLength: 500 }),
|
|
25994
28209
|
threadId: this.opts.threadId,
|
|
25995
28210
|
resourceId: this.opts.resourceId,
|
|
25996
28211
|
mainAgent: this.opts.agent,
|
|
25997
28212
|
memory: this.deps.memory,
|
|
25998
28213
|
sendSignal: this.opts.sendSignal,
|
|
28214
|
+
sendStateSignal: this.opts.sendStateSignal,
|
|
28215
|
+
writer: this.opts.writer,
|
|
28216
|
+
abortSignal: this.opts.abortSignal,
|
|
25999
28217
|
requestContext: this.opts.requestContext
|
|
26000
28218
|
});
|
|
26001
28219
|
const output = {
|
|
@@ -26169,11 +28387,16 @@ var AsyncBufferObservationStrategy = class extends ObservationStrategy {
|
|
|
26169
28387
|
values: result.extractedValues,
|
|
26170
28388
|
failures: result.extractionFailures,
|
|
26171
28389
|
previousValues: this.priorExtractedValues,
|
|
28390
|
+
rawObservations: result.observations,
|
|
28391
|
+
recentMessages: formatMessagesForObserver(messages, { maxPartLength: 500 }),
|
|
26172
28392
|
threadId: this.opts.threadId,
|
|
26173
28393
|
resourceId: this.opts.resourceId,
|
|
26174
28394
|
mainAgent: this.opts.agent,
|
|
26175
28395
|
memory: this.deps.memory,
|
|
26176
28396
|
sendSignal: this.opts.sendSignal,
|
|
28397
|
+
sendStateSignal: this.opts.sendStateSignal,
|
|
28398
|
+
writer: this.opts.writer,
|
|
28399
|
+
abortSignal: this.opts.abortSignal,
|
|
26177
28400
|
requestContext: this.opts.requestContext
|
|
26178
28401
|
});
|
|
26179
28402
|
return {
|
|
@@ -26506,11 +28729,25 @@ var ResourceScopedObservationStrategy = class extends ObservationStrategy {
|
|
|
26506
28729
|
values: result.extractedValues,
|
|
26507
28730
|
failures: result.extractionFailures,
|
|
26508
28731
|
previousValues,
|
|
28732
|
+
rawObservations: result.observations,
|
|
28733
|
+
recentMessages: formatMessagesForObserver(threadMessages, { maxPartLength: 500 }),
|
|
26509
28734
|
threadId,
|
|
26510
28735
|
resourceId: this.resourceId,
|
|
26511
28736
|
mainAgent: this.opts.agent,
|
|
26512
28737
|
memory: this.deps.memory,
|
|
26513
|
-
sendSignal: this.opts.
|
|
28738
|
+
sendSignal: this.opts.agent ? async (signal) => {
|
|
28739
|
+
const delivery = this.opts.agent.sendSignal(signal, {
|
|
28740
|
+
resourceId: this.resourceId,
|
|
28741
|
+
threadId,
|
|
28742
|
+
ifActive: { behavior: "deliver" },
|
|
28743
|
+
ifIdle: { behavior: "persist" }
|
|
28744
|
+
});
|
|
28745
|
+
await delivery.accepted;
|
|
28746
|
+
return delivery.signal;
|
|
28747
|
+
} : void 0,
|
|
28748
|
+
sendStateSignal: this.opts.sendStateSignal,
|
|
28749
|
+
writer: this.opts.writer,
|
|
28750
|
+
abortSignal: this.opts.abortSignal,
|
|
26514
28751
|
requestContext: this.opts.requestContext
|
|
26515
28752
|
});
|
|
26516
28753
|
this.observationResults.push({
|
|
@@ -26823,18 +29060,21 @@ var ObservationStep = class {
|
|
|
26823
29060
|
messageList.removeByIds(candidates.map((msg) => msg.id));
|
|
26824
29061
|
for (const msg of candidates) messageList.add(msg, "memory");
|
|
26825
29062
|
}
|
|
26826
|
-
om.buffer({
|
|
29063
|
+
om.trackBackgroundWork(om.buffer({
|
|
26827
29064
|
threadId,
|
|
26828
29065
|
resourceId,
|
|
26829
29066
|
messages: unobservedMessages,
|
|
26830
29067
|
pendingTokens: statusSnapshot.pendingTokens,
|
|
26831
29068
|
record: statusSnapshot.record,
|
|
26832
29069
|
writer: this.turn.writer,
|
|
29070
|
+
agent: this.turn.agent,
|
|
29071
|
+
sendSignal: this.turn.sendSignal,
|
|
29072
|
+
sendStateSignal: this.turn.sendStateSignal,
|
|
26833
29073
|
requestContext: this.turn.requestContext,
|
|
26834
29074
|
observabilityContext: this.turn.observabilityContext
|
|
26835
29075
|
}).catch((err) => {
|
|
26836
29076
|
omDebug(`[OM:buffer] fire-and-forget buffer failed: ${err?.message}`);
|
|
26837
|
-
});
|
|
29077
|
+
}));
|
|
26838
29078
|
buffered = true;
|
|
26839
29079
|
}
|
|
26840
29080
|
const willObserveNow = statusSnapshot.shouldObserve && !hasIncompleteToolCalls;
|
|
@@ -27006,6 +29246,9 @@ var ObservationStep = class {
|
|
|
27006
29246
|
messages: observableMessages,
|
|
27007
29247
|
messageList,
|
|
27008
29248
|
trigger: "turn-sync",
|
|
29249
|
+
agent: this.turn.agent,
|
|
29250
|
+
sendSignal: this.turn.sendSignal,
|
|
29251
|
+
sendStateSignal: this.turn.sendStateSignal,
|
|
27009
29252
|
requestContext: this.turn.requestContext,
|
|
27010
29253
|
writer: this.turn.writer,
|
|
27011
29254
|
observabilityContext: this.turn.observabilityContext
|
|
@@ -27083,6 +29326,8 @@ var ObservationTurn = class {
|
|
|
27083
29326
|
agent;
|
|
27084
29327
|
/** Optional signal sender for processor-originated notifications. */
|
|
27085
29328
|
sendSignal;
|
|
29329
|
+
/** Optional state signal sender for processor-originated snapshots. */
|
|
29330
|
+
sendStateSignal;
|
|
27086
29331
|
/** Current actor model for this step. Updated by the processor before prepare(). */
|
|
27087
29332
|
actorModelContext;
|
|
27088
29333
|
/** The active assistant response message ID for this step. Updated by the processor before prepare(). */
|
|
@@ -27096,6 +29341,7 @@ var ObservationTurn = class {
|
|
|
27096
29341
|
this.messageList = opts.messageList;
|
|
27097
29342
|
this.agent = opts.agent;
|
|
27098
29343
|
this.sendSignal = opts.sendSignal;
|
|
29344
|
+
this.sendStateSignal = opts.sendStateSignal;
|
|
27099
29345
|
this.requestContext = opts.requestContext;
|
|
27100
29346
|
this.observabilityContext = opts.observabilityContext;
|
|
27101
29347
|
this.hooks = opts.hooks ?? {};
|
|
@@ -27200,7 +29446,7 @@ var ObservationTurn = class {
|
|
|
27200
29446
|
const allMessages = getObservableMessages(this.messageList);
|
|
27201
29447
|
const record = this._record;
|
|
27202
29448
|
const unobservedMessages = this.om.getUnobservedMessages(allMessages, record);
|
|
27203
|
-
if (unobservedMessages.length > 0) this.om.buffer({
|
|
29449
|
+
if (unobservedMessages.length > 0) this.om.trackBackgroundWork(this.om.buffer({
|
|
27204
29450
|
threadId: this.threadId,
|
|
27205
29451
|
resourceId: this.resourceId,
|
|
27206
29452
|
messages: unobservedMessages,
|
|
@@ -27208,13 +29454,14 @@ var ObservationTurn = class {
|
|
|
27208
29454
|
writer: this.writer,
|
|
27209
29455
|
agent: this.agent,
|
|
27210
29456
|
sendSignal: this.sendSignal,
|
|
29457
|
+
sendStateSignal: this.sendStateSignal,
|
|
27211
29458
|
requestContext: this.requestContext,
|
|
27212
29459
|
currentModel: this.actorModelContext,
|
|
27213
29460
|
observabilityContext: this.observabilityContext,
|
|
27214
29461
|
skipMinimumTokenCheck: true
|
|
27215
29462
|
}).catch((err) => {
|
|
27216
29463
|
omDebug(`[OM:turn.end] idle buffer failed: ${err?.message}`);
|
|
27217
|
-
});
|
|
29464
|
+
}));
|
|
27218
29465
|
}
|
|
27219
29466
|
return { record: this._record };
|
|
27220
29467
|
}
|
|
@@ -27612,6 +29859,7 @@ var ReflectorRunner = class {
|
|
|
27612
29859
|
persistMarkerToMessage;
|
|
27613
29860
|
getCompressionStartLevel;
|
|
27614
29861
|
memory;
|
|
29862
|
+
onReflectionCommitted;
|
|
27615
29863
|
mastra;
|
|
27616
29864
|
constructor(opts) {
|
|
27617
29865
|
this.reflectionConfig = opts.reflectionConfig;
|
|
@@ -27627,6 +29875,7 @@ var ReflectorRunner = class {
|
|
|
27627
29875
|
this.getCompressionStartLevel = opts.getCompressionStartLevel;
|
|
27628
29876
|
this.mastra = opts.mastra;
|
|
27629
29877
|
this.memory = opts.memory;
|
|
29878
|
+
this.onReflectionCommitted = opts.onReflectionCommitted;
|
|
27630
29879
|
}
|
|
27631
29880
|
__registerMastra(mastra) {
|
|
27632
29881
|
this.mastra = mastra;
|
|
@@ -27694,6 +29943,8 @@ var ReflectorRunner = class {
|
|
|
27694
29943
|
};
|
|
27695
29944
|
let reflectedTokens = 0;
|
|
27696
29945
|
let attemptNumber = 0;
|
|
29946
|
+
/** Observations from the previous attempt, used to detect a no-progress ladder. */
|
|
29947
|
+
let previousObservations;
|
|
27697
29948
|
while (currentLevel <= maxLevel) {
|
|
27698
29949
|
attemptNumber++;
|
|
27699
29950
|
const isRetry = attemptNumber > 1;
|
|
@@ -27758,7 +30009,7 @@ var ReflectorRunner = class {
|
|
|
27758
30009
|
finalProviderMetadata = result.providerMetadata ?? finalProviderMetadata;
|
|
27759
30010
|
parsed = parseReflectorOutput(result.text, observations, activeExtractors);
|
|
27760
30011
|
if (parsed.degenerate) {
|
|
27761
|
-
omDebug(`[OM:callReflector] attempt #${attemptNumber}: degenerate repetition detected, treating as compression failure`);
|
|
30012
|
+
omDebug(`[OM:callReflector] attempt #${attemptNumber}: degenerate repetition detected, treating as compression failure. ${describeDegenerateOutput(result.text, 2e3)}`);
|
|
27762
30013
|
reflectedTokens = originalTokens;
|
|
27763
30014
|
} else reflectedTokens = this.tokenCounter.countObservations(parsed.observations);
|
|
27764
30015
|
omDebug(`[OM:callReflector] attempt #${attemptNumber} parsed: reflectedTokens=${reflectedTokens}, targetThreshold=${targetThreshold}, compressionValid=${validateCompression(reflectedTokens, targetThreshold)}, parsedObsLen=${parsed.observations?.length}, degenerate=${parsed.degenerate ?? false}`);
|
|
@@ -27767,6 +30018,11 @@ var ReflectorRunner = class {
|
|
|
27767
30018
|
omDebug(`[OM:callReflector] degenerate output persists at maxLevel=${maxLevel}, breaking`);
|
|
27768
30019
|
break;
|
|
27769
30020
|
}
|
|
30021
|
+
if (!parsed.degenerate && previousObservations !== void 0 && parsed.observations === previousObservations) {
|
|
30022
|
+
omDebug(`[OM:callReflector] attempt #${attemptNumber} returned output identical to the previous attempt; escalating cannot help, stopping the ladder`);
|
|
30023
|
+
break;
|
|
30024
|
+
}
|
|
30025
|
+
previousObservations = parsed.observations;
|
|
27770
30026
|
if (streamContext?.writer) {
|
|
27771
30027
|
const failedMarker = createObservationFailedMarker({
|
|
27772
30028
|
cycleId: streamContext.cycleId,
|
|
@@ -27823,6 +30079,8 @@ var ReflectorRunner = class {
|
|
|
27823
30079
|
mainAgent,
|
|
27824
30080
|
memory: this.memory,
|
|
27825
30081
|
sendSignal,
|
|
30082
|
+
writer: streamContext?.writer,
|
|
30083
|
+
abortSignal,
|
|
27826
30084
|
requestContext
|
|
27827
30085
|
});
|
|
27828
30086
|
const extractedValues = hookedValues.values;
|
|
@@ -27978,7 +30236,7 @@ var ReflectorRunner = class {
|
|
|
27978
30236
|
* "activated", "no buffer present", and "suppressed by overshoot guard"
|
|
27979
30237
|
* without re-deriving that state.
|
|
27980
30238
|
*/
|
|
27981
|
-
async tryActivateBufferedReflection(record, lockKey, writer, messageList, activationMetadata) {
|
|
30239
|
+
async tryActivateBufferedReflection(record, lockKey, writer, messageList, activationMetadata, committedContext) {
|
|
27982
30240
|
const bufferKey = this.buffering.getReflectionBufferKey(lockKey);
|
|
27983
30241
|
const asyncOp = BufferingCoordinator.asyncBufferingOps.get(bufferKey);
|
|
27984
30242
|
if (asyncOp) if (activationMetadata?.triggeredBy === "ttl" || activationMetadata?.triggeredBy === "provider_change") omDebug(`[OM:reflect] tryActivateBufferedReflection: async op in progress, not blocking for ${activationMetadata.triggeredBy} trigger`);
|
|
@@ -27997,7 +30255,8 @@ var ReflectorRunner = class {
|
|
|
27997
30255
|
}
|
|
27998
30256
|
const beforeTokens = freshRecord.observationTokenCount ?? 0;
|
|
27999
30257
|
const reflectedLineCount = freshRecord.reflectedObservationLineCount ?? 0;
|
|
28000
|
-
const
|
|
30258
|
+
const allLines = (freshRecord.activeObservations ?? "").split("\n");
|
|
30259
|
+
const unreflectedLines = allLines.slice(reflectedLineCount);
|
|
28001
30260
|
const unreflectedContent = unreflectedLines.join("\n").trim();
|
|
28002
30261
|
const combinedObservations = unreflectedContent ? `${freshRecord.bufferedReflection}\n\n${unreflectedContent}` : freshRecord.bufferedReflection;
|
|
28003
30262
|
const combinedTokenCount = this.tokenCounter.countObservations(combinedObservations);
|
|
@@ -28028,6 +30287,11 @@ var ReflectorRunner = class {
|
|
|
28028
30287
|
currentRecord: freshRecord,
|
|
28029
30288
|
tokenCount: combinedTokenCount
|
|
28030
30289
|
});
|
|
30290
|
+
if (committedContext) await this.notifyReflectionCommitted({
|
|
30291
|
+
...committedContext,
|
|
30292
|
+
observations: allLines.slice(0, reflectedLineCount).join("\n").trim(),
|
|
30293
|
+
writer
|
|
30294
|
+
});
|
|
28031
30295
|
BufferingCoordinator.lastBufferedBoundary.delete(bufferKey);
|
|
28032
30296
|
const afterRecord = await this.storage.getObservationalMemory(record.threadId, record.resourceId);
|
|
28033
30297
|
const afterTokens = afterRecord?.observationTokenCount ?? 0;
|
|
@@ -28063,13 +30327,21 @@ var ReflectorRunner = class {
|
|
|
28063
30327
|
BufferingCoordinator.reflectionBufferCycleIds.delete(bufferKey);
|
|
28064
30328
|
return { status: "activated" };
|
|
28065
30329
|
}
|
|
30330
|
+
async notifyReflectionCommitted(context) {
|
|
30331
|
+
if (!this.onReflectionCommitted || !context.parentThreadId || !context.resourceId) return;
|
|
30332
|
+
try {
|
|
30333
|
+
await this.onReflectionCommitted(context);
|
|
30334
|
+
} catch (error) {
|
|
30335
|
+
omDebug(`[OM:reflect] post-commit reflection agent failed: ${error}`);
|
|
30336
|
+
}
|
|
30337
|
+
}
|
|
28066
30338
|
/**
|
|
28067
30339
|
* Check if reflection needed and trigger if so.
|
|
28068
30340
|
* Supports both synchronous reflection and async buffered reflection.
|
|
28069
30341
|
* @internal Used by observation strategies. Do not call directly.
|
|
28070
30342
|
*/
|
|
28071
30343
|
async maybeReflect(opts) {
|
|
28072
|
-
const { record, observationTokens, writer, abortSignal, mainAgent, sendSignal, messageList, currentModel, reflectionHooks, requestContext, observabilityContext, lastActivityAt, threadId: requestedThreadId } = opts;
|
|
30344
|
+
const { record, observationTokens, writer, abortSignal, mainAgent, sendSignal, sendStateSignal, messageList, currentModel, reflectionHooks, requestContext, observabilityContext, lastActivityAt, threadId: requestedThreadId } = opts;
|
|
28073
30345
|
const lockKey = this.buffering.getLockKey(record.threadId, record.resourceId);
|
|
28074
30346
|
const reflectThreshold = getMaxThreshold(this.getEffectiveReflectionTokens(record));
|
|
28075
30347
|
const priorExtractedValues = await getThreadExtractedValues(this.storage, this.reflectionConfig.extractors, requestedThreadId ?? record.threadId);
|
|
@@ -28114,7 +30386,15 @@ var ReflectorRunner = class {
|
|
|
28114
30386
|
await this.storage.setReflectingFlag(record.id, false);
|
|
28115
30387
|
}
|
|
28116
30388
|
if (this.buffering.isAsyncReflectionEnabled()) {
|
|
28117
|
-
const activationResult = await this.tryActivateBufferedReflection(record, lockKey, writer, messageList, activationMetadata
|
|
30389
|
+
const activationResult = await this.tryActivateBufferedReflection(record, lockKey, writer, messageList, activationMetadata, {
|
|
30390
|
+
parentThreadId: requestedThreadId ?? record.threadId ?? "",
|
|
30391
|
+
resourceId: record.resourceId ?? "",
|
|
30392
|
+
requestContext,
|
|
30393
|
+
mainAgent,
|
|
30394
|
+
sendStateSignal,
|
|
30395
|
+
abortSignal,
|
|
30396
|
+
observabilityContext
|
|
30397
|
+
});
|
|
28118
30398
|
if (activationResult.status === "activated") return;
|
|
28119
30399
|
if (activationResult.status === "suppressed") {
|
|
28120
30400
|
omDebug(`[OM:reflect] skipping sync fallback / re-buffer after suppressed early ${activationMetadata.triggeredBy} activation (reason=${activationResult.reason})`);
|
|
@@ -28185,6 +30465,17 @@ var ReflectorRunner = class {
|
|
|
28185
30465
|
reflection: reflectResult.observations,
|
|
28186
30466
|
tokenCount: reflectionTokenCount
|
|
28187
30467
|
});
|
|
30468
|
+
await this.notifyReflectionCommitted({
|
|
30469
|
+
parentThreadId: requestedThreadId ?? record.threadId ?? "",
|
|
30470
|
+
resourceId: record.resourceId ?? "",
|
|
30471
|
+
observations: record.activeObservations ?? "",
|
|
30472
|
+
requestContext,
|
|
30473
|
+
mainAgent,
|
|
30474
|
+
sendStateSignal,
|
|
30475
|
+
writer,
|
|
30476
|
+
abortSignal,
|
|
30477
|
+
observabilityContext
|
|
30478
|
+
});
|
|
28188
30479
|
if (writer && streamContext) {
|
|
28189
30480
|
const endMarker = createObservationEndMarker({
|
|
28190
30481
|
cycleId: streamContext.cycleId,
|
|
@@ -28710,6 +31001,7 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
28710
31001
|
hasher = e();
|
|
28711
31002
|
mastra;
|
|
28712
31003
|
memory;
|
|
31004
|
+
curationCadence;
|
|
28713
31005
|
/**
|
|
28714
31006
|
* Track message IDs observed during this instance's lifetime.
|
|
28715
31007
|
* Prevents re-observing messages when per-thread lastObservedAt cursors
|
|
@@ -28741,6 +31033,39 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
28741
31033
|
*/
|
|
28742
31034
|
recordInitializations = /* @__PURE__ */ new Map();
|
|
28743
31035
|
/**
|
|
31036
|
+
* In-flight fire-and-forget background cycles (buffered observation, reflection).
|
|
31037
|
+
* Tracked so callers can join them via `settled()` before closing a storage
|
|
31038
|
+
* connection they own — otherwise a background cycle's tail statements race the close.
|
|
31039
|
+
*/
|
|
31040
|
+
pendingBackgroundWork = /* @__PURE__ */ new Set();
|
|
31041
|
+
/**
|
|
31042
|
+
* Register fire-and-forget background work so `settled()` can join it.
|
|
31043
|
+
* Returns the original promise so callers keep their own rejection handling.
|
|
31044
|
+
*/
|
|
31045
|
+
trackBackgroundWork(work) {
|
|
31046
|
+
const tracked = work.catch(() => {}).finally(() => {
|
|
31047
|
+
this.pendingBackgroundWork.delete(tracked);
|
|
31048
|
+
});
|
|
31049
|
+
this.pendingBackgroundWork.add(tracked);
|
|
31050
|
+
return work;
|
|
31051
|
+
}
|
|
31052
|
+
/**
|
|
31053
|
+
* Resolve once all background observational-memory work started so far has finished.
|
|
31054
|
+
*
|
|
31055
|
+
* Background cycles enqueue further background work (a buffered observation can
|
|
31056
|
+
* trigger a reflection, which runs nested agent streams), so this drains repeatedly
|
|
31057
|
+
* until nothing is left rather than joining a single snapshot.
|
|
31058
|
+
*/
|
|
31059
|
+
async settled() {
|
|
31060
|
+
const maxDrainRounds = 100;
|
|
31061
|
+
for (let round = 0; round < maxDrainRounds; round++) {
|
|
31062
|
+
if (this.pendingBackgroundWork.size === 0) return;
|
|
31063
|
+
await Promise.allSettled([...this.pendingBackgroundWork]);
|
|
31064
|
+
}
|
|
31065
|
+
if (this.pendingBackgroundWork.size === 0) return;
|
|
31066
|
+
omError(`[OM:settled] background work still pending after ${maxDrainRounds} drain rounds; giving up waiting`);
|
|
31067
|
+
}
|
|
31068
|
+
/**
|
|
28744
31069
|
* Acquire a lock for the given key, execute the callback, then release.
|
|
28745
31070
|
* If a lock is already held, waits for it to be released before acquiring.
|
|
28746
31071
|
*/
|
|
@@ -28774,6 +31099,7 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
28774
31099
|
this.hooks = config.hooks;
|
|
28775
31100
|
this.mastra = config.mastra;
|
|
28776
31101
|
this.memory = config.memory;
|
|
31102
|
+
this.curationCadence = config.curationCadence;
|
|
28777
31103
|
const resolveModel = (model, defaultModel) => model === "default" ? defaultModel : model;
|
|
28778
31104
|
const observationModel = resolveModel(config.model, OBSERVATIONAL_MEMORY_DEFAULTS.observation.model) ?? resolveModel(config.observation?.model, OBSERVATIONAL_MEMORY_DEFAULTS.observation.model) ?? resolveModel(config.reflection?.model, OBSERVATIONAL_MEMORY_DEFAULTS.observation.model) ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.model;
|
|
28779
31105
|
const reflectionModel = resolveModel(config.model, OBSERVATIONAL_MEMORY_DEFAULTS.reflection.model) ?? resolveModel(config.reflection?.model, OBSERVATIONAL_MEMORY_DEFAULTS.reflection.model) ?? resolveModel(config.observation?.model, OBSERVATIONAL_MEMORY_DEFAULTS.reflection.model) ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.model;
|
|
@@ -28869,7 +31195,8 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
28869
31195
|
getCompressionStartLevel: (rc) => this.getCompressionStartLevel(rc),
|
|
28870
31196
|
resolveModel: (inputTokens) => this.resolveReflectionModel(inputTokens),
|
|
28871
31197
|
mastra: config.mastra,
|
|
28872
|
-
memory: this.memory
|
|
31198
|
+
memory: this.memory,
|
|
31199
|
+
onReflectionCommitted: config.onReflectionCommitted
|
|
28873
31200
|
});
|
|
28874
31201
|
this.validateBufferConfig();
|
|
28875
31202
|
omDebug(`[OM:init] new ObservationalMemory instance created — scope=${this.scope}, messageTokens=${JSON.stringify(this.observationConfig.messageTokens)}, obsAsyncEnabled=${this.buffering.isAsyncObservationEnabled()}, bufferTokens=${this.observationConfig.bufferTokens}, bufferActivation=${this.observationConfig.bufferActivation}, blockAfter=${this.observationConfig.blockAfter}, reflectionTokens=${this.reflectionConfig.observationTokens}, refAsyncEnabled=${this.buffering.isAsyncReflectionEnabled()}, refAsyncActivation=${this.reflectionConfig.bufferActivation}, refBlockAfter=${this.reflectionConfig.blockAfter}`);
|
|
@@ -29741,7 +32068,7 @@ ${formattedMessages}
|
|
|
29741
32068
|
if (!this.buffering.isAsyncObservationEnabled()) return false;
|
|
29742
32069
|
const lockKey = this.buffering.getLockKey(opts.threadId, opts.resourceId);
|
|
29743
32070
|
const shouldTrigger = this.buffering.shouldTriggerAsyncObservation(opts.pendingTokens, lockKey, opts.record, this.storage, opts.threshold);
|
|
29744
|
-
if (shouldTrigger) this.startAsyncBufferedObservation(opts.record, opts.threadId, opts.unobservedMessages, lockKey, opts.writer, opts.unbufferedPendingTokens, opts.requestContext);
|
|
32071
|
+
if (shouldTrigger) this.trackBackgroundWork(this.startAsyncBufferedObservation(opts.record, opts.threadId, opts.unobservedMessages, lockKey, opts.writer, opts.unbufferedPendingTokens, opts.requestContext));
|
|
29745
32072
|
return shouldTrigger;
|
|
29746
32073
|
}
|
|
29747
32074
|
isMessageList(value) {
|
|
@@ -30343,6 +32670,7 @@ ${formattedMessages}
|
|
|
30343
32670
|
writer,
|
|
30344
32671
|
agent: opts.agent,
|
|
30345
32672
|
sendSignal: opts.sendSignal,
|
|
32673
|
+
sendStateSignal: opts.sendStateSignal,
|
|
30346
32674
|
requestContext,
|
|
30347
32675
|
currentModel: opts.currentModel,
|
|
30348
32676
|
observabilityContext
|
|
@@ -30687,6 +33015,8 @@ ${formattedMessages}
|
|
|
30687
33015
|
messageList: opts.messageList,
|
|
30688
33016
|
reflectionHooks,
|
|
30689
33017
|
agent: opts.agent,
|
|
33018
|
+
sendSignal: opts.sendSignal,
|
|
33019
|
+
sendStateSignal: opts.sendStateSignal,
|
|
30690
33020
|
requestContext,
|
|
30691
33021
|
writer: opts.writer,
|
|
30692
33022
|
observabilityContext: opts.observabilityContext
|
|
@@ -30707,6 +33037,9 @@ ${formattedMessages}
|
|
|
30707
33037
|
});
|
|
30708
33038
|
const record = await this.getOrCreateRecord(threadId, resourceId);
|
|
30709
33039
|
const reflected = record.generationCount > generationBefore && generationBefore >= 0;
|
|
33040
|
+
if (observed) this.maybeTriggerCadenceCuration(threadId, resourceId, record, requestContext).catch((error) => {
|
|
33041
|
+
omDebug(`[OM:observe] cadence curation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
33042
|
+
});
|
|
30710
33043
|
return {
|
|
30711
33044
|
observed,
|
|
30712
33045
|
reflected,
|
|
@@ -30714,6 +33047,31 @@ ${formattedMessages}
|
|
|
30714
33047
|
};
|
|
30715
33048
|
}
|
|
30716
33049
|
/**
|
|
33050
|
+
* Count committed observation runs on the sync observe path and run the curator every
|
|
33051
|
+
* `curationCadence` runs. The counter is persisted at `record.config.subconscious.observationRuns`
|
|
33052
|
+
* (the OM record's config jsonb, deep-merged; threshold resolution only reads `_overrides`, so the
|
|
33053
|
+
* sibling key is inert). Concurrent commits can miscount — the curator run is advisory, and the
|
|
33054
|
+
* curation cursor is the real serializer. The async-buffer lane bypasses observe(); deployments
|
|
33055
|
+
* that gate on this cadence (factory's resource scope) disable async buffering.
|
|
33056
|
+
*/
|
|
33057
|
+
async maybeTriggerCadenceCuration(threadId, resourceId, record, requestContext) {
|
|
33058
|
+
const cadence = this.curationCadence;
|
|
33059
|
+
const memory = this.memory;
|
|
33060
|
+
if (!cadence || cadence < 1 || !memory) return;
|
|
33061
|
+
const runs = ((record.config ?? {}).subconscious?.observationRuns ?? 0) + 1;
|
|
33062
|
+
const fire = runs >= cadence;
|
|
33063
|
+
await this.storage.updateObservationalMemoryConfig({
|
|
33064
|
+
id: record.id,
|
|
33065
|
+
config: { subconscious: { observationRuns: fire ? 0 : runs } }
|
|
33066
|
+
});
|
|
33067
|
+
if (!fire) return;
|
|
33068
|
+
omDebug(`[OM:observe] cadence curation outcome=${(await memory.runCuration({
|
|
33069
|
+
threadId,
|
|
33070
|
+
resourceId: resourceId ?? threadId,
|
|
33071
|
+
requestContext
|
|
33072
|
+
})).outcome} thread=${threadId}`);
|
|
33073
|
+
}
|
|
33074
|
+
/**
|
|
30717
33075
|
* Manually trigger reflection with optional guidance prompt.
|
|
30718
33076
|
*
|
|
30719
33077
|
* @example
|
|
@@ -30731,6 +33089,18 @@ ${formattedMessages}
|
|
|
30731
33089
|
record,
|
|
30732
33090
|
usage: void 0
|
|
30733
33091
|
};
|
|
33092
|
+
if (record.isReflecting) {
|
|
33093
|
+
if (isOpActiveInProcess(record.id, "reflecting")) {
|
|
33094
|
+
omDebug(`[OM:reflect] isReflecting=true and active in this process, skipping`);
|
|
33095
|
+
return {
|
|
33096
|
+
reflected: false,
|
|
33097
|
+
record,
|
|
33098
|
+
usage: void 0
|
|
33099
|
+
};
|
|
33100
|
+
}
|
|
33101
|
+
omDebug(`[OM:reflect] isReflecting=true but NOT active in this process — stale flag from dead process, clearing`);
|
|
33102
|
+
await this.storage.setReflectingFlag(record.id, false);
|
|
33103
|
+
}
|
|
30734
33104
|
await this.storage.setReflectingFlag(record.id, true);
|
|
30735
33105
|
registerOp(record.id, "reflecting");
|
|
30736
33106
|
const hooks = this.composeHooks(void 0, {
|
|
@@ -30916,6 +33286,8 @@ ${formattedMessages}
|
|
|
30916
33286
|
resourceId: opts.resourceId,
|
|
30917
33287
|
messageList: opts.messageList,
|
|
30918
33288
|
agent: opts.agent,
|
|
33289
|
+
sendSignal: opts.sendSignal,
|
|
33290
|
+
sendStateSignal: opts.sendStateSignal,
|
|
30919
33291
|
observabilityContext: opts.observabilityContext,
|
|
30920
33292
|
hooks: opts.hooks
|
|
30921
33293
|
});
|
|
@@ -31138,6 +33510,7 @@ var ObservationalMemoryProcessor = class {
|
|
|
31138
33510
|
});
|
|
31139
33511
|
this.turn.writer = writer;
|
|
31140
33512
|
this.turn.sendSignal = args.sendSignal;
|
|
33513
|
+
this.turn.sendStateSignal = args.sendStateSignal;
|
|
31141
33514
|
this.turn.agent = args.agent;
|
|
31142
33515
|
this.turn.requestContext = requestContext;
|
|
31143
33516
|
await this.turn.start(this.memory);
|
|
@@ -31278,6 +33651,7 @@ function getObservationsAsOf(activeObservations, asOf) {
|
|
|
31278
33651
|
}
|
|
31279
33652
|
var observational_memory_exports = /* @__PURE__ */ __exportAll({
|
|
31280
33653
|
Extractor: () => Extractor,
|
|
33654
|
+
KnowledgeSemanticIndexCoordinator: () => KnowledgeSemanticIndexCoordinator,
|
|
31281
33655
|
ModelByInputTokens: () => ModelByInputTokens,
|
|
31282
33656
|
OBSERVATIONAL_MEMORY_DEFAULTS: () => OBSERVATIONAL_MEMORY_DEFAULTS,
|
|
31283
33657
|
OBSERVATION_CONTEXT_INSTRUCTIONS: () => OBSERVATION_CONTEXT_INSTRUCTIONS,
|
|
@@ -31286,10 +33660,16 @@ var observational_memory_exports = /* @__PURE__ */ __exportAll({
|
|
|
31286
33660
|
OBSERVER_SYSTEM_PROMPT: () => OBSERVER_SYSTEM_PROMPT,
|
|
31287
33661
|
ObservationalMemory: () => ObservationalMemory,
|
|
31288
33662
|
ObservationalMemoryProcessor: () => ObservationalMemoryProcessor,
|
|
33663
|
+
SUBCONSCIOUS_ACTIVITY_STATE_ID: () => SUBCONSCIOUS_ACTIVITY_STATE_ID,
|
|
33664
|
+
StaleKnowledgeSemanticIndexError: () => StaleKnowledgeSemanticIndexError,
|
|
33665
|
+
Subconscious: () => Subconscious,
|
|
33666
|
+
SubconsciousCaptureExtractor: () => SubconsciousCaptureExtractor,
|
|
33667
|
+
SubconsciousRemindExtractor: () => SubconsciousRemindExtractor,
|
|
31289
33668
|
TokenCounter: () => TokenCounter,
|
|
31290
33669
|
WorkingMemoryExtractor: () => WorkingMemoryExtractor,
|
|
31291
33670
|
buildObserverPrompt: () => buildObserverPrompt,
|
|
31292
33671
|
buildObserverSystemPrompt: () => buildObserverSystemPrompt,
|
|
33672
|
+
buildSubconsciousActivitySnapshot: () => buildSubconsciousActivitySnapshot,
|
|
31293
33673
|
combineObservationGroupRanges: () => combineObservationGroupRanges,
|
|
31294
33674
|
deriveObservationGroupProvenance: () => deriveObservationGroupProvenance,
|
|
31295
33675
|
extractCurrentTask: () => extractCurrentTask,
|
|
@@ -31301,10 +33681,13 @@ var observational_memory_exports = /* @__PURE__ */ __exportAll({
|
|
|
31301
33681
|
parseAnchorId: () => parseAnchorId,
|
|
31302
33682
|
parseObservationGroups: () => parseObservationGroups,
|
|
31303
33683
|
parseObserverOutput: () => parseObserverOutput,
|
|
33684
|
+
publishSubconsciousActivity: () => publishSubconsciousActivity,
|
|
31304
33685
|
reconcileObservationGroupsFromReflection: () => reconcileObservationGroupsFromReflection,
|
|
31305
33686
|
renderObservationGroupsForReflection: () => renderObservationGroupsForReflection,
|
|
33687
|
+
renderSubconsciousActivity: () => renderSubconsciousActivity,
|
|
31306
33688
|
stripEphemeralAnchorIds: () => stripEphemeralAnchorIds,
|
|
31307
33689
|
stripObservationGroups: () => stripObservationGroups,
|
|
33690
|
+
subconsciousCaptureSchema: () => subconsciousCaptureSchema,
|
|
31308
33691
|
summarizeConversation: () => summarizeConversation,
|
|
31309
33692
|
wrapInObservationGroup: () => wrapInObservationGroup
|
|
31310
33693
|
});
|
|
@@ -31528,10 +33911,11 @@ const DEFAULT_EMBEDDING_CACHE_MAX_SIZE = 1e3;
|
|
|
31528
33911
|
* Concrete implementation of MastraMemory that adds support for thread configuration
|
|
31529
33912
|
* and message injection.
|
|
31530
33913
|
*/
|
|
31531
|
-
var Memory = class extends _mastra_core_memory.MastraMemory {
|
|
33914
|
+
var Memory = class Memory extends _mastra_core_memory.MastraMemory {
|
|
31532
33915
|
_omEngine;
|
|
31533
33916
|
_omEngineInstance;
|
|
31534
33917
|
_mastraInstance;
|
|
33918
|
+
_knowledgeSemanticIndex;
|
|
31535
33919
|
/**
|
|
31536
33920
|
* Every vector cleanup that deleteThread or deleteMessages started in the background.
|
|
31537
33921
|
* Callers do not wait for the cleanup, so this handle is the only join point.
|
|
@@ -31544,6 +33928,25 @@ var Memory = class extends _mastra_core_memory.MastraMemory {
|
|
|
31544
33928
|
trackVectorCleanup(cleanup) {
|
|
31545
33929
|
this.pendingVectorCleanup = Promise.allSettled([this.pendingVectorCleanup, cleanup]).then(() => void 0);
|
|
31546
33930
|
}
|
|
33931
|
+
/**
|
|
33932
|
+
* Resolve once all background work this Memory started has finished: observational-memory
|
|
33933
|
+
* cycles (buffered observation and reflection, including the nested agent runs they spawn)
|
|
33934
|
+
* and vector cleanup from `deleteThread` / `deleteMessages`.
|
|
33935
|
+
*
|
|
33936
|
+
* Callers that own the storage connection should await this before closing it, otherwise
|
|
33937
|
+
* background statements can race the close.
|
|
33938
|
+
*
|
|
33939
|
+
* ```ts
|
|
33940
|
+
* await agent.generate('hello', { memory: { thread, resource } });
|
|
33941
|
+
* await memory.settled();
|
|
33942
|
+
* await store.close();
|
|
33943
|
+
* ```
|
|
33944
|
+
*/
|
|
33945
|
+
async settled() {
|
|
33946
|
+
await this.pendingVectorCleanup;
|
|
33947
|
+
await (this._omEngine ? await this._omEngine : this._omEngineInstance)?.settled();
|
|
33948
|
+
await this.pendingVectorCleanup;
|
|
33949
|
+
}
|
|
31547
33950
|
/** The shared ObservationalMemory engine. Lazily created on first access. */
|
|
31548
33951
|
get omEngine() {
|
|
31549
33952
|
if (!this._omEngine) this._omEngine = this._initOMEngine().then((engine) => {
|
|
@@ -31560,7 +33963,60 @@ var Memory = class extends _mastra_core_memory.MastraMemory {
|
|
|
31560
33963
|
else this._omEngine?.then((engine) => engine?.__registerMastra(mastra));
|
|
31561
33964
|
}
|
|
31562
33965
|
getMergedThreadConfig(config) {
|
|
31563
|
-
|
|
33966
|
+
const merged = super.getMergedThreadConfig(config);
|
|
33967
|
+
return this.applyManagedWorkingMemoryDefaults(this.applySubconsciousDefaults(merged));
|
|
33968
|
+
}
|
|
33969
|
+
applySubconsciousDefaults(config) {
|
|
33970
|
+
const omConfig = normalizeObservationalMemoryConfig(config.observationalMemory);
|
|
33971
|
+
if (!omConfig?.experimental_subconscious) return config;
|
|
33972
|
+
if (!(omConfig.experimental_subconscious instanceof Subconscious)) throw new Error("observationalMemory.experimental_subconscious must be a Subconscious instance.");
|
|
33973
|
+
const observation = omConfig.observation ?? {};
|
|
33974
|
+
const extract = observation.extract ?? [];
|
|
33975
|
+
const existingSlugs = new Set(extract.map((extractor) => extractor.slug));
|
|
33976
|
+
const subconsciousExtractors = omConfig.experimental_subconscious.createObservationExtractors(observation.model ?? omConfig.model).filter((extractor) => !existingSlugs.has(extractor.slug));
|
|
33977
|
+
return {
|
|
33978
|
+
...config,
|
|
33979
|
+
observationalMemory: {
|
|
33980
|
+
...omConfig,
|
|
33981
|
+
observation: {
|
|
33982
|
+
...observation,
|
|
33983
|
+
extract: [...extract, ...subconsciousExtractors]
|
|
33984
|
+
}
|
|
33985
|
+
}
|
|
33986
|
+
};
|
|
33987
|
+
}
|
|
33988
|
+
/** Threads with a curation currently in flight in this process; guards same-process double-fire only. */
|
|
33989
|
+
_curationsInFlight = /* @__PURE__ */ new Set();
|
|
33990
|
+
/**
|
|
33991
|
+
* Run the subconscious curator directly over the pending fact worklist, without a reflection.
|
|
33992
|
+
* Cross-process serialization is the curation cursor's job; a lost race wastes one advisory run.
|
|
33993
|
+
*
|
|
33994
|
+
* Outcomes: `ran` (curator executed), `no-op` (empty worklist and no prompt, or no curate agent
|
|
33995
|
+
* configured), `skipped` (a curation for this thread is already in flight in this process), and
|
|
33996
|
+
* `no-model` (no per-agent, observational memory, or main-agent model could be resolved).
|
|
33997
|
+
*/
|
|
33998
|
+
async runCuration(options) {
|
|
33999
|
+
const omConfig = normalizeObservationalMemoryConfig(this.threadConfig.observationalMemory);
|
|
34000
|
+
const subconscious = omConfig?.experimental_subconscious;
|
|
34001
|
+
if (!omConfig || !(subconscious instanceof Subconscious)) return { outcome: "no-op" };
|
|
34002
|
+
if (this._curationsInFlight.has(options.threadId)) return { outcome: "skipped" };
|
|
34003
|
+
this._curationsInFlight.add(options.threadId);
|
|
34004
|
+
try {
|
|
34005
|
+
return { outcome: await createCuratorHandler(this, subconscious.resolved, new Memory({
|
|
34006
|
+
storage: this.storage,
|
|
34007
|
+
options: { observationalMemory: false }
|
|
34008
|
+
}), { omModel: omConfig.observation?.model ?? omConfig.model })({
|
|
34009
|
+
parentThreadId: options.threadId,
|
|
34010
|
+
resourceId: options.resourceId,
|
|
34011
|
+
observations: options.prompt ?? "",
|
|
34012
|
+
requestContext: options.requestContext
|
|
34013
|
+
}) === "ran" ? "ran" : "no-op" };
|
|
34014
|
+
} catch (error) {
|
|
34015
|
+
if (error instanceof Error && error.message.includes("requires the main agent to resolve its model")) return { outcome: "no-model" };
|
|
34016
|
+
throw error;
|
|
34017
|
+
} finally {
|
|
34018
|
+
this._curationsInFlight.delete(options.threadId);
|
|
34019
|
+
}
|
|
31564
34020
|
}
|
|
31565
34021
|
applyManagedWorkingMemoryDefaults(config) {
|
|
31566
34022
|
const omConfig = normalizeObservationalMemoryConfig(config.observationalMemory);
|
|
@@ -31604,6 +34060,28 @@ var Memory = class extends _mastra_core_memory.MastraMemory {
|
|
|
31604
34060
|
if (!this.vector) throw new Error("`retrieval: { vector: true }` requires a vector store. Pass a `vector` option to your Memory instance.");
|
|
31605
34061
|
if (!this.embedder) throw new Error("`retrieval: { vector: true }` requires an embedder. Pass an `embedder` option to your Memory instance.");
|
|
31606
34062
|
}
|
|
34063
|
+
if (omConfig?.experimental_subconscious) {
|
|
34064
|
+
if (!this.vector) throw new Error("Subconscious semantic knowledge requires a vector store. Pass a `vector` option to Memory.");
|
|
34065
|
+
if (!this.embedder) throw new Error("Subconscious semantic knowledge requires an embedder. Pass an `embedder` option to Memory.");
|
|
34066
|
+
}
|
|
34067
|
+
}
|
|
34068
|
+
async getKnowledgeStore() {
|
|
34069
|
+
const store = await this.storage.getStore("knowledge");
|
|
34070
|
+
if (!store) throw new Error(`Knowledge storage domain is not available on ${this.storage.constructor.name}`);
|
|
34071
|
+
return store;
|
|
34072
|
+
}
|
|
34073
|
+
async getKnowledgeSemanticIndex() {
|
|
34074
|
+
if (!this.vector || !this.embedder) throw new Error("Subconscious semantic knowledge requires both a vector store and an embedder.");
|
|
34075
|
+
this._knowledgeSemanticIndex ??= this.getKnowledgeStore().then((knowledge) => new KnowledgeSemanticIndexCoordinator({
|
|
34076
|
+
knowledge,
|
|
34077
|
+
vector: this.vector,
|
|
34078
|
+
embedder: this.embedder,
|
|
34079
|
+
embedderOptions: this.embedderOptions
|
|
34080
|
+
}));
|
|
34081
|
+
return this._knowledgeSemanticIndex;
|
|
34082
|
+
}
|
|
34083
|
+
async drainKnowledgeSemanticIndex(scope) {
|
|
34084
|
+
return (await this.getKnowledgeSemanticIndex()).drain(scope);
|
|
31607
34085
|
}
|
|
31608
34086
|
/**
|
|
31609
34087
|
* Gets the memory storage domain, throwing if not available.
|
|
@@ -32372,6 +34850,7 @@ ${workingMemory}`;
|
|
|
32372
34850
|
if (!_mastra_core_features.coreFeatures.has("observationalMemory")) throw new Error("Observational memory is enabled but the installed version of @mastra/core does not support it. Please upgrade @mastra/core to a version that includes observational memory support.");
|
|
32373
34851
|
if (omConfig.observation?.bufferTokens !== false && !_mastra_core_features.coreFeatures.has("asyncBuffering")) throw new Error("Observational memory async buffering is enabled by default but the installed version of @mastra/core does not support it. Either upgrade @mastra/core, @mastra/memory, and your storage adapter (@mastra/libsql, @mastra/pg, @mastra/mongodb, or @mastra/convex) to the latest version, or explicitly disable async buffering by setting `observation: { bufferTokens: false }` in your observationalMemory config.");
|
|
32374
34852
|
if (!_mastra_core_features.coreFeatures.has("request-response-id-rotation")) throw new Error("Observational memory requires @mastra/core support for request-response-id-rotation. Please bump @mastra/core to a newer version.");
|
|
34853
|
+
if (omConfig.experimental_subconscious) await this.getKnowledgeStore();
|
|
32375
34854
|
const { ObservationalMemory: OMClass } = await Promise.resolve().then(() => observational_memory_exports);
|
|
32376
34855
|
const onIndexObservations = this.hasRetrievalSearch(omConfig.retrieval) ? async (observation) => {
|
|
32377
34856
|
await this.indexObservation(observation);
|
|
@@ -32385,9 +34864,21 @@ ${workingMemory}`;
|
|
|
32385
34864
|
activateOnProviderChange: omConfig.activateOnProviderChange,
|
|
32386
34865
|
shareTokenBudget: omConfig.shareTokenBudget,
|
|
32387
34866
|
model: omConfig.model,
|
|
34867
|
+
curationCadence: omConfig.experimental_subconscious instanceof Subconscious ? omConfig.experimental_subconscious.resolved.curationCadence : void 0,
|
|
32388
34868
|
mastra: this._mastraInstance,
|
|
32389
34869
|
onIndexObservations,
|
|
32390
34870
|
hooks: omConfig.hooks,
|
|
34871
|
+
onReflectionCommitted: omConfig.experimental_subconscious instanceof Subconscious ? (() => {
|
|
34872
|
+
const resolved = omConfig.experimental_subconscious.resolved;
|
|
34873
|
+
const omModel = omConfig.observation?.model ?? omConfig.model;
|
|
34874
|
+
return composeReflectionAgentHandlers([createCuratorHandler(this, resolved, new Memory({
|
|
34875
|
+
storage: this.storage,
|
|
34876
|
+
options: { observationalMemory: false }
|
|
34877
|
+
}), { omModel }), createLearnerHandler(this, resolved, new Memory({
|
|
34878
|
+
storage: this.storage,
|
|
34879
|
+
options: { observationalMemory: false }
|
|
34880
|
+
}), { omModel })]);
|
|
34881
|
+
})() : void 0,
|
|
32391
34882
|
observation: omConfig.observation ? {
|
|
32392
34883
|
model: omConfig.observation.model,
|
|
32393
34884
|
messageTokens: omConfig.observation.messageTokens,
|
|
@@ -32777,6 +35268,7 @@ Notes:
|
|
|
32777
35268
|
retrievalScope: typeof omConfig.retrieval === "object" ? omConfig.retrieval.scope ?? "resource" : "resource",
|
|
32778
35269
|
searchEnabled: this.hasRetrievalSearch(omConfig.retrieval)
|
|
32779
35270
|
});
|
|
35271
|
+
if (omConfig?.experimental_subconscious instanceof Subconscious && omConfig.experimental_subconscious.resolved.tools) Object.assign(tools, createKnowledgeTools(this));
|
|
32780
35272
|
return tools;
|
|
32781
35273
|
}
|
|
32782
35274
|
/**
|
|
@@ -33257,6 +35749,8 @@ Notes:
|
|
|
33257
35749
|
if (om) processors.push(om);
|
|
33258
35750
|
const wm = await this.createWorkingMemoryStateProcessor(configuredProcessors, context);
|
|
33259
35751
|
if (wm) processors.push(wm);
|
|
35752
|
+
const pins = await this.createPinnedStateProcessor(configuredProcessors, context);
|
|
35753
|
+
if (pins) processors.push(pins);
|
|
33260
35754
|
return processors;
|
|
33261
35755
|
}
|
|
33262
35756
|
/**
|
|
@@ -33304,6 +35798,21 @@ Notes:
|
|
|
33304
35798
|
if (configuredProcessors.some((p) => !("workflow" in p) && p.id === WORKING_MEMORY_STATE_PROCESSOR_ID)) return null;
|
|
33305
35799
|
return new WorkingMemoryStateProcessor(this, runtimeMemory?.memoryConfig);
|
|
33306
35800
|
}
|
|
35801
|
+
/**
|
|
35802
|
+
* Creates a PinnedStateProcessor when Subconscious pins are enabled on the
|
|
35803
|
+
* merged thread config. The gate is the validated `resolved.pins` on the
|
|
35804
|
+
* Subconscious instance, never the raw user object. Returns null when pins
|
|
35805
|
+
* are off or the processor is already present in the user's configured
|
|
35806
|
+
* processors.
|
|
35807
|
+
*/
|
|
35808
|
+
async createPinnedStateProcessor(configuredProcessors = [], context) {
|
|
35809
|
+
const runtimeMemory = context?.get("MastraMemory");
|
|
35810
|
+
const subconscious = normalizeObservationalMemoryConfig(this.getMergedThreadConfig(runtimeMemory?.memoryConfig).observationalMemory)?.experimental_subconscious;
|
|
35811
|
+
if (!(subconscious instanceof Subconscious) || subconscious.resolved.pins === false) return null;
|
|
35812
|
+
const { PinnedStateProcessor, SUBCONSCIOUS_PINS_STATE_ID } = await Promise.resolve().then(() => subconscious_exports);
|
|
35813
|
+
if (configuredProcessors.some((p) => !("workflow" in p) && p.id === SUBCONSCIOUS_PINS_STATE_ID)) return null;
|
|
35814
|
+
return new PinnedStateProcessor({ getKnowledgeStore: () => this.storage.getStore("knowledge") });
|
|
35815
|
+
}
|
|
33307
35816
|
};
|
|
33308
35817
|
//#endregion
|
|
33309
35818
|
//#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/ignore/7.0.5/d6411cd18dd20fbb425503c2ba0ac12fc6b5c7b2b2481cbdc797c212eb8be050/node_modules/ignore/index.js
|
|
@@ -34096,23 +36605,23 @@ const createModelInstance = async (provider, modelId, version = "v2") => {
|
|
|
34096
36605
|
try {
|
|
34097
36606
|
const providerFn = version === `v1` ? { v1: {
|
|
34098
36607
|
openai: async () => {
|
|
34099
|
-
const { openai } = await Promise.resolve().then(() => require("./dist-
|
|
36608
|
+
const { openai } = await Promise.resolve().then(() => require("./dist-2zVeGGHi.cjs"));
|
|
34100
36609
|
return openai(modelId);
|
|
34101
36610
|
},
|
|
34102
36611
|
anthropic: async () => {
|
|
34103
|
-
const { anthropic } = await Promise.resolve().then(() => require("./dist-
|
|
36612
|
+
const { anthropic } = await Promise.resolve().then(() => require("./dist-BfVTO0pC.cjs"));
|
|
34104
36613
|
return anthropic(modelId);
|
|
34105
36614
|
},
|
|
34106
36615
|
groq: async () => {
|
|
34107
|
-
const { groq } = await Promise.resolve().then(() => require("./dist-
|
|
36616
|
+
const { groq } = await Promise.resolve().then(() => require("./dist-D4NzuG3G.cjs"));
|
|
34108
36617
|
return groq(modelId);
|
|
34109
36618
|
},
|
|
34110
36619
|
xai: async () => {
|
|
34111
|
-
const { xai } = await Promise.resolve().then(() => require("./dist-
|
|
36620
|
+
const { xai } = await Promise.resolve().then(() => require("./dist-Be7Caz3Z.cjs"));
|
|
34112
36621
|
return xai(modelId);
|
|
34113
36622
|
},
|
|
34114
36623
|
google: async () => {
|
|
34115
|
-
const { google } = await Promise.resolve().then(() => require("./dist-
|
|
36624
|
+
const { google } = await Promise.resolve().then(() => require("./dist-8-Z5v77M.cjs"));
|
|
34116
36625
|
return google(modelId);
|
|
34117
36626
|
}
|
|
34118
36627
|
} }[version][provider] : () => new _mastra_core_llm.ModelRouterLanguageModel(`${provider}/${modelId}`);
|
|
@@ -43690,4 +46199,4 @@ const agentBuilderWorkflows = {
|
|
|
43690
46199
|
//#endregion
|
|
43691
46200
|
exports.agentBuilderWorkflows = agentBuilderWorkflows;
|
|
43692
46201
|
|
|
43693
|
-
//# sourceMappingURL=dist-
|
|
46202
|
+
//# sourceMappingURL=dist-DERatX43.cjs.map
|