@crewx/sdk 0.8.0-rc.72 → 0.8.0-rc.74
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/README.md +380 -818
- package/dist/adapter/context-builder.d.ts +35 -0
- package/dist/adapter/context-builder.js +87 -0
- package/dist/adapter/index.d.ts +5 -0
- package/dist/{core/remote → adapter}/index.js +3 -2
- package/dist/adapter/plugin-helper.d.ts +19 -0
- package/dist/adapter/plugin-helper.js +45 -0
- package/dist/adapter/scoped-store.d.ts +12 -0
- package/dist/adapter/scoped-store.js +43 -0
- package/dist/adapter/types.d.ts +264 -0
- package/dist/adapter/types.js +23 -0
- package/dist/agent/resolver.d.ts +18 -0
- package/dist/agent/resolver.js +46 -0
- package/dist/boxing/box-storage.interface.d.ts +12 -0
- package/dist/boxing/box-storage.interface.js +3 -0
- package/dist/boxing/box.service.d.ts +4 -0
- package/dist/boxing/box.service.js +5 -1
- package/dist/boxing/box.types.d.ts +4 -0
- package/dist/boxing/box.types.js +3 -0
- package/dist/boxing/context-builder.d.ts +6 -7
- package/dist/boxing/context-builder.js +3 -0
- package/dist/client/CrewxClient.d.ts +65 -0
- package/dist/client/CrewxClient.js +86 -0
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.js +6 -0
- package/dist/config/loader.browser.d.ts +14 -0
- package/dist/config/loader.browser.js +59 -0
- package/dist/config/loader.d.ts +19 -0
- package/dist/config/loader.js +95 -0
- package/dist/conversation/index.d.ts +5 -3
- package/dist/conversation/index.js +8 -3
- package/dist/conversation/sqlite-provider.d.ts +21 -0
- package/dist/conversation/sqlite-provider.js +178 -0
- package/dist/conversation/to-task-reader.d.ts +14 -0
- package/dist/conversation/to-task-reader.js +28 -0
- package/dist/conversation/to-template-messages.d.ts +15 -0
- package/dist/conversation/to-template-messages.js +34 -0
- package/dist/conversation/types.d.ts +101 -0
- package/dist/conversation/types.js +10 -0
- package/dist/esm/agent/resolver.js +41 -0
- package/dist/esm/boxing/box-storage.interface.js +5 -0
- package/dist/esm/boxing/box.service.js +69 -0
- package/dist/esm/boxing/box.types.js +5 -0
- package/dist/esm/boxing/context-builder.js +76 -0
- package/dist/esm/client/CrewxClient.js +82 -0
- package/dist/esm/client/index.js +2 -0
- package/dist/esm/config/loader.browser.js +54 -0
- package/dist/esm/config/loader.js +77 -0
- package/dist/esm/events/TypedEventEmitter.js +61 -0
- package/dist/esm/events/types.js +8 -0
- package/dist/esm/facade/Crewx.browser.js +310 -0
- package/dist/esm/facade/Crewx.js +941 -0
- package/dist/esm/hooks/define.js +10 -0
- package/dist/esm/hooks/dispatch.js +76 -0
- package/dist/esm/hooks/index.js +6 -0
- package/dist/esm/hooks/observer.js +56 -0
- package/dist/esm/hooks/plugin.js +12 -0
- package/dist/esm/hooks/types.js +9 -0
- package/dist/esm/index.browser.js +15 -0
- package/dist/esm/index.js +60 -0
- package/dist/esm/layout/loader.js +268 -0
- package/dist/esm/layout/props-validator.js +297 -0
- package/dist/esm/layout/renderer.js +180 -0
- package/dist/esm/layout/types.js +31 -0
- package/dist/esm/parallel/agent-runtime.js +21 -0
- package/dist/esm/parallel/helpers.js +214 -0
- package/dist/esm/parallel/index.js +5 -0
- package/dist/esm/parallel/parallel-runner.js +221 -0
- package/dist/esm/parallel/types.js +5 -0
- package/dist/esm/parsers/agent-call.util.js +15 -0
- package/dist/esm/parsers/claude.parser.js +64 -0
- package/dist/esm/parsers/codex.parser.js +97 -0
- package/dist/esm/parsers/copilot.parser.js +63 -0
- package/dist/esm/parsers/gemini.parser.js +43 -0
- package/dist/esm/parsers/opencode.parser.js +73 -0
- package/dist/esm/parsers/router.js +53 -0
- package/dist/esm/platform/BrowserFsAdapter.js +80 -0
- package/dist/esm/platform/IFsAdapter.js +2 -0
- package/dist/esm/platform/NodeFsAdapter.js +34 -0
- package/dist/esm/plugin/plugin-provider.js +202 -0
- package/dist/esm/plugin/types.js +8 -0
- package/dist/esm/plugin.js +25 -0
- package/dist/esm/provider/bridge.browser.js +43 -0
- package/dist/esm/provider/bridge.js +373 -0
- package/dist/esm/provider/parse-usage.js +80 -0
- package/dist/esm/provider/register-api.js +21 -0
- package/dist/esm/provider/vercel-runtime.js +310 -0
- package/dist/esm/remote/index.js +10 -0
- package/dist/esm/remote/remote-agent-manager.js +194 -0
- package/dist/esm/remote/remote-provider.js +98 -0
- package/dist/esm/remote/remote-transport.js +79 -0
- package/dist/esm/remote/types.js +8 -0
- package/dist/esm/server/auth.js +31 -0
- package/dist/esm/server/handler.js +72 -0
- package/dist/esm/server/index.js +5 -0
- package/dist/esm/server/tool-adapter.js +92 -0
- package/dist/esm/template/engine.js +100 -0
- package/dist/esm/template/helpers/exec.browser.js +31 -0
- package/dist/esm/template/helpers/exec.js +220 -0
- package/dist/esm/template/helpers/fenced_code.js +17 -0
- package/dist/esm/template/helpers/include.js +20 -0
- package/dist/esm/template/helpers/p1p2.js +83 -0
- package/dist/esm/template/loader/DocumentLoader.js +124 -0
- package/dist/esm/template/types.js +5 -0
- package/dist/esm/tools/delegate.js +57 -0
- package/dist/esm/tools/index.js +5 -0
- package/dist/esm/tools/node/builtin.js +541 -0
- package/dist/esm/tools/node/index.js +54 -0
- package/dist/esm/types/index.js +27 -0
- package/dist/esm/types/task-log.types.js +5 -0
- package/dist/esm/utils/env-defaults.js +23 -0
- package/dist/esm/utils/glob-match.js +38 -0
- package/dist/esm/utils/id.js +46 -0
- package/dist/esm/utils/workspace.js +21 -0
- package/dist/events/TypedEventEmitter.d.ts +31 -0
- package/dist/events/TypedEventEmitter.js +65 -0
- package/dist/events/types.d.ts +139 -0
- package/dist/events/types.js +9 -0
- package/dist/facade/Crewx.browser.d.ts +73 -0
- package/dist/facade/Crewx.browser.js +314 -0
- package/dist/facade/Crewx.d.ts +267 -0
- package/dist/facade/Crewx.js +1299 -0
- package/dist/hooks/define.d.ts +10 -0
- package/dist/hooks/define.js +13 -0
- package/dist/hooks/dispatch.d.ts +61 -0
- package/dist/hooks/dispatch.js +147 -0
- package/dist/hooks/index.d.ts +13 -0
- package/dist/hooks/index.js +24 -0
- package/dist/hooks/observer.d.ts +20 -0
- package/dist/hooks/observer.js +60 -0
- package/dist/hooks/plugin.d.ts +19 -0
- package/dist/hooks/plugin.js +17 -0
- package/dist/hooks/tool-normalize.d.ts +29 -0
- package/dist/hooks/tool-normalize.js +110 -0
- package/dist/hooks/types.d.ts +79 -0
- package/dist/hooks/types.js +12 -0
- package/dist/hooks/yaml-plugin.d.ts +29 -0
- package/dist/hooks/yaml-plugin.js +356 -0
- package/dist/index.browser.d.ts +15 -0
- package/dist/index.browser.js +25 -0
- package/dist/index.d.ts +70 -58
- package/dist/index.js +144 -133
- package/dist/{services/layout-loader.service.d.ts → layout/loader.d.ts} +24 -4
- package/dist/{services/layout-loader.service.js → layout/loader.js} +103 -73
- package/dist/{services/props-validator.service.d.ts → layout/props-validator.d.ts} +7 -1
- package/dist/{services/props-validator.service.js → layout/props-validator.js} +28 -59
- package/dist/{services/layout-renderer.service.d.ts → layout/renderer.d.ts} +28 -14
- package/dist/layout/renderer.js +193 -0
- package/dist/{types/layout.types.d.ts → layout/types.d.ts} +47 -1
- package/dist/{types/layout.types.js → layout/types.js} +15 -1
- package/dist/parallel/agent-runtime.d.ts +31 -0
- package/dist/parallel/agent-runtime.js +25 -0
- package/dist/{core/parallel → parallel}/helpers.d.ts +2 -1
- package/dist/{core/parallel → parallel}/helpers.js +55 -88
- package/dist/parallel/index.d.ts +8 -0
- package/dist/{core/parallel → parallel}/index.js +5 -3
- package/dist/{core/parallel → parallel}/parallel-runner.d.ts +8 -1
- package/dist/{core/parallel → parallel}/parallel-runner.js +53 -57
- package/dist/parallel/types.d.ts +65 -0
- package/dist/parallel/types.js +6 -0
- package/dist/parsers/agent-call.util.d.ts +3 -0
- package/dist/parsers/agent-call.util.js +2 -0
- package/dist/parsers/api.parser.d.ts +10 -0
- package/dist/parsers/api.parser.js +26 -0
- package/dist/parsers/claude.parser.d.ts +8 -0
- package/dist/parsers/claude.parser.js +22 -1
- package/dist/parsers/codex.parser.d.ts +8 -0
- package/dist/parsers/codex.parser.js +11 -0
- package/dist/parsers/copilot.parser.d.ts +9 -0
- package/dist/parsers/copilot.parser.js +8 -0
- package/dist/parsers/gemini.parser.d.ts +10 -0
- package/dist/parsers/gemini.parser.js +10 -0
- package/dist/parsers/opencode.parser.d.ts +12 -0
- package/dist/parsers/opencode.parser.js +76 -0
- package/dist/parsers/router.d.ts +7 -0
- package/dist/parsers/router.js +56 -0
- package/dist/platform/BrowserFsAdapter.d.ts +37 -0
- package/dist/platform/BrowserFsAdapter.js +84 -0
- package/dist/platform/IFsAdapter.d.ts +29 -0
- package/dist/{core/remote/types.js → platform/IFsAdapter.js} +1 -1
- package/dist/platform/NodeFsAdapter.d.ts +16 -0
- package/dist/platform/NodeFsAdapter.js +38 -0
- package/dist/plugin/plugin-provider.d.ts +33 -0
- package/dist/plugin/plugin-provider.js +207 -0
- package/dist/plugin/types.d.ts +53 -0
- package/dist/plugin/types.js +9 -0
- package/dist/plugin.d.ts +33 -0
- package/dist/plugin.js +29 -0
- package/dist/plugins/conversation.d.ts +18 -0
- package/dist/plugins/conversation.js +59 -0
- package/dist/plugins/file-logger.d.ts +29 -0
- package/dist/plugins/file-logger.js +87 -0
- package/dist/plugins/index.d.ts +16 -0
- package/dist/plugins/index.js +19 -0
- package/dist/plugins/sqlite-tracing.d.ts +29 -0
- package/dist/plugins/sqlite-tracing.js +112 -0
- package/dist/provider/bridge.browser.d.ts +49 -0
- package/dist/provider/bridge.browser.js +49 -0
- package/dist/provider/bridge.d.ts +106 -0
- package/dist/provider/bridge.js +380 -0
- package/dist/provider/mastra-runtime.d.ts +45 -0
- package/dist/provider/mastra-runtime.js +208 -0
- package/dist/provider/parse-usage.d.ts +20 -0
- package/dist/provider/parse-usage.js +83 -0
- package/dist/provider/register-api.d.ts +14 -0
- package/dist/provider/register-api.js +24 -0
- package/dist/provider/vercel-runtime.d.ts +54 -0
- package/dist/provider/vercel-runtime.js +347 -0
- package/dist/remote/index.d.ts +13 -0
- package/dist/remote/index.js +32 -0
- package/dist/remote/remote-agent-manager.d.ts +54 -0
- package/dist/{core/remote → remote}/remote-agent-manager.js +100 -97
- package/dist/remote/remote-provider.d.ts +47 -0
- package/dist/remote/remote-provider.js +141 -0
- package/dist/remote/remote-transport.d.ts +32 -0
- package/dist/remote/remote-transport.js +83 -0
- package/dist/remote/types.d.ts +147 -0
- package/dist/remote/types.js +9 -0
- package/dist/server/auth.d.ts +21 -0
- package/dist/server/auth.js +35 -0
- package/dist/server/handler.d.ts +24 -0
- package/dist/server/handler.js +75 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.js +9 -0
- package/dist/server/tool-adapter.d.ts +19 -0
- package/dist/server/tool-adapter.js +95 -0
- package/dist/template/engine.d.ts +28 -0
- package/dist/template/engine.js +137 -0
- package/dist/template/helpers/exec.browser.d.ts +22 -0
- package/dist/template/helpers/exec.browser.js +41 -0
- package/dist/template/helpers/exec.d.ts +60 -0
- package/dist/template/helpers/exec.js +230 -0
- package/dist/template/helpers/fenced_code.d.ts +22 -0
- package/dist/template/helpers/fenced_code.js +20 -0
- package/dist/template/helpers/format-conversation.d.ts +30 -0
- package/dist/template/helpers/format-conversation.js +53 -0
- package/dist/template/helpers/include.d.ts +16 -0
- package/dist/template/helpers/include.js +23 -0
- package/dist/template/helpers/p1p2.d.ts +37 -0
- package/dist/template/helpers/p1p2.js +90 -0
- package/dist/template/loader/DocumentLoader.d.ts +48 -0
- package/dist/template/loader/DocumentLoader.js +128 -0
- package/dist/template/types.d.ts +51 -0
- package/dist/template/types.js +6 -0
- package/dist/testing/index.d.ts +12 -0
- package/dist/testing/index.js +16 -0
- package/dist/testing/mock-audit.d.ts +10 -0
- package/dist/testing/mock-audit.js +13 -0
- package/dist/testing/mock-context.d.ts +27 -0
- package/dist/testing/mock-context.js +68 -0
- package/dist/testing/mock-logger.d.ts +15 -0
- package/dist/testing/mock-logger.js +27 -0
- package/dist/testing/mock-router.d.ts +16 -0
- package/dist/testing/mock-router.js +67 -0
- package/dist/testing/mock-storage.d.ts +9 -0
- package/dist/testing/mock-storage.js +21 -0
- package/dist/testing/mock-store.d.ts +3 -0
- package/dist/testing/mock-store.js +8 -0
- package/dist/tools/delegate.d.ts +10 -0
- package/dist/tools/delegate.js +60 -0
- package/dist/tools/index.d.ts +5 -12
- package/dist/tools/index.js +6 -37
- package/dist/tools/node/builtin.d.ts +23 -0
- package/dist/tools/node/builtin.js +547 -0
- package/dist/tools/node/index.d.ts +23 -0
- package/dist/tools/node/index.js +59 -0
- package/dist/types/index.d.ts +804 -6
- package/dist/types/index.js +29 -20
- package/dist/types/task-log.types.d.ts +4 -0
- package/dist/types/task-log.types.js +3 -0
- package/dist/utils/env-defaults.d.ts +18 -0
- package/dist/utils/env-defaults.js +27 -0
- package/dist/utils/glob-match.d.ts +18 -0
- package/dist/utils/glob-match.js +42 -0
- package/dist/{core → utils}/id.d.ts +15 -0
- package/dist/utils/id.js +50 -0
- package/dist/utils/timestamp.d.ts +2 -0
- package/dist/utils/timestamp.js +13 -0
- package/dist/{core → utils}/workspace.d.ts +4 -0
- package/dist/{core → utils}/workspace.js +3 -0
- package/package.json +67 -102
- package/src/schemas/hooks.schema.json +59 -0
- package/templates/agents/default.yaml +490 -0
- package/templates/agents/minimal.yaml +16 -0
- package/LICENSE +0 -201
- package/dist/adapters/MastraToolAdapter.d.ts +0 -9
- package/dist/adapters/MastraToolAdapter.js +0 -66
- package/dist/adapters/MastraToolAdapter.js.map +0 -1
- package/dist/api/index.d.ts +0 -2
- package/dist/api/index.js +0 -8
- package/dist/api/index.js.map +0 -1
- package/dist/boxing/box-storage.interface.js.map +0 -1
- package/dist/boxing/box.service.js.map +0 -1
- package/dist/boxing/box.types.js.map +0 -1
- package/dist/boxing/context-builder.js.map +0 -1
- package/dist/boxing/index.d.ts +0 -6
- package/dist/boxing/index.js +0 -11
- package/dist/boxing/index.js.map +0 -1
- package/dist/boxing/tokenizer.d.ts +0 -3
- package/dist/boxing/tokenizer.js +0 -11
- package/dist/boxing/tokenizer.js.map +0 -1
- package/dist/config/api-provider-parser.d.ts +0 -58
- package/dist/config/api-provider-parser.js +0 -212
- package/dist/config/api-provider-parser.js.map +0 -1
- package/dist/config/index.d.ts +0 -3
- package/dist/config/index.js +0 -20
- package/dist/config/index.js.map +0 -1
- package/dist/config/log.config.d.ts +0 -7
- package/dist/config/log.config.js +0 -20
- package/dist/config/log.config.js.map +0 -1
- package/dist/config/pricing.d.ts +0 -11
- package/dist/config/pricing.js +0 -53
- package/dist/config/pricing.js.map +0 -1
- package/dist/config/timeout.config.d.ts +0 -14
- package/dist/config/timeout.config.js +0 -34
- package/dist/config/timeout.config.js.map +0 -1
- package/dist/config/yaml-loader.d.ts +0 -8
- package/dist/config/yaml-loader.js +0 -155
- package/dist/config/yaml-loader.js.map +0 -1
- package/dist/constants/index.d.ts +0 -4
- package/dist/constants/index.js +0 -8
- package/dist/constants/index.js.map +0 -1
- package/dist/constants.d.ts +0 -1
- package/dist/constants.js +0 -18
- package/dist/constants.js.map +0 -1
- package/dist/conversation/conversation-config.d.ts +0 -9
- package/dist/conversation/conversation-config.js +0 -22
- package/dist/conversation/conversation-config.js.map +0 -1
- package/dist/conversation/conversation-history.interface.d.ts +0 -36
- package/dist/conversation/conversation-history.interface.js +0 -3
- package/dist/conversation/conversation-history.interface.js.map +0 -1
- package/dist/conversation/conversation-storage.service.d.ts +0 -16
- package/dist/conversation/conversation-storage.service.js +0 -213
- package/dist/conversation/conversation-storage.service.js.map +0 -1
- package/dist/conversation/index.js.map +0 -1
- package/dist/core/__tests__/id.test.d.ts +0 -1
- package/dist/core/__tests__/id.test.js +0 -115
- package/dist/core/__tests__/id.test.js.map +0 -1
- package/dist/core/agent/agent-factory.d.ts +0 -37
- package/dist/core/agent/agent-factory.js +0 -68
- package/dist/core/agent/agent-factory.js.map +0 -1
- package/dist/core/agent/agent-runtime.d.ts +0 -52
- package/dist/core/agent/agent-runtime.js +0 -206
- package/dist/core/agent/agent-runtime.js.map +0 -1
- package/dist/core/agent/event-bus.d.ts +0 -44
- package/dist/core/agent/event-bus.js +0 -43
- package/dist/core/agent/event-bus.js.map +0 -1
- package/dist/core/agent/index.d.ts +0 -3
- package/dist/core/agent/index.js +0 -13
- package/dist/core/agent/index.js.map +0 -1
- package/dist/core/env-defaults.d.ts +0 -1
- package/dist/core/env-defaults.js +0 -7
- package/dist/core/env-defaults.js.map +0 -1
- package/dist/core/id.js +0 -27
- package/dist/core/id.js.map +0 -1
- package/dist/core/parallel/helpers.js.map +0 -1
- package/dist/core/parallel/index.d.ts +0 -4
- package/dist/core/parallel/index.js.map +0 -1
- package/dist/core/parallel/parallel-runner.js.map +0 -1
- package/dist/core/parallel/types.d.ts +0 -41
- package/dist/core/parallel/types.js +0 -3
- package/dist/core/parallel/types.js.map +0 -1
- package/dist/core/providers/MastraAPIProvider.d.ts +0 -31
- package/dist/core/providers/MastraAPIProvider.js +0 -365
- package/dist/core/providers/MastraAPIProvider.js.map +0 -1
- package/dist/core/providers/ai-provider.interface.d.ts +0 -79
- package/dist/core/providers/ai-provider.interface.js +0 -23
- package/dist/core/providers/ai-provider.interface.js.map +0 -1
- package/dist/core/providers/base-ai.provider.d.ts +0 -84
- package/dist/core/providers/base-ai.provider.js +0 -1237
- package/dist/core/providers/base-ai.provider.js.map +0 -1
- package/dist/core/providers/base-ai.types.d.ts +0 -26
- package/dist/core/providers/base-ai.types.js +0 -3
- package/dist/core/providers/base-ai.types.js.map +0 -1
- package/dist/core/providers/claude.provider.d.ts +0 -19
- package/dist/core/providers/claude.provider.js +0 -170
- package/dist/core/providers/claude.provider.js.map +0 -1
- package/dist/core/providers/codex.provider.d.ts +0 -21
- package/dist/core/providers/codex.provider.js +0 -134
- package/dist/core/providers/codex.provider.js.map +0 -1
- package/dist/core/providers/copilot.provider.d.ts +0 -25
- package/dist/core/providers/copilot.provider.js +0 -146
- package/dist/core/providers/copilot.provider.js.map +0 -1
- package/dist/core/providers/dynamic-provider.factory.d.ts +0 -74
- package/dist/core/providers/dynamic-provider.factory.js +0 -645
- package/dist/core/providers/dynamic-provider.factory.js.map +0 -1
- package/dist/core/providers/gemini.provider.d.ts +0 -16
- package/dist/core/providers/gemini.provider.js +0 -101
- package/dist/core/providers/gemini.provider.js.map +0 -1
- package/dist/core/providers/index.d.ts +0 -8
- package/dist/core/providers/index.js +0 -20
- package/dist/core/providers/index.js.map +0 -1
- package/dist/core/providers/mock.provider.d.ts +0 -13
- package/dist/core/providers/mock.provider.js +0 -55
- package/dist/core/providers/mock.provider.js.map +0 -1
- package/dist/core/providers/provider-factory.d.ts +0 -3
- package/dist/core/providers/provider-factory.js +0 -65
- package/dist/core/providers/provider-factory.js.map +0 -1
- package/dist/core/providers/tool-call.types.d.ts +0 -39
- package/dist/core/providers/tool-call.types.js +0 -3
- package/dist/core/providers/tool-call.types.js.map +0 -1
- package/dist/core/remote/index.d.ts +0 -3
- package/dist/core/remote/index.js.map +0 -1
- package/dist/core/remote/remote-agent-manager.d.ts +0 -24
- package/dist/core/remote/remote-agent-manager.js.map +0 -1
- package/dist/core/remote/remote-transport.d.ts +0 -15
- package/dist/core/remote/remote-transport.js +0 -70
- package/dist/core/remote/remote-transport.js.map +0 -1
- package/dist/core/remote/types.d.ts +0 -79
- package/dist/core/remote/types.js.map +0 -1
- package/dist/core/workspace.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/internal/index.d.ts +0 -1
- package/dist/internal/index.js +0 -6
- package/dist/internal/index.js.map +0 -1
- package/dist/knowledge/DocumentManager.d.ts +0 -4
- package/dist/knowledge/DocumentManager.js +0 -119
- package/dist/knowledge/DocumentManager.js.map +0 -1
- package/dist/knowledge/index.d.ts +0 -1
- package/dist/knowledge/index.js +0 -18
- package/dist/knowledge/index.js.map +0 -1
- package/dist/parsers/agent-call.util.js.map +0 -1
- package/dist/parsers/claude.parser.js.map +0 -1
- package/dist/parsers/codex.parser.js.map +0 -1
- package/dist/parsers/copilot.parser.js.map +0 -1
- package/dist/parsers/gemini.parser.js.map +0 -1
- package/dist/parsers/index.d.ts +0 -7
- package/dist/parsers/index.js +0 -45
- package/dist/parsers/index.js.map +0 -1
- package/dist/schema/skills-parser.d.ts +0 -8
- package/dist/schema/skills-parser.js +0 -438
- package/dist/schema/skills-parser.js.map +0 -1
- package/dist/schema/skills.types.d.ts +0 -158
- package/dist/schema/skills.types.js +0 -41
- package/dist/schema/skills.types.js.map +0 -1
- package/dist/schemas/api-provider.schema.d.ts +0 -432
- package/dist/schemas/api-provider.schema.js +0 -50
- package/dist/schemas/api-provider.schema.js.map +0 -1
- package/dist/services/index.d.ts +0 -2
- package/dist/services/index.js +0 -19
- package/dist/services/index.js.map +0 -1
- package/dist/services/layout-loader.service.js.map +0 -1
- package/dist/services/layout-renderer.service.js +0 -325
- package/dist/services/layout-renderer.service.js.map +0 -1
- package/dist/services/props-validator.service.js.map +0 -1
- package/dist/skills/adapter/claude-skill-adapter.d.ts +0 -11
- package/dist/skills/adapter/claude-skill-adapter.js +0 -222
- package/dist/skills/adapter/claude-skill-adapter.js.map +0 -1
- package/dist/skills/index.d.ts +0 -6
- package/dist/skills/index.js +0 -31
- package/dist/skills/index.js.map +0 -1
- package/dist/skills/runtime/progressive-loader.d.ts +0 -27
- package/dist/skills/runtime/progressive-loader.js +0 -186
- package/dist/skills/runtime/progressive-loader.js.map +0 -1
- package/dist/skills/runtime/runtime-requirements-validator.d.ts +0 -23
- package/dist/skills/runtime/runtime-requirements-validator.js +0 -248
- package/dist/skills/runtime/runtime-requirements-validator.js.map +0 -1
- package/dist/skills/runtime/skill-runtime.service.d.ts +0 -42
- package/dist/skills/runtime/skill-runtime.service.js +0 -434
- package/dist/skills/runtime/skill-runtime.service.js.map +0 -1
- package/dist/tools/file-system.service.d.ts +0 -10
- package/dist/tools/file-system.service.js +0 -33
- package/dist/tools/file-system.service.js.map +0 -1
- package/dist/tools/find.tool.d.ts +0 -21
- package/dist/tools/find.tool.js +0 -139
- package/dist/tools/find.tool.js.map +0 -1
- package/dist/tools/glob.tool.d.ts +0 -24
- package/dist/tools/glob.tool.js +0 -153
- package/dist/tools/glob.tool.js.map +0 -1
- package/dist/tools/grep.tool.d.ts +0 -1
- package/dist/tools/grep.tool.js +0 -137
- package/dist/tools/grep.tool.js.map +0 -1
- package/dist/tools/index.js.map +0 -1
- package/dist/tools/ls.tool.d.ts +0 -1
- package/dist/tools/ls.tool.js +0 -94
- package/dist/tools/ls.tool.js.map +0 -1
- package/dist/tools/read-file.tool.d.ts +0 -1
- package/dist/tools/read-file.tool.js +0 -69
- package/dist/tools/read-file.tool.js.map +0 -1
- package/dist/tools/replace.tool.d.ts +0 -1
- package/dist/tools/replace.tool.js +0 -68
- package/dist/tools/replace.tool.js.map +0 -1
- package/dist/tools/run-shell-command.tool.d.ts +0 -1
- package/dist/tools/run-shell-command.tool.js +0 -64
- package/dist/tools/run-shell-command.tool.js.map +0 -1
- package/dist/tools/tree.tool.d.ts +0 -1
- package/dist/tools/tree.tool.js +0 -109
- package/dist/tools/tree.tool.js.map +0 -1
- package/dist/tools/types.d.ts +0 -42
- package/dist/tools/types.js +0 -13
- package/dist/tools/types.js.map +0 -1
- package/dist/tools/utils/file-utils.d.ts +0 -5
- package/dist/tools/utils/file-utils.js +0 -221
- package/dist/tools/utils/file-utils.js.map +0 -1
- package/dist/tools/write-file.tool.d.ts +0 -1
- package/dist/tools/write-file.tool.js +0 -55
- package/dist/tools/write-file.tool.js.map +0 -1
- package/dist/types/agent.types.d.ts +0 -134
- package/dist/types/agent.types.js +0 -16
- package/dist/types/agent.types.js.map +0 -1
- package/dist/types/api-provider.types.d.ts +0 -85
- package/dist/types/api-provider.types.js +0 -65
- package/dist/types/api-provider.types.js.map +0 -1
- package/dist/types/index.js.map +0 -1
- package/dist/types/layout.types.js.map +0 -1
- package/dist/types/provider.types.d.ts +0 -12
- package/dist/types/provider.types.js +0 -3
- package/dist/types/provider.types.js.map +0 -1
- package/dist/types/skill-runtime.types.d.ts +0 -244
- package/dist/types/skill-runtime.types.js +0 -44
- package/dist/types/skill-runtime.types.js.map +0 -1
- package/dist/types/structured-payload.types.d.ts +0 -46
- package/dist/types/structured-payload.types.js +0 -65
- package/dist/types/structured-payload.types.js.map +0 -1
- package/dist/types/task-log.types.js.map +0 -1
- package/dist/types/template.types.d.ts +0 -38
- package/dist/types/template.types.js +0 -3
- package/dist/types/template.types.js.map +0 -1
- package/dist/types.d.ts +0 -1
- package/dist/types.js +0 -18
- package/dist/types.js.map +0 -1
- package/dist/utils/api-provider-normalizer.d.ts +0 -16
- package/dist/utils/api-provider-normalizer.js +0 -135
- package/dist/utils/api-provider-normalizer.js.map +0 -1
- package/dist/utils/base-message-formatter.d.ts +0 -32
- package/dist/utils/base-message-formatter.js +0 -170
- package/dist/utils/base-message-formatter.js.map +0 -1
- package/dist/utils/error-utils.d.ts +0 -3
- package/dist/utils/error-utils.js +0 -27
- package/dist/utils/error-utils.js.map +0 -1
- package/dist/utils/index.d.ts +0 -4
- package/dist/utils/index.js +0 -21
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/math-utils.d.ts +0 -3
- package/dist/utils/math-utils.js +0 -10
- package/dist/utils/math-utils.js.map +0 -1
- package/dist/utils/mention-parser.d.ts +0 -18
- package/dist/utils/mention-parser.js +0 -136
- package/dist/utils/mention-parser.js.map +0 -1
- package/dist/utils/string-utils.d.ts +0 -1
- package/dist/utils/string-utils.js +0 -10
- package/dist/utils/string-utils.js.map +0 -1
- package/dist/utils.d.ts +0 -3
- package/dist/utils.js +0 -20
- package/dist/utils.js.map +0 -1
- package/schema/api-provider-config.json +0 -138
- package/schema/crewx-config.json +0 -224
- package/schema/skills-config.json +0 -306
|
@@ -0,0 +1,1299 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Crewx facade — main entry point for the CrewX SDK.
|
|
4
|
+
* Provides loadYaml(), fromConfig(), query(), execute(), renderAgentPromptFull(),
|
|
5
|
+
* and registerLayout() methods.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.Crewx = void 0;
|
|
42
|
+
const path_1 = require("path");
|
|
43
|
+
const glob_match_1 = require("../utils/glob-match");
|
|
44
|
+
const loader_1 = require("../config/loader");
|
|
45
|
+
const resolver_1 = require("../agent/resolver");
|
|
46
|
+
const bridge_1 = require("../provider/bridge");
|
|
47
|
+
const engine_1 = require("../template/engine");
|
|
48
|
+
const DocumentLoader_1 = require("../template/loader/DocumentLoader");
|
|
49
|
+
const loader_2 = require("../layout/loader");
|
|
50
|
+
const renderer_1 = require("../layout/renderer");
|
|
51
|
+
const id_1 = require("../utils/id");
|
|
52
|
+
const timestamp_1 = require("../utils/timestamp");
|
|
53
|
+
const TypedEventEmitter_1 = require("../events/TypedEventEmitter");
|
|
54
|
+
const scoped_store_1 = require("../adapter/scoped-store");
|
|
55
|
+
const context_builder_1 = require("../adapter/context-builder");
|
|
56
|
+
const router_1 = require("../parsers/router");
|
|
57
|
+
const to_template_messages_1 = require("../conversation/to-template-messages");
|
|
58
|
+
const handler_1 = require("../server/handler");
|
|
59
|
+
const conversation_1 = require("../plugins/conversation");
|
|
60
|
+
const workspace_1 = require("../utils/workspace");
|
|
61
|
+
/**
|
|
62
|
+
* Extract exec policy from config.settings.template.exec if present.
|
|
63
|
+
*/
|
|
64
|
+
function extractExecPolicyFromConfig(config) {
|
|
65
|
+
if (!config)
|
|
66
|
+
return undefined;
|
|
67
|
+
const settings = config.settings;
|
|
68
|
+
const templateSettings = settings?.['template'];
|
|
69
|
+
const exec = templateSettings?.['exec'];
|
|
70
|
+
return exec;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Generate a random security key (16-char hex, same as global crewx).
|
|
74
|
+
* Uses crypto.getRandomValues (browser-safe) with Node crypto.randomBytes fallback.
|
|
75
|
+
*/
|
|
76
|
+
function generateSecurityKey() {
|
|
77
|
+
try {
|
|
78
|
+
// Works in both browser (globalThis.crypto) and Node 19+ (globalThis.crypto)
|
|
79
|
+
const bytes = new Uint8Array(8);
|
|
80
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
81
|
+
return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Fallback: Node.js crypto module
|
|
85
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
86
|
+
const { randomBytes } = require('crypto');
|
|
87
|
+
return randomBytes(8).toString('hex');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Build the default SDK templates path.
|
|
92
|
+
*/
|
|
93
|
+
const SDK_TEMPLATES_PATH = (0, path_1.join)(__dirname, '../../templates/agents');
|
|
94
|
+
class Crewx extends TypedEventEmitter_1.TypedEventEmitter {
|
|
95
|
+
_agents;
|
|
96
|
+
_templateEngine;
|
|
97
|
+
_documentLoader;
|
|
98
|
+
_layoutLoader;
|
|
99
|
+
_layoutRenderer;
|
|
100
|
+
_config;
|
|
101
|
+
_projectRoot;
|
|
102
|
+
_workspaceId;
|
|
103
|
+
_workspaceName;
|
|
104
|
+
_plugins = [];
|
|
105
|
+
_tools = new Map();
|
|
106
|
+
_activeAdapters = new Map();
|
|
107
|
+
_pendingThreads = new Map();
|
|
108
|
+
/**
|
|
109
|
+
* Bootstrap factory for target Crewx instances when delegating file:// remote agents.
|
|
110
|
+
* Consumers (CLI / server / Slack) provide their own bootstrap wrapper so that the
|
|
111
|
+
* target inherits the same plugin/environment setup as the caller.
|
|
112
|
+
*/
|
|
113
|
+
_remoteFactory;
|
|
114
|
+
/** Lazily-created target Crewx instances, keyed by absolute configPath. */
|
|
115
|
+
_remoteTargets = new Map();
|
|
116
|
+
constructor(agents, options = {}, config, documentLoader, projectRoot) {
|
|
117
|
+
super();
|
|
118
|
+
this._agents = new Map(agents.map(a => [a.id, a]));
|
|
119
|
+
this._config = config;
|
|
120
|
+
this._projectRoot = projectRoot ?? (typeof process !== 'undefined' ? process.cwd() : '/');
|
|
121
|
+
// Workspace single source of truth (WI-CONV-003, WI-20260418-002):
|
|
122
|
+
// projectRoot takes priority so that a target crewx instance gets its own workspace ID
|
|
123
|
+
// rather than inheriting the caller's cwd.
|
|
124
|
+
const workspacePath = projectRoot ?? (typeof process !== 'undefined'
|
|
125
|
+
? (process.env.CREWX_WORKSPACE ?? process.cwd())
|
|
126
|
+
: '/');
|
|
127
|
+
this._workspaceId = (0, workspace_1.hashWorkspaceId)(workspacePath);
|
|
128
|
+
this._workspaceName = (0, path_1.basename)(workspacePath);
|
|
129
|
+
const settingsPolicy = extractExecPolicyFromConfig(config);
|
|
130
|
+
this._templateEngine = new engine_1.TemplateEngine({
|
|
131
|
+
execPolicy: options.execPolicy ?? settingsPolicy,
|
|
132
|
+
});
|
|
133
|
+
this._documentLoader = documentLoader ?? new DocumentLoader_1.DocumentLoader();
|
|
134
|
+
this._layoutLoader = new loader_2.LayoutLoader({ templatesPath: SDK_TEMPLATES_PATH });
|
|
135
|
+
this._layoutRenderer = new renderer_1.LayoutRenderer();
|
|
136
|
+
this._remoteFactory = options.remoteFactory;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* If `agentRef` resolves to a `remote/*` provider backed by `file://`, return
|
|
140
|
+
* the target Crewx (lazily bootstrapped) together with the agent ref to use
|
|
141
|
+
* inside the target. Returns null for local agents or non-file remotes.
|
|
142
|
+
*
|
|
143
|
+
* The caller's Crewx.query/execute delegates entirely to the returned target
|
|
144
|
+
* (including task:start/end emit, renderContext, plugins) so execution
|
|
145
|
+
* semantics exactly match running `crewx q` inside the target workspace.
|
|
146
|
+
*/
|
|
147
|
+
async resolveFileRemoteTarget(agentRef) {
|
|
148
|
+
const agent = this.getAgent(agentRef);
|
|
149
|
+
const providerStr = Array.isArray(agent?.provider) ? agent?.provider[0] : agent?.provider;
|
|
150
|
+
if (!providerStr?.startsWith('remote/'))
|
|
151
|
+
return null;
|
|
152
|
+
const remoteId = providerStr.slice('remote/'.length);
|
|
153
|
+
const remoteConfig = this.getRemoteProviderConfig(remoteId);
|
|
154
|
+
if (!remoteConfig?.location?.startsWith('file://'))
|
|
155
|
+
return null;
|
|
156
|
+
const targetConfigPath = (0, path_1.resolve)(remoteConfig.location.replace('file://', ''));
|
|
157
|
+
const targetAgentId = remoteConfig.external_agent_id ?? agentRef.replace(/^@/, '');
|
|
158
|
+
let targetPromise = this._remoteTargets.get(targetConfigPath);
|
|
159
|
+
if (!targetPromise) {
|
|
160
|
+
const factory = this._remoteFactory ?? ((p) => Crewx.loadYaml(p));
|
|
161
|
+
targetPromise = factory(targetConfigPath);
|
|
162
|
+
this._remoteTargets.set(targetConfigPath, targetPromise);
|
|
163
|
+
// On failure, drop the cached Promise so the next call can retry.
|
|
164
|
+
targetPromise.catch(() => this._remoteTargets.delete(targetConfigPath));
|
|
165
|
+
}
|
|
166
|
+
const target = await targetPromise;
|
|
167
|
+
// Guard: target agent must not itself be a remote/ provider (chained remotes).
|
|
168
|
+
const targetAgent = target.getAgent('@' + targetAgentId);
|
|
169
|
+
const targetProviderStr = Array.isArray(targetAgent?.provider)
|
|
170
|
+
? targetAgent?.provider[0]
|
|
171
|
+
: targetAgent?.provider;
|
|
172
|
+
if (targetProviderStr?.startsWith('remote/')) {
|
|
173
|
+
throw new Error(`Chained remotes not allowed: "${remoteId}" → "${targetProviderStr}"`);
|
|
174
|
+
}
|
|
175
|
+
return { target, agentRef: '@' + targetAgentId };
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Load crewx.yaml from the given file path and create a Crewx instance.
|
|
179
|
+
*/
|
|
180
|
+
static async loadYaml(path, options, fsAdapter) {
|
|
181
|
+
const config = (0, loader_1.loadYamlFile)(path);
|
|
182
|
+
const projectRoot = (0, path_1.dirname)(path);
|
|
183
|
+
const loader = new DocumentLoader_1.DocumentLoader(fsAdapter);
|
|
184
|
+
await loader.load(config.documents, projectRoot);
|
|
185
|
+
// Auto-register api/* provider factory if any agent uses api/ namespace
|
|
186
|
+
const agents = config.agents ?? [];
|
|
187
|
+
const hasApiProvider = agents.some((a) => {
|
|
188
|
+
const providers = Array.isArray(a.provider) ? a.provider : [a.provider];
|
|
189
|
+
return providers.some(p => p.startsWith('api/'));
|
|
190
|
+
});
|
|
191
|
+
if (hasApiProvider) {
|
|
192
|
+
const { registerApiProviders } = await Promise.resolve().then(() => __importStar(require('../provider/register-api.js')));
|
|
193
|
+
registerApiProviders(options?.api);
|
|
194
|
+
}
|
|
195
|
+
// Auto-register remote/* provider factory if any agent uses remote/ namespace
|
|
196
|
+
registerRemoteProvidersIfNeeded(agents, config);
|
|
197
|
+
// Auto-register plugin/* provider factory if any agent uses plugin/ namespace
|
|
198
|
+
registerPluginProvidersIfNeeded(agents, config);
|
|
199
|
+
const instance = new Crewx(agents, options ?? {}, config, loader, projectRoot);
|
|
200
|
+
await instance.use(new conversation_1.ConversationPlugin());
|
|
201
|
+
return instance;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Create a Crewx instance from an already-parsed config object.
|
|
205
|
+
*/
|
|
206
|
+
static async fromConfig(config, options, projectRoot, fsAdapter) {
|
|
207
|
+
const loader = new DocumentLoader_1.DocumentLoader(fsAdapter);
|
|
208
|
+
await loader.load(config.documents, projectRoot ?? (typeof process !== 'undefined' ? process.cwd() : '/'));
|
|
209
|
+
// Auto-register remote/* provider factory
|
|
210
|
+
registerRemoteProvidersIfNeeded(config.agents ?? [], config);
|
|
211
|
+
// Auto-register plugin/* provider factory
|
|
212
|
+
registerPluginProvidersIfNeeded(config.agents ?? [], config);
|
|
213
|
+
const instance = new Crewx(config.agents ?? [], options ?? {}, config, loader, projectRoot);
|
|
214
|
+
await instance.use(new conversation_1.ConversationPlugin());
|
|
215
|
+
return instance;
|
|
216
|
+
}
|
|
217
|
+
/** All loaded agents, keyed by agent id. */
|
|
218
|
+
get agents() {
|
|
219
|
+
return this._agents;
|
|
220
|
+
}
|
|
221
|
+
/** The raw project config (includes providers, settings, etc.). */
|
|
222
|
+
get config() {
|
|
223
|
+
return this._config;
|
|
224
|
+
}
|
|
225
|
+
/** All registered plugins. */
|
|
226
|
+
get plugins() {
|
|
227
|
+
return this._plugins;
|
|
228
|
+
}
|
|
229
|
+
/** All registered custom tools. */
|
|
230
|
+
get tools() {
|
|
231
|
+
return this._tools;
|
|
232
|
+
}
|
|
233
|
+
/** Workspace ID (SHA-256 hash). Single source of truth for all plugins. */
|
|
234
|
+
get workspaceId() {
|
|
235
|
+
return this._workspaceId;
|
|
236
|
+
}
|
|
237
|
+
/** Human-readable workspace name (basename of cwd). */
|
|
238
|
+
get workspaceName() {
|
|
239
|
+
return this._workspaceName;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Return an agent config by ref (with or without leading '@').
|
|
243
|
+
* Returns undefined if the agent is not found.
|
|
244
|
+
*/
|
|
245
|
+
getAgent(agentRef) {
|
|
246
|
+
const id = agentRef.startsWith('@') ? agentRef.slice(1) : agentRef;
|
|
247
|
+
return this._agents.get(id);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Return a remote provider config by provider ID from the crewx.yaml `providers:` section.
|
|
251
|
+
* Returns undefined if not found or if config has no providers.
|
|
252
|
+
*/
|
|
253
|
+
getRemoteProviderConfig(providerId) {
|
|
254
|
+
const providersRaw = this._config?.['providers'];
|
|
255
|
+
if (!Array.isArray(providersRaw))
|
|
256
|
+
return undefined;
|
|
257
|
+
const entry = providersRaw.find(e => e['type'] === 'remote' && e['id'] === providerId);
|
|
258
|
+
return entry;
|
|
259
|
+
}
|
|
260
|
+
computeTaskLogPath(traceId, timestamp) {
|
|
261
|
+
const ts = (0, timestamp_1.formatTimestamp)(timestamp);
|
|
262
|
+
return (0, path_1.join)(this._projectRoot, '.crewx', 'logs', `${ts}_${traceId}.log`);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Register a custom tool for use in agent prompts.
|
|
266
|
+
*
|
|
267
|
+
* Registered tools are included in the `tools` context of renderAgentPromptFull(),
|
|
268
|
+
* and can be invoked programmatically (e.g. in browser environments with API providers).
|
|
269
|
+
*
|
|
270
|
+
* @param name - Unique tool name (overwrites if already registered)
|
|
271
|
+
* @param definition - Tool definition with description, parameters, and execute function
|
|
272
|
+
*/
|
|
273
|
+
registerTool(name, definition) {
|
|
274
|
+
this._tools.set(name, { name, ...definition });
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Register a plugin and immediately call attach().
|
|
278
|
+
* Same instance registered twice is silently ignored (by reference).
|
|
279
|
+
*/
|
|
280
|
+
async use(plugin) {
|
|
281
|
+
if (this._plugins.includes(plugin))
|
|
282
|
+
return;
|
|
283
|
+
await plugin.attach(this);
|
|
284
|
+
this._plugins.push(plugin);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Create a Web Standard MCP HTTP handler for exposing agents over the network.
|
|
288
|
+
*
|
|
289
|
+
* @param options - Handler config. `agents` list is required for security.
|
|
290
|
+
* @returns `(req: Request) => Promise<Response>` handler
|
|
291
|
+
*/
|
|
292
|
+
handler(options) {
|
|
293
|
+
return (0, handler_1.createHandler)(this, options);
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Register a channel adapter and start it.
|
|
297
|
+
*/
|
|
298
|
+
async registerChannelAdapter(reg) {
|
|
299
|
+
const { adapter, instanceId, config } = reg;
|
|
300
|
+
if (this._activeAdapters.has(instanceId)) {
|
|
301
|
+
throw new Error(`Adapter instance already registered: ${instanceId}`);
|
|
302
|
+
}
|
|
303
|
+
const capabilities = new Set(adapter.manifest.capabilities);
|
|
304
|
+
const store = reg.store ?? (0, scoped_store_1.createScopedAdapterStore)(instanceId);
|
|
305
|
+
const defaultMode = reg.defaultMode ?? 'query';
|
|
306
|
+
const adapterPlatform = adapter.manifest.platform;
|
|
307
|
+
const agentRunner = reg.agentRunner ?? {
|
|
308
|
+
run: async (agentId, message, opts) => {
|
|
309
|
+
const fn = defaultMode === 'execute' ? this.execute.bind(this) : this.query.bind(this);
|
|
310
|
+
const result = await fn(`@${agentId}`, message, { threadId: opts?.threadId, platform: adapterPlatform });
|
|
311
|
+
return { output: result.ok ? result.data : (result.error?.message ?? '') };
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
const onInbound = reg.onInbound ?? (async (msg) => {
|
|
315
|
+
const agentId = msg.routingHints?.agentId ?? reg.defaultAgent;
|
|
316
|
+
if (!agentId) {
|
|
317
|
+
return { accepted: false, reason: 'no_agent' };
|
|
318
|
+
}
|
|
319
|
+
const { output } = await agentRunner.run(agentId, msg.text, { threadId: msg.threadId });
|
|
320
|
+
return { accepted: true, output };
|
|
321
|
+
});
|
|
322
|
+
const ctx = (0, context_builder_1.createAdapterContext)({
|
|
323
|
+
instanceId,
|
|
324
|
+
config,
|
|
325
|
+
capabilities,
|
|
326
|
+
db: store,
|
|
327
|
+
agentRunner,
|
|
328
|
+
onInbound,
|
|
329
|
+
});
|
|
330
|
+
const entry = { adapter: adapter, ctx: ctx, state: 'starting' };
|
|
331
|
+
this._activeAdapters.set(instanceId, entry);
|
|
332
|
+
this.emit('adapter:lifecycle', {
|
|
333
|
+
adapterId: adapter.manifest.id,
|
|
334
|
+
instanceId,
|
|
335
|
+
state: 'starting',
|
|
336
|
+
timestamp: new Date(),
|
|
337
|
+
});
|
|
338
|
+
try {
|
|
339
|
+
await adapter.start(ctx);
|
|
340
|
+
entry.state = 'started';
|
|
341
|
+
this.emit('adapter:lifecycle', {
|
|
342
|
+
adapterId: adapter.manifest.id,
|
|
343
|
+
instanceId,
|
|
344
|
+
state: 'started',
|
|
345
|
+
timestamp: new Date(),
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
catch (err) {
|
|
349
|
+
entry.state = 'failed';
|
|
350
|
+
this.emit('adapter:lifecycle', {
|
|
351
|
+
adapterId: adapter.manifest.id,
|
|
352
|
+
instanceId,
|
|
353
|
+
state: 'failed',
|
|
354
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
355
|
+
timestamp: new Date(),
|
|
356
|
+
});
|
|
357
|
+
this._activeAdapters.delete(instanceId);
|
|
358
|
+
throw err;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Unregister and stop a channel adapter by instanceId.
|
|
363
|
+
*/
|
|
364
|
+
async unregisterChannelAdapter(instanceId) {
|
|
365
|
+
const entry = this._activeAdapters.get(instanceId);
|
|
366
|
+
if (!entry)
|
|
367
|
+
return;
|
|
368
|
+
entry.state = 'stopping';
|
|
369
|
+
this.emit('adapter:lifecycle', {
|
|
370
|
+
adapterId: entry.adapter.manifest.id,
|
|
371
|
+
instanceId,
|
|
372
|
+
state: 'stopping',
|
|
373
|
+
timestamp: new Date(),
|
|
374
|
+
});
|
|
375
|
+
try {
|
|
376
|
+
await entry.adapter.stop(entry.ctx);
|
|
377
|
+
entry.state = 'stopped';
|
|
378
|
+
this.emit('adapter:lifecycle', {
|
|
379
|
+
adapterId: entry.adapter.manifest.id,
|
|
380
|
+
instanceId,
|
|
381
|
+
state: 'stopped',
|
|
382
|
+
timestamp: new Date(),
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
catch (err) {
|
|
386
|
+
entry.state = 'failed';
|
|
387
|
+
this.emit('adapter:lifecycle', {
|
|
388
|
+
adapterId: entry.adapter.manifest.id,
|
|
389
|
+
instanceId,
|
|
390
|
+
state: 'failed',
|
|
391
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
392
|
+
timestamp: new Date(),
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
finally {
|
|
396
|
+
this._activeAdapters.delete(instanceId);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Stop all registered adapters with a timeout.
|
|
401
|
+
*/
|
|
402
|
+
async stopAllAdapters(opts = {}) {
|
|
403
|
+
const timeoutMs = opts.timeoutMs ?? 10_000;
|
|
404
|
+
const instanceIds = Array.from(this._activeAdapters.keys());
|
|
405
|
+
const results = await Promise.allSettled(instanceIds.map(id => Promise.race([
|
|
406
|
+
this.unregisterChannelAdapter(id),
|
|
407
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`Adapter stop timeout: ${id}`)), timeoutMs)),
|
|
408
|
+
])));
|
|
409
|
+
for (let i = 0; i < results.length; i++) {
|
|
410
|
+
if (results[i].status === 'rejected') {
|
|
411
|
+
console.error(`[crewx] adapter stop error (${instanceIds[i]}): ${results[i].reason}`);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Detach all plugins in LIFO order and release resources.
|
|
417
|
+
* Call before process exit for clean shutdown.
|
|
418
|
+
*/
|
|
419
|
+
async close() {
|
|
420
|
+
await this.stopAllAdapters({ timeoutMs: 10_000 });
|
|
421
|
+
// Cascade close target Crewx instances bootstrapped for file:// remotes.
|
|
422
|
+
const remoteTargets = [...this._remoteTargets.values()];
|
|
423
|
+
this._remoteTargets.clear();
|
|
424
|
+
await Promise.allSettled(remoteTargets.map(async (p) => {
|
|
425
|
+
try {
|
|
426
|
+
await (await p).close();
|
|
427
|
+
}
|
|
428
|
+
catch (err) {
|
|
429
|
+
console.error(`[crewx] remote target close error: ${err instanceof Error ? err.message : String(err)}`);
|
|
430
|
+
}
|
|
431
|
+
}));
|
|
432
|
+
const reversed = [...this._plugins].reverse();
|
|
433
|
+
for (const plugin of reversed) {
|
|
434
|
+
try {
|
|
435
|
+
await plugin.detach(this);
|
|
436
|
+
}
|
|
437
|
+
catch (err) {
|
|
438
|
+
console.error(`[crewx] plugin ${plugin.name} detach error: ${err instanceof Error ? err.message : String(err)}`);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
this._plugins.length = 0;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Filter agents by role, team, and/or provider.
|
|
445
|
+
*/
|
|
446
|
+
filterAgents(filters) {
|
|
447
|
+
const parseFilter = (value) => value ? value.split(',').map(v => v.trim().toLowerCase()).filter(Boolean) : undefined;
|
|
448
|
+
const roleFilter = parseFilter(filters.role);
|
|
449
|
+
const teamFilter = parseFilter(filters.team);
|
|
450
|
+
const providerFilter = parseFilter(filters.provider);
|
|
451
|
+
let result = Array.from(this._agents.values());
|
|
452
|
+
if (roleFilter) {
|
|
453
|
+
result = result.filter(a => a.role && roleFilter.some(f => (0, glob_match_1.matchesPattern)(a.role.toLowerCase(), f)));
|
|
454
|
+
}
|
|
455
|
+
if (teamFilter) {
|
|
456
|
+
result = result.filter(a => a.team && teamFilter.some(f => (0, glob_match_1.matchesPattern)(a.team.toLowerCase(), f)));
|
|
457
|
+
}
|
|
458
|
+
if (providerFilter) {
|
|
459
|
+
result = result.filter(a => {
|
|
460
|
+
const providers = Array.isArray(a.provider) ? a.provider : [a.provider];
|
|
461
|
+
return providers.some(pv => providerFilter.some(f => (0, glob_match_1.matchesPattern)(pv.toLowerCase(), f)));
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
return result;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Return the raw system prompt for the given agent (no template expansion, no layout).
|
|
468
|
+
* @throws AgentNotFoundError if agentId is not found
|
|
469
|
+
*/
|
|
470
|
+
renderAgentPrompt(agentId) {
|
|
471
|
+
const id = agentId.startsWith('@') ? agentId.slice(1) : agentId;
|
|
472
|
+
const agent = this._agents.get(id);
|
|
473
|
+
if (!agent) {
|
|
474
|
+
throw new resolver_1.AgentNotFoundError(id, Array.from(this._agents.keys()));
|
|
475
|
+
}
|
|
476
|
+
return (agent.inline?.prompt ??
|
|
477
|
+
agent.inline?.system_prompt ??
|
|
478
|
+
agent.description ??
|
|
479
|
+
`You are an expert ${id}.`);
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Render a Handlebars template string with the given context.
|
|
483
|
+
* Documents from crewx.yaml are automatically merged into context.documents.
|
|
484
|
+
*/
|
|
485
|
+
async renderPrompt(template, context) {
|
|
486
|
+
const loaderDocs = await this._documentLoader.buildContext();
|
|
487
|
+
const mergedDocs = { ...loaderDocs, ...(context?.documents ?? {}) };
|
|
488
|
+
const mergedContext = { ...context, documents: mergedDocs };
|
|
489
|
+
return this._templateEngine.render(template, mergedContext);
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Register a custom layout template at runtime.
|
|
493
|
+
*
|
|
494
|
+
* @param name - Layout identifier (used as-is, no forced namespace)
|
|
495
|
+
* @param template - Handlebars template string or CustomLayoutDefinition
|
|
496
|
+
*/
|
|
497
|
+
registerLayout(name, template) {
|
|
498
|
+
this._layoutLoader.registerLayout(name, template);
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Render the full agent prompt using the layout system.
|
|
502
|
+
*
|
|
503
|
+
* Resolution priority (first match wins):
|
|
504
|
+
* 1. options.layout (call-site override)
|
|
505
|
+
* 2. agent.inline.layout (agent YAML definition)
|
|
506
|
+
* 3. config.layouts.default (project-level default)
|
|
507
|
+
* 4. SDK built-in default (crewx/default)
|
|
508
|
+
*
|
|
509
|
+
* @param agentId - Agent ID (with or without leading '@')
|
|
510
|
+
* @param options - Optional layout/session/env/vars overrides
|
|
511
|
+
* @throws AgentNotFoundError if agentId is not found
|
|
512
|
+
*/
|
|
513
|
+
async renderAgentPromptFull(agentId, options) {
|
|
514
|
+
const id = agentId.startsWith('@') ? agentId.slice(1) : agentId;
|
|
515
|
+
const agent = this._agents.get(id);
|
|
516
|
+
if (!agent) {
|
|
517
|
+
throw new resolver_1.AgentNotFoundError(id, Array.from(this._agents.keys()));
|
|
518
|
+
}
|
|
519
|
+
// ── Step 1: Resolve layout spec ─────────────────────────────────────────
|
|
520
|
+
const layoutSpec = this._resolveLayoutSpec(agent, options?.layout);
|
|
521
|
+
const layoutId = this._extractLayoutId(layoutSpec);
|
|
522
|
+
const layoutProps = this._extractLayoutProps(agent, layoutSpec, options?.layout);
|
|
523
|
+
// ── Step 2: Load layout definition ──────────────────────────────────────
|
|
524
|
+
const layout = this._layoutLoader.load(layoutId, layoutProps);
|
|
525
|
+
// ── Step 3: Pre-render agent.inline.prompt through TemplateEngine ────────
|
|
526
|
+
// (expands exec, documents, env vars inside the prompt template)
|
|
527
|
+
const rawPrompt = agent.inline?.prompt ??
|
|
528
|
+
agent.inline?.system_prompt ??
|
|
529
|
+
agent.description ??
|
|
530
|
+
`You are an expert ${id}.`;
|
|
531
|
+
const loaderDocs = await this._documentLoader.buildContext();
|
|
532
|
+
const env = options?.env ?? (typeof process !== 'undefined' ? process.env : {});
|
|
533
|
+
const security_key = options?.vars?.['security_key'] ?? generateSecurityKey();
|
|
534
|
+
const preRenderCtx = {
|
|
535
|
+
...(options?.vars ?? {}), // make vars available as top-level template variables
|
|
536
|
+
documents: loaderDocs,
|
|
537
|
+
env,
|
|
538
|
+
agent: {
|
|
539
|
+
id: agent.id,
|
|
540
|
+
name: agent.name ?? agent.id,
|
|
541
|
+
role: agent.role ?? '',
|
|
542
|
+
team: agent.team ?? '',
|
|
543
|
+
description: agent.description ?? '',
|
|
544
|
+
},
|
|
545
|
+
};
|
|
546
|
+
const renderedPrompt = await this._templateEngine.render(rawPrompt, preRenderCtx);
|
|
547
|
+
// ── Step 4: Build full RenderContext ─────────────────────────────────────
|
|
548
|
+
const session = {
|
|
549
|
+
mode: options?.session?.mode ?? 'query',
|
|
550
|
+
platform: options?.session?.platform ?? 'cli',
|
|
551
|
+
options: options?.session?.options ?? [],
|
|
552
|
+
};
|
|
553
|
+
const providerRaw = agent.provider;
|
|
554
|
+
const providerList = Array.isArray(providerRaw)
|
|
555
|
+
? providerRaw
|
|
556
|
+
: typeof providerRaw === 'string' && providerRaw.length > 0
|
|
557
|
+
? [providerRaw]
|
|
558
|
+
: [];
|
|
559
|
+
const providerDisplay = providerList.join(', ') || (typeof providerRaw === 'string' ? providerRaw : '');
|
|
560
|
+
const agentOptions = agent.options;
|
|
561
|
+
const optionsByMode = !Array.isArray(agentOptions) && typeof agentOptions === 'object' && agentOptions !== null
|
|
562
|
+
? agentOptions
|
|
563
|
+
: undefined;
|
|
564
|
+
const optionsArray = Array.isArray(agentOptions) ? agentOptions : undefined;
|
|
565
|
+
// Build document context for layout (with toc/path metadata)
|
|
566
|
+
const documents = {};
|
|
567
|
+
for (const [k, v] of Object.entries(loaderDocs)) {
|
|
568
|
+
documents[k] = {
|
|
569
|
+
content: v.content ?? '',
|
|
570
|
+
toc: v.toc,
|
|
571
|
+
summary: v.summary,
|
|
572
|
+
path: v.path,
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
// Extract user_input from vars for top-level access (default.yaml uses {{user_input}})
|
|
576
|
+
const userInputRaw = options?.vars?.['user_input'] ?? undefined;
|
|
577
|
+
const renderContext = {
|
|
578
|
+
user_input: userInputRaw,
|
|
579
|
+
agent: {
|
|
580
|
+
id: agent.id,
|
|
581
|
+
name: agent.name ?? agent.id,
|
|
582
|
+
role: agent.role ?? '',
|
|
583
|
+
team: agent.team ?? '',
|
|
584
|
+
description: agent.description ?? '',
|
|
585
|
+
provider: providerDisplay,
|
|
586
|
+
providerList,
|
|
587
|
+
model: agent.inline?.model,
|
|
588
|
+
workingDirectory: agent.working_directory ?? agent.workingDirectory ?? '.',
|
|
589
|
+
inline: {
|
|
590
|
+
...(agent.inline ?? {}),
|
|
591
|
+
prompt: renderedPrompt, // pre-rendered (exec expanded)
|
|
592
|
+
},
|
|
593
|
+
specialties: agent.specialties ?? [],
|
|
594
|
+
capabilities: agent.capabilities ?? [],
|
|
595
|
+
remote: agent.remote ?? null,
|
|
596
|
+
optionsByMode,
|
|
597
|
+
optionsArray,
|
|
598
|
+
},
|
|
599
|
+
agentMetadata: {
|
|
600
|
+
specialties: agent.specialties ?? [],
|
|
601
|
+
capabilities: agent.capabilities ?? [],
|
|
602
|
+
description: agent.description ?? '',
|
|
603
|
+
},
|
|
604
|
+
documents,
|
|
605
|
+
skills: options?.skills ?? [],
|
|
606
|
+
session,
|
|
607
|
+
env,
|
|
608
|
+
vars: {
|
|
609
|
+
security_key,
|
|
610
|
+
...(options?.vars ?? {}),
|
|
611
|
+
},
|
|
612
|
+
props: {
|
|
613
|
+
...(layoutProps ?? {}),
|
|
614
|
+
// TRAP 2: auto-gate showConversationHistory when messages are present
|
|
615
|
+
...(options?.messages && options.messages.length > 0
|
|
616
|
+
? { showConversationHistory: true }
|
|
617
|
+
: {}),
|
|
618
|
+
},
|
|
619
|
+
platform: session.platform,
|
|
620
|
+
mode: session.mode,
|
|
621
|
+
messages: options?.messages ?? [],
|
|
622
|
+
tools: this._tools.size > 0
|
|
623
|
+
? {
|
|
624
|
+
list: Array.from(this._tools.values()).map(t => ({
|
|
625
|
+
name: t.name,
|
|
626
|
+
description: t.description,
|
|
627
|
+
parameters: t.parameters,
|
|
628
|
+
})),
|
|
629
|
+
json: JSON.stringify(Array.from(this._tools.values()).map(t => ({
|
|
630
|
+
name: t.name,
|
|
631
|
+
description: t.description,
|
|
632
|
+
parameters: t.parameters,
|
|
633
|
+
})), null, 2),
|
|
634
|
+
count: this._tools.size,
|
|
635
|
+
}
|
|
636
|
+
: null,
|
|
637
|
+
metadata: {},
|
|
638
|
+
};
|
|
639
|
+
// ── Step 5: Render layout ────────────────────────────────────────────────
|
|
640
|
+
return this._layoutRenderer.render(layout, renderContext);
|
|
641
|
+
}
|
|
642
|
+
// ── Private helpers ─────────────────────────────────────────────────────────
|
|
643
|
+
/**
|
|
644
|
+
* Filter tools by allowed names from agent options (query/execute mode).
|
|
645
|
+
* If allowedNames is undefined, return all registered tools.
|
|
646
|
+
*/
|
|
647
|
+
_filterToolsByMode(allowedNames) {
|
|
648
|
+
if (!allowedNames) {
|
|
649
|
+
return Array.from(this._tools.values());
|
|
650
|
+
}
|
|
651
|
+
return allowedNames
|
|
652
|
+
.map(name => this._tools.get(name))
|
|
653
|
+
.filter((t) => t !== undefined);
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Resolve layout spec following the priority order.
|
|
657
|
+
*/
|
|
658
|
+
_resolveLayoutSpec(agent, callLayout) {
|
|
659
|
+
// Priority 1: call-site options
|
|
660
|
+
if (callLayout !== undefined)
|
|
661
|
+
return callLayout;
|
|
662
|
+
// Priority 2: agent.inline.layout
|
|
663
|
+
const inlineLayout = agent.inline?.layout;
|
|
664
|
+
if (inlineLayout !== undefined)
|
|
665
|
+
return inlineLayout;
|
|
666
|
+
// Priority 3: project config layouts.default
|
|
667
|
+
const projectDefault = this._config?.layouts?.['default'];
|
|
668
|
+
if (typeof projectDefault === 'string' && projectDefault)
|
|
669
|
+
return projectDefault;
|
|
670
|
+
// Priority 4: SDK built-in default
|
|
671
|
+
return 'crewx/default';
|
|
672
|
+
}
|
|
673
|
+
/** Extract the layout ID string from a LayoutSpec. */
|
|
674
|
+
_extractLayoutId(spec) {
|
|
675
|
+
if (typeof spec === 'string')
|
|
676
|
+
return spec;
|
|
677
|
+
if ('id' in spec)
|
|
678
|
+
return spec.id;
|
|
679
|
+
// Inline template — register it temporarily and return its ID
|
|
680
|
+
const tempId = `crewx/__inline_${Date.now()}`;
|
|
681
|
+
this._layoutLoader.registerLayout(tempId, spec.template);
|
|
682
|
+
return tempId;
|
|
683
|
+
}
|
|
684
|
+
/** Extract layout props overrides from agent inline.layout and call-site options. */
|
|
685
|
+
_extractLayoutProps(agent, _resolvedSpec, callLayout) {
|
|
686
|
+
// Props from agent.inline.layout
|
|
687
|
+
const inlineLayout = agent.inline?.layout;
|
|
688
|
+
const agentProps = inlineLayout && typeof inlineLayout === 'object' && 'props' in inlineLayout
|
|
689
|
+
? inlineLayout.props
|
|
690
|
+
: undefined;
|
|
691
|
+
// Props from call-site options
|
|
692
|
+
const callProps = callLayout && typeof callLayout === 'object' && 'id' in callLayout
|
|
693
|
+
? callLayout.props
|
|
694
|
+
: undefined;
|
|
695
|
+
// Merge: call-site overrides agent props
|
|
696
|
+
if (agentProps || callProps) {
|
|
697
|
+
return { ...(agentProps ?? {}), ...(callProps ?? {}) };
|
|
698
|
+
}
|
|
699
|
+
return undefined;
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Get the ConversationPlugin's provider for history auto-fetch (WI-CONV-002).
|
|
703
|
+
* Returns undefined if no ConversationPlugin is registered.
|
|
704
|
+
*/
|
|
705
|
+
_getConversationProvider() {
|
|
706
|
+
const plugin = this._plugins.find(p => p.name === 'conversation');
|
|
707
|
+
return plugin?.conversationProvider;
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Auto-fetch conversation history and convert to TemplateMessage[] (WI-CONV-002).
|
|
711
|
+
* Returns undefined if no threadId, no provider, or fetch fails.
|
|
712
|
+
*/
|
|
713
|
+
async _fetchHistoryMessages(threadId, traceId, callerMessages) {
|
|
714
|
+
// Caller-provided messages take priority
|
|
715
|
+
if (callerMessages && callerMessages.length > 0)
|
|
716
|
+
return callerMessages;
|
|
717
|
+
if (!threadId)
|
|
718
|
+
return undefined;
|
|
719
|
+
const provider = this._getConversationProvider();
|
|
720
|
+
if (!provider)
|
|
721
|
+
return undefined;
|
|
722
|
+
try {
|
|
723
|
+
const thread = await provider.fetchHistory(threadId, { currentTraceId: traceId });
|
|
724
|
+
if (thread.messages.length === 0)
|
|
725
|
+
return undefined;
|
|
726
|
+
return (0, to_template_messages_1.toTemplateMessages)(thread);
|
|
727
|
+
}
|
|
728
|
+
catch {
|
|
729
|
+
// Non-fatal: history fetch failure must not block the query/execute
|
|
730
|
+
return undefined;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
emitToolEvents(traceId, agentRef, provider, line, agentId, threadId, sessionId) {
|
|
734
|
+
try {
|
|
735
|
+
const entries = (0, router_1.parseStdoutEvent)(new Date().toISOString(), line);
|
|
736
|
+
for (const entry of entries) {
|
|
737
|
+
if (entry.type === 'tool_use' && entry.toolName) {
|
|
738
|
+
this.emit('tool:observed:before', {
|
|
739
|
+
traceId,
|
|
740
|
+
timestamp: new Date(),
|
|
741
|
+
agentRef,
|
|
742
|
+
agentId,
|
|
743
|
+
threadId,
|
|
744
|
+
sessionId,
|
|
745
|
+
provider,
|
|
746
|
+
tool: {
|
|
747
|
+
name: entry.toolName,
|
|
748
|
+
rawName: entry.toolName,
|
|
749
|
+
input: entry.toolInput ? this.tryParseJson(entry.toolInput) : undefined,
|
|
750
|
+
toolUseId: entry.toolUseId,
|
|
751
|
+
},
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
if (entry.type === 'tool_result') {
|
|
755
|
+
this.emit('tool:observed:after', {
|
|
756
|
+
traceId,
|
|
757
|
+
timestamp: new Date(),
|
|
758
|
+
agentRef,
|
|
759
|
+
agentId,
|
|
760
|
+
threadId,
|
|
761
|
+
sessionId,
|
|
762
|
+
provider,
|
|
763
|
+
tool: {
|
|
764
|
+
name: entry.toolName ?? 'unknown',
|
|
765
|
+
rawName: entry.toolName ?? 'unknown',
|
|
766
|
+
toolUseId: entry.toolUseId,
|
|
767
|
+
result: entry.resultPreview,
|
|
768
|
+
isError: entry.isError,
|
|
769
|
+
},
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
catch {
|
|
775
|
+
// non-fatal: parsing failure must not block the main process
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
tryParseJson(s) {
|
|
779
|
+
try {
|
|
780
|
+
return JSON.parse(s);
|
|
781
|
+
}
|
|
782
|
+
catch {
|
|
783
|
+
return s;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Query an agent with a message.
|
|
788
|
+
*
|
|
789
|
+
* Emits task:start (with child pid when available) then task:output per
|
|
790
|
+
* stdout/stderr line, then task:end on completion or error.
|
|
791
|
+
*/
|
|
792
|
+
async query(agentRef, message, options) {
|
|
793
|
+
// file:// remote agents: delegate entirely to the target Crewx so execution
|
|
794
|
+
// runs inside the target workspace (same as `crewx q` invoked in that dir).
|
|
795
|
+
const remoteTarget = await this.resolveFileRemoteTarget(agentRef);
|
|
796
|
+
if (remoteTarget) {
|
|
797
|
+
return remoteTarget.target.query(remoteTarget.agentRef, message, options);
|
|
798
|
+
}
|
|
799
|
+
const startMs = Date.now();
|
|
800
|
+
const traceId = (0, id_1.generateId)('tsk');
|
|
801
|
+
const timestamp = new Date();
|
|
802
|
+
let agent;
|
|
803
|
+
try {
|
|
804
|
+
agent = (0, resolver_1.resolveAgent)(agentRef, Array.from(this._agents.values()));
|
|
805
|
+
}
|
|
806
|
+
catch (err) {
|
|
807
|
+
if (err instanceof resolver_1.AgentNotFoundError) {
|
|
808
|
+
this.emit('task:start', { traceId, timestamp, agentRef, message: message, mode: 'query', metadata: { ...(options?.metadata ?? {}) }, threadId: options?.threadId, platform: options?.platform ?? 'cli', workspaceId: this._workspaceId, workspaceName: this._workspaceName });
|
|
809
|
+
const durationMs = Date.now() - startMs;
|
|
810
|
+
const error = { code: 'AGENT_NOT_FOUND', message: err.message };
|
|
811
|
+
this.emit('task:end', { traceId, timestamp: new Date(), agentRef, mode: 'query', durationMs, error, metadata: options?.metadata ? { ...options.metadata } : undefined });
|
|
812
|
+
return {
|
|
813
|
+
ok: false,
|
|
814
|
+
data: '',
|
|
815
|
+
error,
|
|
816
|
+
meta: { agentId: agentRef.replace(/^@/, ''), provider: '', durationMs },
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
throw err;
|
|
820
|
+
}
|
|
821
|
+
const providerStr = Array.isArray(agent.provider)
|
|
822
|
+
? agent.provider[0] ?? 'cli/claude'
|
|
823
|
+
: agent.provider;
|
|
824
|
+
const effectiveProviderStr = options?.provider ?? providerStr;
|
|
825
|
+
const effectiveModel = options?.model ?? agent.inline?.model;
|
|
826
|
+
let provider;
|
|
827
|
+
try {
|
|
828
|
+
provider = (0, bridge_1.createProvider)(effectiveProviderStr);
|
|
829
|
+
}
|
|
830
|
+
catch (err) {
|
|
831
|
+
this.emit('task:start', { traceId, timestamp, agentRef, message: message, mode: 'query', metadata: { ...(options?.metadata ?? {}) }, threadId: options?.threadId, platform: options?.platform ?? 'cli', workspaceId: this._workspaceId, workspaceName: this._workspaceName });
|
|
832
|
+
const durationMs = Date.now() - startMs;
|
|
833
|
+
const error = { code: 'PROVIDER_ERROR', message: err.message };
|
|
834
|
+
this.emit('task:end', { traceId, timestamp: new Date(), agentRef, mode: 'query', durationMs, error, metadata: options?.metadata ? { ...options.metadata } : undefined });
|
|
835
|
+
return {
|
|
836
|
+
ok: false,
|
|
837
|
+
data: '',
|
|
838
|
+
error,
|
|
839
|
+
meta: { agentId: agent.id, provider: effectiveProviderStr, model: effectiveModel, durationMs },
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
// WI-CONV-002: Auto-fetch conversation history for thread context injection
|
|
843
|
+
const historyMessages = await this._fetchHistoryMessages(options?.threadId, traceId, options?.messages);
|
|
844
|
+
// Render agent prompt with user_input for <user_query> wrapping (non-fatal if it fails)
|
|
845
|
+
// Intentionally includes user_input in renderedPrompt for tracing/logging purposes.
|
|
846
|
+
let renderedPrompt;
|
|
847
|
+
try {
|
|
848
|
+
renderedPrompt = await this.renderAgentPromptFull(agentRef, {
|
|
849
|
+
session: { mode: 'query', platform: options?.platform },
|
|
850
|
+
vars: { user_input: message },
|
|
851
|
+
messages: historyMessages,
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
catch {
|
|
855
|
+
// Prompt rendering is best-effort; do not block the query
|
|
856
|
+
}
|
|
857
|
+
let codingAgentCommand;
|
|
858
|
+
let providerUsage;
|
|
859
|
+
let exitCode;
|
|
860
|
+
let resolvedModel = effectiveModel;
|
|
861
|
+
let taskStartEmitted = false;
|
|
862
|
+
const emitStartIfNeeded = (pid) => {
|
|
863
|
+
if (!taskStartEmitted) {
|
|
864
|
+
taskStartEmitted = true;
|
|
865
|
+
this.emit('task:start', {
|
|
866
|
+
traceId, timestamp, agentRef, message: message, mode: 'query', pid,
|
|
867
|
+
model: resolvedModel,
|
|
868
|
+
provider: effectiveProviderStr,
|
|
869
|
+
codingAgentCommand,
|
|
870
|
+
renderedPrompt,
|
|
871
|
+
metadata: { ...(options?.metadata ?? {}), provider: effectiveProviderStr },
|
|
872
|
+
threadId: options?.threadId,
|
|
873
|
+
platform: options?.platform ?? 'cli',
|
|
874
|
+
workspaceId: this._workspaceId,
|
|
875
|
+
workspaceName: this._workspaceName,
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
};
|
|
879
|
+
const agentCliOpts = agent.options;
|
|
880
|
+
// Filter tools for query mode
|
|
881
|
+
const queryToolNames = Array.isArray(agentCliOpts?.query?.tools)
|
|
882
|
+
? agentCliOpts.query.tools
|
|
883
|
+
: undefined;
|
|
884
|
+
const filteredTools = this._tools.size > 0
|
|
885
|
+
? this._filterToolsByMode(queryToolNames)
|
|
886
|
+
: [];
|
|
887
|
+
// maxSteps from agent inline config
|
|
888
|
+
const maxSteps = agent.inline?.max_steps;
|
|
889
|
+
// api/* providers don't emit pid — emit task:start early so plugins (FileLogger) can log tool calls
|
|
890
|
+
if (effectiveProviderStr.startsWith('api/')) {
|
|
891
|
+
emitStartIfNeeded();
|
|
892
|
+
}
|
|
893
|
+
try {
|
|
894
|
+
const response = await provider.query(message, {
|
|
895
|
+
model: effectiveModel,
|
|
896
|
+
context: options?.context,
|
|
897
|
+
systemPrompt: renderedPrompt ?? agent.inline?.system_prompt ?? agent.inline?.prompt,
|
|
898
|
+
additionalArgs: Array.isArray(agentCliOpts?.query) ? agentCliOpts.query : undefined,
|
|
899
|
+
tools: filteredTools.length > 0 ? filteredTools : undefined,
|
|
900
|
+
maxSteps,
|
|
901
|
+
env: {
|
|
902
|
+
CREWX_AGENT_ID: agent.id,
|
|
903
|
+
CREWX_AGENT_ROLE: agent.role ?? '',
|
|
904
|
+
CREWX_AGENT_TEAM: agent.team ?? '',
|
|
905
|
+
CREWX_USER_ID: process.env.USER || process.env.USERNAME || 'unknown',
|
|
906
|
+
CREWX_TRACE_ID: traceId,
|
|
907
|
+
CREWX_PARENT_TASK_ID: traceId,
|
|
908
|
+
CREWX_TASK_ID: traceId,
|
|
909
|
+
CREWX_CALLER_AGENT_ID: process.env.CREWX_AGENT_ID ?? '',
|
|
910
|
+
CREWX_THREAD_ID: options?.threadId ?? '',
|
|
911
|
+
CREWX_PROVIDER: effectiveProviderStr,
|
|
912
|
+
CREWX_SESSION_ID: '',
|
|
913
|
+
CREWX_TASK_LOG_PATH: this.computeTaskLogPath(traceId, timestamp),
|
|
914
|
+
},
|
|
915
|
+
onPid: (pid) => emitStartIfNeeded(pid),
|
|
916
|
+
onOutput: (line, level) => {
|
|
917
|
+
this.emit('task:output', { traceId, timestamp: new Date(), agentRef, output: line, level });
|
|
918
|
+
if (level === 'stdout') {
|
|
919
|
+
this.emitToolEvents(traceId, agentRef, effectiveProviderStr, line, agent.id, options?.threadId ?? '', '');
|
|
920
|
+
}
|
|
921
|
+
},
|
|
922
|
+
onCommand: (cmd) => { codingAgentCommand = cmd; },
|
|
923
|
+
onUsage: (u) => { providerUsage = u; },
|
|
924
|
+
onExitCode: (code) => { exitCode = code; },
|
|
925
|
+
onModel: (m) => { if (!resolvedModel)
|
|
926
|
+
resolvedModel = m; },
|
|
927
|
+
});
|
|
928
|
+
emitStartIfNeeded();
|
|
929
|
+
const durationMs = Date.now() - startMs;
|
|
930
|
+
this.emit('task:end', {
|
|
931
|
+
traceId, timestamp: new Date(), agentRef, mode: 'query', result: response, durationMs,
|
|
932
|
+
exitCode,
|
|
933
|
+
inputTokens: providerUsage?.inputTokens,
|
|
934
|
+
outputTokens: providerUsage?.outputTokens,
|
|
935
|
+
cachedInputTokens: providerUsage?.cachedInputTokens,
|
|
936
|
+
costUsd: providerUsage?.costUsd,
|
|
937
|
+
model: resolvedModel,
|
|
938
|
+
metadata: { ...(options?.metadata ?? {}), ...(options?.threadId ? { threadId: options.threadId } : {}) },
|
|
939
|
+
});
|
|
940
|
+
return {
|
|
941
|
+
ok: true,
|
|
942
|
+
data: response,
|
|
943
|
+
meta: { agentId: agent.id, provider: effectiveProviderStr, model: effectiveModel, durationMs },
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
catch (err) {
|
|
947
|
+
// Client tool call required — return requires_action with thread state
|
|
948
|
+
if (err instanceof bridge_1.ClientToolCallRequiredError) {
|
|
949
|
+
const threadId = (0, id_1.generateId)('thd');
|
|
950
|
+
this._pendingThreads.set(threadId, {
|
|
951
|
+
agentRef: agent.id,
|
|
952
|
+
providerStr: effectiveProviderStr,
|
|
953
|
+
continuationState: err.continuationState,
|
|
954
|
+
toolCall: err.toolCall,
|
|
955
|
+
traceId,
|
|
956
|
+
startMs,
|
|
957
|
+
model: effectiveModel,
|
|
958
|
+
});
|
|
959
|
+
return {
|
|
960
|
+
ok: true,
|
|
961
|
+
status: 'requires_action',
|
|
962
|
+
data: '',
|
|
963
|
+
toolCall: err.toolCall,
|
|
964
|
+
threadId,
|
|
965
|
+
meta: { agentId: agent.id, provider: effectiveProviderStr, model: effectiveModel, durationMs: Date.now() - startMs },
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
emitStartIfNeeded();
|
|
969
|
+
const durationMs = Date.now() - startMs;
|
|
970
|
+
const error = { code: 'QUERY_FAILED', message: err.message };
|
|
971
|
+
this.emit('task:end', {
|
|
972
|
+
traceId, timestamp: new Date(), agentRef, mode: 'query', durationMs, error,
|
|
973
|
+
exitCode,
|
|
974
|
+
inputTokens: providerUsage?.inputTokens,
|
|
975
|
+
outputTokens: providerUsage?.outputTokens,
|
|
976
|
+
cachedInputTokens: providerUsage?.cachedInputTokens,
|
|
977
|
+
costUsd: providerUsage?.costUsd,
|
|
978
|
+
model: resolvedModel,
|
|
979
|
+
metadata: options?.metadata ? { ...options.metadata } : undefined,
|
|
980
|
+
});
|
|
981
|
+
return {
|
|
982
|
+
ok: false,
|
|
983
|
+
data: '',
|
|
984
|
+
error,
|
|
985
|
+
meta: { agentId: agent.id, provider: effectiveProviderStr, model: effectiveModel, durationMs },
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* Continue a conversation after providing client-side tool results.
|
|
991
|
+
*
|
|
992
|
+
* Called when a previous query() returned status: 'requires_action'.
|
|
993
|
+
* Feeds the tool result back to the agent and resumes generation.
|
|
994
|
+
* May return 'requires_action' again if the agent calls another client tool.
|
|
995
|
+
*/
|
|
996
|
+
async continueQuery(threadId, toolResults) {
|
|
997
|
+
const state = this._pendingThreads.get(threadId);
|
|
998
|
+
if (!state) {
|
|
999
|
+
return {
|
|
1000
|
+
ok: false,
|
|
1001
|
+
data: '',
|
|
1002
|
+
error: { code: 'THREAD_NOT_FOUND', message: `No pending thread: ${threadId}` },
|
|
1003
|
+
meta: { agentId: '', provider: '', durationMs: 0 },
|
|
1004
|
+
};
|
|
1005
|
+
}
|
|
1006
|
+
this._pendingThreads.delete(threadId);
|
|
1007
|
+
const provider = (0, bridge_1.createProvider)(state.providerStr);
|
|
1008
|
+
if (!provider.continueWithToolResults) {
|
|
1009
|
+
return {
|
|
1010
|
+
ok: false,
|
|
1011
|
+
data: '',
|
|
1012
|
+
error: { code: 'UNSUPPORTED', message: 'Provider does not support client tool continuation' },
|
|
1013
|
+
meta: { agentId: state.agentRef, provider: state.providerStr, durationMs: 0 },
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
// Enrich toolResults with toolName (looked up from stored toolCall by toolCallId)
|
|
1017
|
+
const enrichedToolResults = toolResults.map(tr => ({
|
|
1018
|
+
...tr,
|
|
1019
|
+
toolName: state.toolCall.toolCallId === tr.toolCallId
|
|
1020
|
+
? state.toolCall.toolName
|
|
1021
|
+
: tr.toolCallId,
|
|
1022
|
+
}));
|
|
1023
|
+
try {
|
|
1024
|
+
const response = await provider.continueWithToolResults(state.continuationState, enrichedToolResults);
|
|
1025
|
+
const durationMs = Date.now() - state.startMs;
|
|
1026
|
+
this.emit('task:end', {
|
|
1027
|
+
traceId: state.traceId, timestamp: new Date(), agentRef: state.agentRef,
|
|
1028
|
+
mode: 'query', result: response, durationMs,
|
|
1029
|
+
});
|
|
1030
|
+
return {
|
|
1031
|
+
ok: true,
|
|
1032
|
+
status: 'complete',
|
|
1033
|
+
data: response,
|
|
1034
|
+
meta: { agentId: state.agentRef, provider: state.providerStr, model: state.model, durationMs },
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
catch (err) {
|
|
1038
|
+
if (err instanceof bridge_1.ClientToolCallRequiredError) {
|
|
1039
|
+
// Another client tool needed — re-store thread state
|
|
1040
|
+
this._pendingThreads.set(threadId, {
|
|
1041
|
+
...state,
|
|
1042
|
+
continuationState: err.continuationState,
|
|
1043
|
+
toolCall: err.toolCall,
|
|
1044
|
+
});
|
|
1045
|
+
return {
|
|
1046
|
+
ok: true,
|
|
1047
|
+
status: 'requires_action',
|
|
1048
|
+
data: '',
|
|
1049
|
+
toolCall: err.toolCall,
|
|
1050
|
+
threadId,
|
|
1051
|
+
meta: { agentId: state.agentRef, provider: state.providerStr, model: state.model, durationMs: Date.now() - state.startMs },
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
const durationMs = Date.now() - state.startMs;
|
|
1055
|
+
return {
|
|
1056
|
+
ok: false,
|
|
1057
|
+
data: '',
|
|
1058
|
+
error: { code: 'CONTINUE_FAILED', message: err.message },
|
|
1059
|
+
meta: { agentId: state.agentRef, provider: state.providerStr, model: state.model, durationMs },
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
/**
|
|
1064
|
+
* Execute a task with an agent.
|
|
1065
|
+
*
|
|
1066
|
+
* Emits task:start (with child pid when available) then task:output per
|
|
1067
|
+
* stdout/stderr line, then task:end on completion or error.
|
|
1068
|
+
*/
|
|
1069
|
+
async execute(agentRef, message, options) {
|
|
1070
|
+
// file:// remote agents: delegate entirely to the target Crewx so execution
|
|
1071
|
+
// runs inside the target workspace (same as `crewx x` invoked in that dir).
|
|
1072
|
+
const remoteTarget = await this.resolveFileRemoteTarget(agentRef);
|
|
1073
|
+
if (remoteTarget) {
|
|
1074
|
+
return remoteTarget.target.execute(remoteTarget.agentRef, message, options);
|
|
1075
|
+
}
|
|
1076
|
+
const startMs = Date.now();
|
|
1077
|
+
const traceId = (0, id_1.generateId)('tsk');
|
|
1078
|
+
const timestamp = new Date();
|
|
1079
|
+
let agent;
|
|
1080
|
+
try {
|
|
1081
|
+
agent = (0, resolver_1.resolveAgent)(agentRef, Array.from(this._agents.values()));
|
|
1082
|
+
}
|
|
1083
|
+
catch (err) {
|
|
1084
|
+
if (err instanceof resolver_1.AgentNotFoundError) {
|
|
1085
|
+
this.emit('task:start', { traceId, timestamp, agentRef, message: message, mode: 'execute', metadata: { ...(options?.metadata ?? {}) }, threadId: options?.threadId, platform: options?.platform ?? 'cli', workspaceId: this._workspaceId, workspaceName: this._workspaceName });
|
|
1086
|
+
const durationMs = Date.now() - startMs;
|
|
1087
|
+
const error = { code: 'AGENT_NOT_FOUND', message: err.message };
|
|
1088
|
+
this.emit('task:end', { traceId, timestamp: new Date(), agentRef, mode: 'execute', durationMs, error, metadata: options?.metadata ? { ...options.metadata } : undefined });
|
|
1089
|
+
return {
|
|
1090
|
+
ok: false,
|
|
1091
|
+
data: '',
|
|
1092
|
+
error,
|
|
1093
|
+
meta: { agentId: agentRef.replace(/^@/, ''), provider: '', durationMs },
|
|
1094
|
+
};
|
|
1095
|
+
}
|
|
1096
|
+
throw err;
|
|
1097
|
+
}
|
|
1098
|
+
const providerStr = Array.isArray(agent.provider)
|
|
1099
|
+
? agent.provider[0] ?? 'cli/claude'
|
|
1100
|
+
: agent.provider;
|
|
1101
|
+
const effectiveProviderStr = options?.provider ?? providerStr;
|
|
1102
|
+
const effectiveModel = options?.model ?? agent.inline?.model;
|
|
1103
|
+
let provider;
|
|
1104
|
+
try {
|
|
1105
|
+
provider = (0, bridge_1.createProvider)(effectiveProviderStr);
|
|
1106
|
+
}
|
|
1107
|
+
catch (err) {
|
|
1108
|
+
this.emit('task:start', { traceId, timestamp, agentRef, message: message, mode: 'execute', metadata: { ...(options?.metadata ?? {}) }, threadId: options?.threadId, platform: options?.platform ?? 'cli', workspaceId: this._workspaceId, workspaceName: this._workspaceName });
|
|
1109
|
+
const durationMs = Date.now() - startMs;
|
|
1110
|
+
const error = { code: 'PROVIDER_ERROR', message: err.message };
|
|
1111
|
+
this.emit('task:end', { traceId, timestamp: new Date(), agentRef, mode: 'execute', durationMs, error, metadata: options?.metadata ? { ...options.metadata } : undefined });
|
|
1112
|
+
return {
|
|
1113
|
+
ok: false,
|
|
1114
|
+
data: '',
|
|
1115
|
+
error,
|
|
1116
|
+
meta: { agentId: agent.id, provider: effectiveProviderStr, model: effectiveModel, durationMs },
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
// WI-CONV-002: Auto-fetch conversation history for thread context injection
|
|
1120
|
+
const historyMessages = await this._fetchHistoryMessages(options?.threadId, traceId, options?.messages);
|
|
1121
|
+
// Render agent prompt with user_input for <user_query> wrapping (non-fatal if it fails)
|
|
1122
|
+
// Intentionally includes user_input in renderedPrompt for tracing/logging purposes.
|
|
1123
|
+
let renderedPrompt;
|
|
1124
|
+
try {
|
|
1125
|
+
renderedPrompt = await this.renderAgentPromptFull(agentRef, {
|
|
1126
|
+
session: { mode: 'execute', platform: options?.platform },
|
|
1127
|
+
vars: { user_input: message },
|
|
1128
|
+
messages: historyMessages,
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
catch {
|
|
1132
|
+
// Prompt rendering is best-effort; do not block the execute
|
|
1133
|
+
}
|
|
1134
|
+
let codingAgentCommand;
|
|
1135
|
+
let providerUsage;
|
|
1136
|
+
let exitCode;
|
|
1137
|
+
let resolvedModel = effectiveModel;
|
|
1138
|
+
let taskStartEmitted = false;
|
|
1139
|
+
const emitStartIfNeeded = (pid) => {
|
|
1140
|
+
if (!taskStartEmitted) {
|
|
1141
|
+
taskStartEmitted = true;
|
|
1142
|
+
this.emit('task:start', {
|
|
1143
|
+
traceId, timestamp, agentRef, message: message, mode: 'execute', pid,
|
|
1144
|
+
model: resolvedModel,
|
|
1145
|
+
provider: effectiveProviderStr,
|
|
1146
|
+
codingAgentCommand,
|
|
1147
|
+
renderedPrompt,
|
|
1148
|
+
metadata: { ...(options?.metadata ?? {}), provider: effectiveProviderStr },
|
|
1149
|
+
threadId: options?.threadId,
|
|
1150
|
+
platform: options?.platform ?? 'cli',
|
|
1151
|
+
workspaceId: this._workspaceId,
|
|
1152
|
+
workspaceName: this._workspaceName,
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
};
|
|
1156
|
+
const agentCliOpts = agent.options;
|
|
1157
|
+
// Filter tools for execute mode
|
|
1158
|
+
const executeToolNames = Array.isArray(agentCliOpts?.execute?.tools)
|
|
1159
|
+
? agentCliOpts.execute.tools
|
|
1160
|
+
: undefined;
|
|
1161
|
+
const filteredTools = this._tools.size > 0
|
|
1162
|
+
? this._filterToolsByMode(executeToolNames)
|
|
1163
|
+
: [];
|
|
1164
|
+
// maxSteps from agent inline config
|
|
1165
|
+
const maxSteps = agent.inline?.max_steps;
|
|
1166
|
+
// api/* providers don't emit pid — emit task:start early so plugins (FileLogger) can log tool calls
|
|
1167
|
+
if (effectiveProviderStr.startsWith('api/')) {
|
|
1168
|
+
emitStartIfNeeded();
|
|
1169
|
+
}
|
|
1170
|
+
try {
|
|
1171
|
+
const response = await provider.execute(message, {
|
|
1172
|
+
model: effectiveModel,
|
|
1173
|
+
context: options?.context,
|
|
1174
|
+
systemPrompt: renderedPrompt ?? agent.inline?.system_prompt ?? agent.inline?.prompt,
|
|
1175
|
+
additionalArgs: Array.isArray(agentCliOpts?.execute) ? agentCliOpts.execute : undefined,
|
|
1176
|
+
tools: filteredTools.length > 0 ? filteredTools : undefined,
|
|
1177
|
+
maxSteps,
|
|
1178
|
+
env: {
|
|
1179
|
+
CREWX_AGENT_ID: agent.id,
|
|
1180
|
+
CREWX_AGENT_ROLE: agent.role ?? '',
|
|
1181
|
+
CREWX_AGENT_TEAM: agent.team ?? '',
|
|
1182
|
+
CREWX_USER_ID: process.env.USER || process.env.USERNAME || 'unknown',
|
|
1183
|
+
CREWX_TRACE_ID: traceId,
|
|
1184
|
+
CREWX_PARENT_TASK_ID: traceId,
|
|
1185
|
+
CREWX_TASK_ID: traceId,
|
|
1186
|
+
CREWX_CALLER_AGENT_ID: process.env.CREWX_AGENT_ID ?? '',
|
|
1187
|
+
CREWX_THREAD_ID: options?.threadId ?? '',
|
|
1188
|
+
CREWX_PROVIDER: effectiveProviderStr,
|
|
1189
|
+
CREWX_SESSION_ID: '',
|
|
1190
|
+
CREWX_TASK_LOG_PATH: this.computeTaskLogPath(traceId, timestamp),
|
|
1191
|
+
},
|
|
1192
|
+
onPid: (pid) => emitStartIfNeeded(pid),
|
|
1193
|
+
onOutput: (line, level) => {
|
|
1194
|
+
this.emit('task:output', { traceId, timestamp: new Date(), agentRef, output: line, level });
|
|
1195
|
+
if (level === 'stdout') {
|
|
1196
|
+
this.emitToolEvents(traceId, agentRef, effectiveProviderStr, line, agent.id, options?.threadId ?? '', '');
|
|
1197
|
+
}
|
|
1198
|
+
},
|
|
1199
|
+
onCommand: (cmd) => { codingAgentCommand = cmd; },
|
|
1200
|
+
onUsage: (u) => { providerUsage = u; },
|
|
1201
|
+
onExitCode: (code) => { exitCode = code; },
|
|
1202
|
+
onModel: (m) => { if (!resolvedModel)
|
|
1203
|
+
resolvedModel = m; },
|
|
1204
|
+
});
|
|
1205
|
+
emitStartIfNeeded();
|
|
1206
|
+
const durationMs = Date.now() - startMs;
|
|
1207
|
+
this.emit('task:end', {
|
|
1208
|
+
traceId, timestamp: new Date(), agentRef, mode: 'execute', result: response, durationMs,
|
|
1209
|
+
exitCode,
|
|
1210
|
+
inputTokens: providerUsage?.inputTokens,
|
|
1211
|
+
outputTokens: providerUsage?.outputTokens,
|
|
1212
|
+
cachedInputTokens: providerUsage?.cachedInputTokens,
|
|
1213
|
+
costUsd: providerUsage?.costUsd,
|
|
1214
|
+
model: resolvedModel,
|
|
1215
|
+
metadata: { ...(options?.metadata ?? {}), ...(options?.threadId ? { threadId: options.threadId } : {}) },
|
|
1216
|
+
});
|
|
1217
|
+
return {
|
|
1218
|
+
ok: true,
|
|
1219
|
+
data: response,
|
|
1220
|
+
meta: { agentId: agent.id, provider: effectiveProviderStr, model: effectiveModel, durationMs },
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
catch (err) {
|
|
1224
|
+
emitStartIfNeeded();
|
|
1225
|
+
const durationMs = Date.now() - startMs;
|
|
1226
|
+
const error = { code: 'EXECUTE_FAILED', message: err.message };
|
|
1227
|
+
this.emit('task:end', {
|
|
1228
|
+
traceId, timestamp: new Date(), agentRef, mode: 'execute', durationMs, error,
|
|
1229
|
+
exitCode,
|
|
1230
|
+
inputTokens: providerUsage?.inputTokens,
|
|
1231
|
+
outputTokens: providerUsage?.outputTokens,
|
|
1232
|
+
cachedInputTokens: providerUsage?.cachedInputTokens,
|
|
1233
|
+
costUsd: providerUsage?.costUsd,
|
|
1234
|
+
model: resolvedModel,
|
|
1235
|
+
metadata: options?.metadata ? { ...options.metadata } : undefined,
|
|
1236
|
+
});
|
|
1237
|
+
return {
|
|
1238
|
+
ok: false,
|
|
1239
|
+
data: '',
|
|
1240
|
+
error,
|
|
1241
|
+
meta: { agentId: agent.id, provider: effectiveProviderStr, model: effectiveModel, durationMs },
|
|
1242
|
+
};
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
exports.Crewx = Crewx;
|
|
1247
|
+
// ── Module-level helper ─────────────────────────────────────────────────────
|
|
1248
|
+
/**
|
|
1249
|
+
* Auto-register the `remote` provider factory if any agent uses `remote/*` namespace.
|
|
1250
|
+
* Reads remote provider configs from crewx.yaml `providers:` section.
|
|
1251
|
+
*/
|
|
1252
|
+
function registerRemoteProvidersIfNeeded(agents, config) {
|
|
1253
|
+
const hasRemoteProvider = agents.some(a => {
|
|
1254
|
+
const providers = Array.isArray(a.provider) ? a.provider : [a.provider];
|
|
1255
|
+
return providers.some(p => p.startsWith('remote/'));
|
|
1256
|
+
});
|
|
1257
|
+
if (!hasRemoteProvider)
|
|
1258
|
+
return;
|
|
1259
|
+
// Read remote provider configs from crewx.yaml `providers:` array
|
|
1260
|
+
const providersRaw = config.providers;
|
|
1261
|
+
if (!Array.isArray(providersRaw))
|
|
1262
|
+
return;
|
|
1263
|
+
const { createRemoteProviderFactory } = require('../remote/remote-provider.js');
|
|
1264
|
+
const remoteConfigs = new Map();
|
|
1265
|
+
for (const entry of providersRaw) {
|
|
1266
|
+
if (entry.type === 'remote' && typeof entry.id === 'string') {
|
|
1267
|
+
remoteConfigs.set(entry.id, entry);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
if (remoteConfigs.size > 0) {
|
|
1271
|
+
(0, bridge_1.registerProviderFactory)('remote', createRemoteProviderFactory(remoteConfigs, bridge_1.createProvider));
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Auto-register the `plugin` provider factory if any agent uses `plugin/*` namespace.
|
|
1276
|
+
* Reads plugin provider configs from crewx.yaml `providers:` section.
|
|
1277
|
+
*/
|
|
1278
|
+
function registerPluginProvidersIfNeeded(agents, config) {
|
|
1279
|
+
const hasPluginProvider = agents.some(a => {
|
|
1280
|
+
const providers = Array.isArray(a.provider) ? a.provider : [a.provider];
|
|
1281
|
+
return providers.some(p => p.startsWith('plugin/'));
|
|
1282
|
+
});
|
|
1283
|
+
if (!hasPluginProvider)
|
|
1284
|
+
return;
|
|
1285
|
+
const providersRaw = config.providers;
|
|
1286
|
+
if (!Array.isArray(providersRaw))
|
|
1287
|
+
return;
|
|
1288
|
+
const { createPluginProviderFactory } = require('../plugin/plugin-provider.js');
|
|
1289
|
+
const pluginConfigs = new Map();
|
|
1290
|
+
for (const entry of providersRaw) {
|
|
1291
|
+
if (entry.type === 'plugin' && typeof entry.id === 'string') {
|
|
1292
|
+
pluginConfigs.set(entry.id, entry);
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
if (pluginConfigs.size > 0) {
|
|
1296
|
+
(0, bridge_1.registerProviderFactory)('plugin', createPluginProviderFactory(pluginConfigs));
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
//# sourceMappingURL=Crewx.js.map
|