@schlenkr/ragents 0.1.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/LICENSE +166 -0
- package/README.md +88 -0
- package/apps/server/agent-home/settings.json +3 -0
- package/apps/server/package.json +29 -0
- package/apps/server/src/access-projection.ts +97 -0
- package/apps/server/src/access-service.ts +22 -0
- package/apps/server/src/access-session.ts +204 -0
- package/apps/server/src/api/contracts.ts +203 -0
- package/apps/server/src/api/core-methods.ts +163 -0
- package/apps/server/src/api/delivery.ts +40 -0
- package/apps/server/src/api/reference.ts +146 -0
- package/apps/server/src/api/rights.ts +26 -0
- package/apps/server/src/chat-attachments.ts +52 -0
- package/apps/server/src/chat-context.ts +6 -0
- package/apps/server/src/chat-events.ts +185 -0
- package/apps/server/src/chat-handler.ts +37 -0
- package/apps/server/src/config-definition.ts +80 -0
- package/apps/server/src/config-file.ts +324 -0
- package/apps/server/src/config.ts +46 -0
- package/apps/server/src/data-directory.ts +42 -0
- package/apps/server/src/external-access.ts +40 -0
- package/apps/server/src/help-files.ts +63 -0
- package/apps/server/src/host-resolution-hooks.mjs +31 -0
- package/apps/server/src/host-resolution.ts +3 -0
- package/apps/server/src/host-version.ts +74 -0
- package/apps/server/src/layout.ts +36 -0
- package/apps/server/src/main.ts +54 -0
- package/apps/server/src/plugin-support/actor-programs/capability-resolver.ts +107 -0
- package/apps/server/src/plugin-support/actor-programs/limits.ts +33 -0
- package/apps/server/src/plugin-support/actor-programs/operations.ts +19 -0
- package/apps/server/src/plugin-support/actor-programs/service.ts +16 -0
- package/apps/server/src/plugin-support/agent-tool.ts +60 -0
- package/apps/server/src/plugin-support/asset-path.ts +4 -0
- package/apps/server/src/plugin-support/await-with-signal.ts +18 -0
- package/apps/server/src/plugin-support/chat-display-contract.ts +7 -0
- package/apps/server/src/plugin-support/chat-display-policy.ts +55 -0
- package/apps/server/src/plugin-support/front-matter.ts +44 -0
- package/apps/server/src/plugin-support/http.ts +93 -0
- package/apps/server/src/plugin-support/language-server/contract.ts +18 -0
- package/apps/server/src/plugin-support/language-server/plugin.ts +32 -0
- package/apps/server/src/plugin-support/language-server/snapshot-method.ts +17 -0
- package/apps/server/src/plugin-support/language-server/tools.ts +73 -0
- package/apps/server/src/plugin-support/model-choice.ts +109 -0
- package/apps/server/src/plugin-support/model-upstreams.ts +12 -0
- package/apps/server/src/plugin-support/native-typescript-child.ts +78 -0
- package/apps/server/src/plugin-support/native-typescript-executor.ts +260 -0
- package/apps/server/src/plugin-support/plugin-config.ts +48 -0
- package/apps/server/src/plugin-support/plugin-folder.ts +81 -0
- package/apps/server/src/plugin-support/plugin-module.ts +14 -0
- package/apps/server/src/plugin-support/plugins-root.ts +41 -0
- package/apps/server/src/plugin-support/product-model-settings-contract.ts +24 -0
- package/apps/server/src/plugin-support/product-model-settings.ts +120 -0
- package/apps/server/src/plugin-support/product-start-options.ts +104 -0
- package/apps/server/src/plugin-support/prompt.ts +68 -0
- package/apps/server/src/plugin-support/provision.ts +85 -0
- package/apps/server/src/plugin-support/run-scripts.ts +88 -0
- package/apps/server/src/plugin-support/shell-platform.ts +21 -0
- package/apps/server/src/plugin-support/skills.ts +97 -0
- package/apps/server/src/plugin-support/start-entries-contract.ts +71 -0
- package/apps/server/src/plugin-support/start-options-contract.ts +65 -0
- package/apps/server/src/plugin-support/system-prompts.ts +138 -0
- package/apps/server/src/plugin-support/thinking-level.ts +8 -0
- package/apps/server/src/plugin-support/tool-availability.ts +20 -0
- package/apps/server/src/plugin-support/workspace-ownership.ts +36 -0
- package/apps/server/src/plugin-support/workspace-sandbox-host.ts +213 -0
- package/apps/server/src/plugin-support/workspace-tool-naming.ts +11 -0
- package/apps/server/src/plugin-support/zip.ts +69 -0
- package/apps/server/src/profile/compose.ts +69 -0
- package/apps/server/src/profile/plugin-discovery.ts +112 -0
- package/apps/server/src/profile/plugin-list.ts +19 -0
- package/apps/server/src/profile/provisioning.ts +81 -0
- package/apps/server/src/protocol.ts +106 -0
- package/apps/server/src/provider.ts +817 -0
- package/apps/server/src/ragents/actor-chat-history.ts +111 -0
- package/apps/server/src/ragents/chat-projection.ts +55 -0
- package/apps/server/src/ragents/chat-text-positions.ts +43 -0
- package/apps/server/src/ragents/coordinator.ts +5 -0
- package/apps/server/src/ragents/document-store.ts +12 -0
- package/apps/server/src/ragents/engine.ts +417 -0
- package/apps/server/src/ragents/global-chat.ts +40 -0
- package/apps/server/src/ragents/host-services.ts +26 -0
- package/apps/server/src/ragents/journal-chat-events.ts +52 -0
- package/apps/server/src/ragents/product-runtime.ts +31 -0
- package/apps/server/src/ragents/runtime-bridge.ts +7 -0
- package/apps/server/src/ragents/session.ts +859 -0
- package/apps/server/src/ragents/start-option-state.ts +37 -0
- package/apps/server/src/ragents/typescript-tools.ts +182 -0
- package/apps/server/src/ragents/workspace-runtime.ts +64 -0
- package/apps/server/src/rpc/dispatcher.ts +178 -0
- package/apps/server/src/rpc/http-transport.ts +178 -0
- package/apps/server/src/rpc/stdio-transport.ts +44 -0
- package/apps/server/src/run-preparation-contract.ts +20 -0
- package/apps/server/src/run-preparation-input.ts +16 -0
- package/apps/server/src/run-preparation.ts +147 -0
- package/apps/server/src/run-transfer.ts +264 -0
- package/apps/server/src/server.ts +312 -0
- package/apps/server/src/settings.ts +209 -0
- package/apps/server/src/startup.ts +13 -0
- package/apps/server/src/title-compactor.ts +131 -0
- package/apps/server/src/title-settings-contract.ts +9 -0
- package/apps/server/src/title-settings.ts +67 -0
- package/apps/web/package.json +41 -0
- package/apps/web/src/AccessContext.tsx +125 -0
- package/apps/web/src/App.tsx +315 -0
- package/apps/web/src/CanvasShortcuts.tsx +60 -0
- package/apps/web/src/DiffCode.tsx +89 -0
- package/apps/web/src/HelpDialog.tsx +87 -0
- package/apps/web/src/MaterialSettings.tsx +40 -0
- package/apps/web/src/Overview.tsx +201 -0
- package/apps/web/src/PluginActivation.ts +41 -0
- package/apps/web/src/PluginChat.tsx +552 -0
- package/apps/web/src/PluginRegistry.tsx +689 -0
- package/apps/web/src/RunPreparationChat.tsx +111 -0
- package/apps/web/src/RunStore.ts +86 -0
- package/apps/web/src/SessionList.tsx +148 -0
- package/apps/web/src/SettingsModal.tsx +949 -0
- package/apps/web/src/SourceCode.tsx +49 -0
- package/apps/web/src/StartOptions.tsx +231 -0
- package/apps/web/src/StartSurface.tsx +161 -0
- package/apps/web/src/StatusGroup.tsx +18 -0
- package/apps/web/src/ThemeSettings.tsx +46 -0
- package/apps/web/src/TitleModelSettings.tsx +100 -0
- package/apps/web/src/Toolbar.tsx +28 -0
- package/apps/web/src/WorkspacePanel.tsx +309 -0
- package/apps/web/src/access-session.ts +27 -0
- package/apps/web/src/access-token.ts +31 -0
- package/apps/web/src/api.ts +368 -0
- package/apps/web/src/chat/ChatInputToolbar.tsx +488 -0
- package/apps/web/src/chat/ChatMessages.tsx +666 -0
- package/apps/web/src/chat/ChatPanel.tsx +61 -0
- package/apps/web/src/chat/DetailModeSwitch.tsx +58 -0
- package/apps/web/src/chat/Markdown.tsx +104 -0
- package/apps/web/src/chat/QuestionCard.tsx +107 -0
- package/apps/web/src/chat/StepPopover.tsx +82 -0
- package/apps/web/src/chat/WorkingScenes.tsx +235 -0
- package/apps/web/src/chat/attachments.ts +53 -0
- package/apps/web/src/chat/chat-scroll.ts +41 -0
- package/apps/web/src/chat/chat-target.ts +21 -0
- package/apps/web/src/chat/requests.ts +23 -0
- package/apps/web/src/chat/texts.ts +61 -0
- package/apps/web/src/chat/types.ts +26 -0
- package/apps/web/src/chat/useAttachmentCapabilities.ts +35 -0
- package/apps/web/src/chat/useChat.ts +46 -0
- package/apps/web/src/chat/user-location.ts +22 -0
- package/apps/web/src/column/ColumnApp.tsx +158 -0
- package/apps/web/src/column/ColumnMenu.tsx +37 -0
- package/apps/web/src/column/ColumnRunHeader.tsx +43 -0
- package/apps/web/src/column/column-location.ts +30 -0
- package/apps/web/src/column/host-contract.ts +83 -0
- package/apps/web/src/column/host.ts +101 -0
- package/apps/web/src/column/use-session-list.ts +42 -0
- package/apps/web/src/column.tsx +43 -0
- package/apps/web/src/diff-view.css +38 -0
- package/apps/web/src/help-samples.ts +11 -0
- package/apps/web/src/highlighting.css +74 -0
- package/apps/web/src/highlighting.ts +262 -0
- package/apps/web/src/lib/format.ts +5 -0
- package/apps/web/src/lib/guards.ts +8 -0
- package/apps/web/src/lib/http.ts +9 -0
- package/apps/web/src/lib/labels.ts +11 -0
- package/apps/web/src/lib/local-storage-setting.ts +39 -0
- package/apps/web/src/main.tsx +30 -0
- package/apps/web/src/material-settings.ts +104 -0
- package/apps/web/src/model-settings-events.ts +1 -0
- package/apps/web/src/page-opener.tsx +14 -0
- package/apps/web/src/panel/LoginForm.tsx +31 -0
- package/apps/web/src/panel/OverviewPage.tsx +90 -0
- package/apps/web/src/panel/PanelPage.tsx +9 -0
- package/apps/web/src/panel/SettingsPage.tsx +102 -0
- package/apps/web/src/panel/contract.ts +101 -0
- package/apps/web/src/panel/target-state.ts +53 -0
- package/apps/web/src/panel.tsx +30 -0
- package/apps/web/src/plugin-bootstrap.ts +90 -0
- package/apps/web/src/plugin-discovery.ts +5 -0
- package/apps/web/src/rpc/client.ts +301 -0
- package/apps/web/src/rpc.ts +4 -0
- package/apps/web/src/run-overview.ts +34 -0
- package/apps/web/src/run-preparation.ts +16 -0
- package/apps/web/src/run-read-state.ts +33 -0
- package/apps/web/src/settings-contributions.ts +274 -0
- package/apps/web/src/theme.ts +135 -0
- package/apps/web/src/title-model-settings.ts +51 -0
- package/apps/web/src/toolLine.ts +67 -0
- package/apps/web/src/ui/ListDetail.tsx +149 -0
- package/apps/web/src/ui/SectionLabel.tsx +7 -0
- package/apps/web/src/ui/SvgEdge.tsx +39 -0
- package/apps/web/src/ui/alert.tsx +75 -0
- package/apps/web/src/ui/badge.tsx +51 -0
- package/apps/web/src/ui/button.tsx +57 -0
- package/apps/web/src/ui/card.tsx +102 -0
- package/apps/web/src/ui/checkbox.tsx +26 -0
- package/apps/web/src/ui/dialog.tsx +250 -0
- package/apps/web/src/ui/dropdown-menu.tsx +265 -0
- package/apps/web/src/ui/empty.tsx +103 -0
- package/apps/web/src/ui/field.tsx +236 -0
- package/apps/web/src/ui/frame.css +4 -0
- package/apps/web/src/ui/index.ts +43 -0
- package/apps/web/src/ui/input.tsx +19 -0
- package/apps/web/src/ui/label.tsx +17 -0
- package/apps/web/src/ui/modal-controller.ts +70 -0
- package/apps/web/src/ui/modal.tsx +62 -0
- package/apps/web/src/ui/popover.tsx +102 -0
- package/apps/web/src/ui/progress.tsx +80 -0
- package/apps/web/src/ui/radio-group.tsx +35 -0
- package/apps/web/src/ui/select.tsx +198 -0
- package/apps/web/src/ui/separator.tsx +22 -0
- package/apps/web/src/ui/skeleton.tsx +13 -0
- package/apps/web/src/ui/spinner.tsx +10 -0
- package/apps/web/src/ui/switch.tsx +29 -0
- package/apps/web/src/ui/table.tsx +113 -0
- package/apps/web/src/ui/tabs.tsx +79 -0
- package/apps/web/src/ui/tailwind.css +21 -0
- package/apps/web/src/ui/textarea.tsx +17 -0
- package/apps/web/src/ui/theme.css +300 -0
- package/apps/web/src/ui/toggle-group.tsx +87 -0
- package/apps/web/src/ui/toggle.tsx +42 -0
- package/apps/web/src/ui/tooltip.tsx +63 -0
- package/apps/web/src/ui/useFileInput.ts +50 -0
- package/apps/web/src/virtual-plugins.d.ts +3 -0
- package/apps/web/src/vite-env.d.ts +1 -0
- package/package.json +82 -0
- package/packages/agent/package.json +64 -0
- package/packages/agent/src/config.ts +161 -0
- package/packages/agent/src/core/agent-session-runtime.ts +548 -0
- package/packages/agent/src/core/agent-session-services.ts +224 -0
- package/packages/agent/src/core/agent-session.ts +3357 -0
- package/packages/agent/src/core/auth-guidance.ts +18 -0
- package/packages/agent/src/core/auth-storage.ts +271 -0
- package/packages/agent/src/core/bash-executor.ts +156 -0
- package/packages/agent/src/core/compaction/branch-summarization.ts +372 -0
- package/packages/agent/src/core/compaction/compaction.ts +875 -0
- package/packages/agent/src/core/compaction/index.ts +7 -0
- package/packages/agent/src/core/compaction/utils.ts +174 -0
- package/packages/agent/src/core/defaults.ts +3 -0
- package/packages/agent/src/core/diagnostics.ts +15 -0
- package/packages/agent/src/core/event-bus.ts +33 -0
- package/packages/agent/src/core/exec.ts +107 -0
- package/packages/agent/src/core/experimental.ts +3 -0
- package/packages/agent/src/core/extensions/index.ts +149 -0
- package/packages/agent/src/core/extensions/loader.ts +709 -0
- package/packages/agent/src/core/extensions/runner.ts +1132 -0
- package/packages/agent/src/core/extensions/types.ts +1460 -0
- package/packages/agent/src/core/extensions/wrapper.ts +45 -0
- package/packages/agent/src/core/footer-data-provider.ts +388 -0
- package/packages/agent/src/core/http-dispatcher.ts +106 -0
- package/packages/agent/src/core/index.ts +78 -0
- package/packages/agent/src/core/messages.ts +195 -0
- package/packages/agent/src/core/model-config.ts +287 -0
- package/packages/agent/src/core/model-registry.ts +126 -0
- package/packages/agent/src/core/model-resolver.ts +675 -0
- package/packages/agent/src/core/model-runtime.ts +517 -0
- package/packages/agent/src/core/output-guard.ts +108 -0
- package/packages/agent/src/core/package-manager.ts +2441 -0
- package/packages/agent/src/core/prompt-templates.ts +284 -0
- package/packages/agent/src/core/provider-composer.ts +549 -0
- package/packages/agent/src/core/resolve-config-value.ts +287 -0
- package/packages/agent/src/core/resource-loader.ts +946 -0
- package/packages/agent/src/core/runtime-credentials.ts +48 -0
- package/packages/agent/src/core/sdk.ts +358 -0
- package/packages/agent/src/core/session-cwd.ts +59 -0
- package/packages/agent/src/core/session-manager.ts +1623 -0
- package/packages/agent/src/core/settings-manager.ts +1212 -0
- package/packages/agent/src/core/skills.ts +487 -0
- package/packages/agent/src/core/slash-commands.ts +41 -0
- package/packages/agent/src/core/source-info.ts +40 -0
- package/packages/agent/src/core/system-prompt.ts +147 -0
- package/packages/agent/src/core/timings.ts +50 -0
- package/packages/agent/src/core/tools/bash.ts +314 -0
- package/packages/agent/src/core/tools/edit-diff.ts +704 -0
- package/packages/agent/src/core/tools/edit.ts +222 -0
- package/packages/agent/src/core/tools/file-mutation-queue.ts +61 -0
- package/packages/agent/src/core/tools/index.ts +130 -0
- package/packages/agent/src/core/tools/output-accumulator.ts +222 -0
- package/packages/agent/src/core/tools/path-utils.ts +118 -0
- package/packages/agent/src/core/tools/read.ts +195 -0
- package/packages/agent/src/core/tools/tool-definition-wrapper.ts +45 -0
- package/packages/agent/src/core/tools/truncate.ts +276 -0
- package/packages/agent/src/core/tools/write.ts +90 -0
- package/packages/agent/src/core/trust-manager.ts +244 -0
- package/packages/agent/src/index.ts +287 -0
- package/packages/agent/src/utils/ansi.ts +60 -0
- package/packages/agent/src/utils/child-process.ts +137 -0
- package/packages/agent/src/utils/exif-orientation.ts +183 -0
- package/packages/agent/src/utils/frontmatter.ts +39 -0
- package/packages/agent/src/utils/fs-watch.ts +30 -0
- package/packages/agent/src/utils/git.ts +226 -0
- package/packages/agent/src/utils/image-convert.ts +49 -0
- package/packages/agent/src/utils/image-process.ts +119 -0
- package/packages/agent/src/utils/image-resize-core.ts +164 -0
- package/packages/agent/src/utils/image-resize-worker.ts +42 -0
- package/packages/agent/src/utils/image-resize.ts +123 -0
- package/packages/agent/src/utils/json.ts +6 -0
- package/packages/agent/src/utils/mime.ts +116 -0
- package/packages/agent/src/utils/paths.ts +118 -0
- package/packages/agent/src/utils/photon.ts +139 -0
- package/packages/agent/src/utils/shell.ts +225 -0
- package/packages/agent/src/utils/sleep.ts +18 -0
- package/packages/agent/src/utils/tools-manager.ts +63 -0
- package/packages/agent-core/package.json +32 -0
- package/packages/agent-core/src/agent-loop.ts +877 -0
- package/packages/agent-core/src/agent.ts +598 -0
- package/packages/agent-core/src/index.ts +4 -0
- package/packages/agent-core/src/types.ts +455 -0
- package/packages/agent-core/src/uuid.ts +54 -0
- package/packages/ai/package.json +46 -0
- package/packages/ai/src/api/ai-sdk-messages.ts +102 -0
- package/packages/ai/src/api/ai-sdk-transport.ts +53 -0
- package/packages/ai/src/api/ai-sdk.lazy.ts +4 -0
- package/packages/ai/src/api/ai-sdk.ts +273 -0
- package/packages/ai/src/api/lazy.ts +75 -0
- package/packages/ai/src/api/openrouter-images.lazy.ts +10 -0
- package/packages/ai/src/api/openrouter-images.ts +98 -0
- package/packages/ai/src/api/simple-options.ts +77 -0
- package/packages/ai/src/api/transform-messages.ts +185 -0
- package/packages/ai/src/api-registry.ts +226 -0
- package/packages/ai/src/auth/context.ts +45 -0
- package/packages/ai/src/auth/credential-store.ts +51 -0
- package/packages/ai/src/auth/helpers.ts +47 -0
- package/packages/ai/src/auth/resolve.ts +139 -0
- package/packages/ai/src/auth/types.ts +220 -0
- package/packages/ai/src/compat/extension-oauth-types.ts +45 -0
- package/packages/ai/src/env-api-keys.ts +24 -0
- package/packages/ai/src/image-models.generated.ts +533 -0
- package/packages/ai/src/images-models.ts +274 -0
- package/packages/ai/src/index.ts +33 -0
- package/packages/ai/src/models-store.ts +38 -0
- package/packages/ai/src/models.generated.ts +6 -0
- package/packages/ai/src/models.ts +705 -0
- package/packages/ai/src/oauth.ts +10 -0
- package/packages/ai/src/providers/all.ts +64 -0
- package/packages/ai/src/providers/faux.ts +539 -0
- package/packages/ai/src/providers/openrouter-images.ts +14 -0
- package/packages/ai/src/providers/openrouter.models.ts +6050 -0
- package/packages/ai/src/providers/openrouter.ts +15 -0
- package/packages/ai/src/session-resources.ts +24 -0
- package/packages/ai/src/types.ts +692 -0
- package/packages/ai/src/utils/abort-signals.ts +41 -0
- package/packages/ai/src/utils/deferred-tools.ts +39 -0
- package/packages/ai/src/utils/diagnostics.ts +45 -0
- package/packages/ai/src/utils/error-body.ts +129 -0
- package/packages/ai/src/utils/estimate.ts +146 -0
- package/packages/ai/src/utils/event-stream.ts +88 -0
- package/packages/ai/src/utils/hash.ts +13 -0
- package/packages/ai/src/utils/headers.ts +18 -0
- package/packages/ai/src/utils/json-parse.ts +124 -0
- package/packages/ai/src/utils/node-http-proxy.ts +112 -0
- package/packages/ai/src/utils/overflow.ts +165 -0
- package/packages/ai/src/utils/provider-env.ts +52 -0
- package/packages/ai/src/utils/retry.ts +101 -0
- package/packages/ai/src/utils/sanitize-unicode.ts +25 -0
- package/packages/ai/src/utils/typebox-helpers.ts +24 -0
- package/packages/ai/src/utils/validation.ts +383 -0
- package/packages/ragents/package.json +31 -0
- package/packages/ragents/src/access.ts +54 -0
- package/packages/ragents/src/agents/actor-input.ts +191 -0
- package/packages/ragents/src/agents/catalog.ts +220 -0
- package/packages/ragents/src/agents/delivery.ts +187 -0
- package/packages/ragents/src/agents/live.ts +71 -0
- package/packages/ragents/src/agents/plugins.ts +130 -0
- package/packages/ragents/src/agents/scheduler.ts +1048 -0
- package/packages/ragents/src/agents/schemas.ts +64 -0
- package/packages/ragents/src/agents/tool-orientation.ts +12 -0
- package/packages/ragents/src/agents/tools.ts +709 -0
- package/packages/ragents/src/agents/toolset.ts +324 -0
- package/packages/ragents/src/agents/turn.ts +65 -0
- package/packages/ragents/src/agents/workspace-tools.ts +11 -0
- package/packages/ragents/src/agents/workspaces.ts +15 -0
- package/packages/ragents/src/domain/draft.ts +11 -0
- package/packages/ragents/src/domain/driver.ts +56 -0
- package/packages/ragents/src/domain/event-semantics.ts +668 -0
- package/packages/ragents/src/domain/event-validation.ts +620 -0
- package/packages/ragents/src/domain/events.ts +236 -0
- package/packages/ragents/src/domain/json-patch.ts +77 -0
- package/packages/ragents/src/domain/json.ts +86 -0
- package/packages/ragents/src/domain/model.ts +267 -0
- package/packages/ragents/src/domain/plugin-state.ts +33 -0
- package/packages/ragents/src/domain/portable-id.ts +9 -0
- package/packages/ragents/src/domain/projection.ts +506 -0
- package/packages/ragents/src/domain/schema-errors.ts +56 -0
- package/packages/ragents/src/domain/vocabulary.ts +37 -0
- package/packages/ragents/src/drivers/agent-runtime.ts +1503 -0
- package/packages/ragents/src/drivers/agent.ts +108 -0
- package/packages/ragents/src/drivers/attachments.ts +56 -0
- package/packages/ragents/src/drivers/skill-preload.ts +205 -0
- package/packages/ragents/src/drivers/types.ts +77 -0
- package/packages/ragents/src/http/contracts.ts +80 -0
- package/packages/ragents/src/http/methods.ts +150 -0
- package/packages/ragents/src/index.ts +161 -0
- package/packages/ragents/src/plugin-host.ts +1184 -0
- package/packages/ragents/src/plugin-types.ts +373 -0
- package/packages/ragents/src/rpc/contract.ts +76 -0
- package/packages/ragents/src/rpc/contribution.ts +67 -0
- package/packages/ragents/src/rpc/peer.ts +208 -0
- package/packages/ragents/src/rpc/protocol.ts +129 -0
- package/packages/ragents/src/runtime/artifacts.ts +95 -0
- package/packages/ragents/src/runtime/canonical-hash.ts +5 -0
- package/packages/ragents/src/runtime/canonical-json.ts +41 -0
- package/packages/ragents/src/runtime/command.ts +35 -0
- package/packages/ragents/src/runtime/decisions/actions.ts +77 -0
- package/packages/ragents/src/runtime/decisions/actors.ts +283 -0
- package/packages/ragents/src/runtime/decisions/artifacts.ts +28 -0
- package/packages/ragents/src/runtime/decisions/inputs.ts +79 -0
- package/packages/ragents/src/runtime/decisions/subscriptions.ts +135 -0
- package/packages/ragents/src/runtime/decisions/turns.ts +166 -0
- package/packages/ragents/src/runtime/domain-error.ts +10 -0
- package/packages/ragents/src/runtime/durable-fs.ts +13 -0
- package/packages/ragents/src/runtime/failures.ts +18 -0
- package/packages/ragents/src/runtime/guards.ts +196 -0
- package/packages/ragents/src/runtime/journal-storage.ts +228 -0
- package/packages/ragents/src/runtime/journal.ts +952 -0
- package/packages/ragents/src/runtime/orchestration.ts +711 -0
- package/packages/ragents/src/runtime/serial-queue.ts +13 -0
- package/packages/ragents/src/runtime/services.ts +15 -0
- package/packages/ragents/src/runtime/stop.ts +186 -0
- package/packages/ragents/src/script/driver.ts +18 -0
- package/packages/ragents/src/script/mediators.ts +386 -0
- package/packages/ragents/src/script/programs.ts +10 -0
- package/packages/ragents/src/script/std.ts +27 -0
- package/packages/ragents/src/script/types.ts +6 -0
- package/packages/ragents/src/typescript/async-compiler.ts +322 -0
- package/packages/ragents/src/typescript/build-contract.ts +14 -0
- package/packages/ragents/src/typescript/compiler-worker.ts +52 -0
- package/packages/ragents/src/typescript/compiler.ts +304 -0
- package/packages/ragents/src/typescript/index.ts +48 -0
- package/packages/ragents/src/typescript/native-executor.ts +40 -0
- package/packages/ragents/src/typescript/native-program.ts +5 -0
- package/packages/ragents/src/typescript/run-context.ts +199 -0
- package/packages/ragents/src/typescript/schema.ts +176 -0
- package/packages/ragents/src/typescript/snippet.ts +121 -0
- package/packages/workspace-executor/package.json +25 -0
- package/packages/workspace-executor/src/context.ts +123 -0
- package/packages/workspace-executor/src/executor.ts +134 -0
- package/packages/workspace-executor/src/git-config-environment.ts +10 -0
- package/packages/workspace-executor/src/index.ts +52 -0
- package/packages/workspace-executor/src/language-server/adapters/fsharp.ts +59 -0
- package/packages/workspace-executor/src/language-server/adapters/index.ts +7 -0
- package/packages/workspace-executor/src/language-server/adapters/roslyn.ts +54 -0
- package/packages/workspace-executor/src/language-server/adapters/typescript.ts +46 -0
- package/packages/workspace-executor/src/language-server/contract.ts +23 -0
- package/packages/workspace-executor/src/language-server/diagnostics.ts +62 -0
- package/packages/workspace-executor/src/language-server/host.ts +409 -0
- package/packages/workspace-executor/src/language-server/json-rpc.ts +103 -0
- package/packages/workspace-executor/src/language-server/roots.ts +29 -0
- package/packages/workspace-executor/src/language-server/session.ts +442 -0
- package/packages/workspace-executor/src/language-server/solution.ts +13 -0
- package/packages/workspace-executor/src/managed-process.ts +329 -0
- package/packages/workspace-executor/src/paths.ts +43 -0
- package/packages/workspace-executor/src/run-marker.ts +6 -0
- package/packages/workspace-executor/src/safe-environment.ts +47 -0
- package/packages/workspace-executor/src/sandbox-tools.ts +258 -0
- package/packages/workspace-executor/src/session-ident.ts +37 -0
- package/packages/workspace-executor/src/shell-platform.ts +11 -0
- package/packages/workspace-executor/src/tools.ts +28 -0
- package/plugins/package.json +8 -0
- package/plugins/ragents.activity/server/index.ts +9 -0
- package/plugins/ragents.activity/web/ActivityHeader.tsx +58 -0
- package/plugins/ragents.activity/web/activity.ts +144 -0
- package/plugins/ragents.activity/web/index.tsx +13 -0
- package/plugins/ragents.actor-programs/client-ui/DataTable.tsx +100 -0
- package/plugins/ragents.actor-programs/client-ui/FilePicker.tsx +65 -0
- package/plugins/ragents.actor-programs/client-ui/FlowDiagram.tsx +234 -0
- package/plugins/ragents.actor-programs/client-ui/FlowDiagramRenderer.tsx +85 -0
- package/plugins/ragents.actor-programs/client-ui/Form.tsx +126 -0
- package/plugins/ragents.actor-programs/client-ui/Layout.tsx +27 -0
- package/plugins/ragents.actor-programs/client-ui/MessageList.tsx +30 -0
- package/plugins/ragents.actor-programs/client-ui/Viewers.tsx +41 -0
- package/plugins/ragents.actor-programs/client-ui/WorkflowDiagram.tsx +14 -0
- package/plugins/ragents.actor-programs/client-ui/contracts.d.ts +84 -0
- package/plugins/ragents.actor-programs/client-ui/file-contracts.d.ts +19 -0
- package/plugins/ragents.actor-programs/client-ui/file-selection.ts +24 -0
- package/plugins/ragents.actor-programs/client-ui/flow-diagram-contracts.d.ts +27 -0
- package/plugins/ragents.actor-programs/client-ui/flow-diagram.css +23 -0
- package/plugins/ragents.actor-programs/client-ui/form-contracts.d.ts +38 -0
- package/plugins/ragents.actor-programs/client-ui/frame-layout.ts +4 -0
- package/plugins/ragents.actor-programs/client-ui/index.tsx +81 -0
- package/plugins/ragents.actor-programs/client-ui/layout-contracts.d.ts +33 -0
- package/plugins/ragents.actor-programs/client-ui/message-list-contracts.d.ts +33 -0
- package/plugins/ragents.actor-programs/client-ui/table-contracts.d.ts +35 -0
- package/plugins/ragents.actor-programs/client-ui/viewer-contracts.d.ts +37 -0
- package/plugins/ragents.actor-programs/client-ui/workflow-diagram-contracts.d.ts +10 -0
- package/plugins/ragents.actor-programs/contract.ts +180 -0
- package/plugins/ragents.actor-programs/parameter-types.ts +3 -0
- package/plugins/ragents.actor-programs/prompt.hbs +79 -0
- package/plugins/ragents.actor-programs/server/agent-tools.ts +31 -0
- package/plugins/ragents.actor-programs/server/app-project.ts +284 -0
- package/plugins/ragents.actor-programs/server/authoring-contracts.ts +10 -0
- package/plugins/ragents.actor-programs/server/client-compiler.ts +174 -0
- package/plugins/ragents.actor-programs/server/client-contracts.ts +187 -0
- package/plugins/ragents.actor-programs/server/client-runtime.ts +16 -0
- package/plugins/ragents.actor-programs/server/controls-template.ts +118 -0
- package/plugins/ragents.actor-programs/server/controls-tool.ts +48 -0
- package/plugins/ragents.actor-programs/server/index.ts +51 -0
- package/plugins/ragents.actor-programs/server/methods.ts +72 -0
- package/plugins/ragents.actor-programs/server/project-diagnostics.ts +138 -0
- package/plugins/ragents.actor-programs/server/prompts.ts +21 -0
- package/plugins/ragents.actor-programs/server/routes.ts +235 -0
- package/plugins/ragents.actor-programs/server/runtime-libraries.ts +4 -0
- package/plugins/ragents.actor-programs/server/runtime.ts +721 -0
- package/plugins/ragents.actor-programs/server/tailwind.ts +22 -0
- package/plugins/ragents.actor-programs/server/templates.ts +400 -0
- package/plugins/ragents.actor-programs/server/tool-contributor.ts +29 -0
- package/plugins/ragents.actor-programs/summary.hbs +17 -0
- package/plugins/ragents.actor-programs/web/ActorViewFrame.tsx +463 -0
- package/plugins/ragents.actor-programs/web/AppsPanel.tsx +436 -0
- package/plugins/ragents.actor-programs/web/EmbeddedApps.tsx +116 -0
- package/plugins/ragents.actor-programs/web/ExpandIcon.tsx +5 -0
- package/plugins/ragents.actor-programs/web/FullscreenHost.tsx +31 -0
- package/plugins/ragents.actor-programs/web/FunctionForm.tsx +102 -0
- package/plugins/ragents.actor-programs/web/ProgramSource.tsx +81 -0
- package/plugins/ragents.actor-programs/web/api.ts +353 -0
- package/plugins/ragents.actor-programs/web/bridge.ts +122 -0
- package/plugins/ragents.actor-programs/web/chat-state.ts +37 -0
- package/plugins/ragents.actor-programs/web/context.ts +30 -0
- package/plugins/ragents.actor-programs/web/function-call.ts +28 -0
- package/plugins/ragents.actor-programs/web/function-input.ts +40 -0
- package/plugins/ragents.actor-programs/web/index.tsx +96 -0
- package/plugins/ragents.actor-programs/web/invocations.ts +43 -0
- package/plugins/ragents.actor-programs/web/program-state.ts +68 -0
- package/plugins/ragents.actor-programs/web/state-revision.ts +16 -0
- package/plugins/ragents.actor-programs/workflow/index.ts +202 -0
- package/plugins/ragents.actor-programs/workflow/prompt-reader.ts +15 -0
- package/plugins/ragents.ask/ask.hbs +4 -0
- package/plugins/ragents.ask/contract.ts +17 -0
- package/plugins/ragents.ask/server/answer-method.ts +15 -0
- package/plugins/ragents.ask/server/ask-service.ts +152 -0
- package/plugins/ragents.ask/server/ask-tool.ts +39 -0
- package/plugins/ragents.ask/server/contract.ts +22 -0
- package/plugins/ragents.ask/server/index.ts +26 -0
- package/plugins/ragents.ask/server/tool-contributor.ts +11 -0
- package/plugins/ragents.ask/web/QuestionSection.tsx +47 -0
- package/plugins/ragents.ask/web/api.ts +6 -0
- package/plugins/ragents.ask/web/constants.ts +1 -0
- package/plugins/ragents.ask/web/index.tsx +50 -0
- package/plugins/ragents.browser/provision.ts +48 -0
- package/plugins/ragents.browser/server/browser.ts +393 -0
- package/plugins/ragents.browser/server/contract.ts +36 -0
- package/plugins/ragents.browser/server/index.ts +35 -0
- package/plugins/ragents.browser/server/tools.ts +197 -0
- package/plugins/ragents.browser/skills/browser-testing/SKILL.md +36 -0
- package/plugins/ragents.documents/contract.ts +33 -0
- package/plugins/ragents.documents/prompt.hbs +18 -0
- package/plugins/ragents.documents/server/config.ts +14 -0
- package/plugins/ragents.documents/server/document-write-tool.ts +45 -0
- package/plugins/ragents.documents/server/files-route.ts +137 -0
- package/plugins/ragents.documents/server/index.ts +38 -0
- package/plugins/ragents.documents/server/show-document-tool.ts +73 -0
- package/plugins/ragents.documents/server/store.ts +35 -0
- package/plugins/ragents.documents/server/tool-contributor.ts +16 -0
- package/plugins/ragents.documents/web/DocumentViewer.tsx +450 -0
- package/plugins/ragents.documents/web/api.ts +8 -0
- package/plugins/ragents.documents/web/index.tsx +279 -0
- package/plugins/ragents.lsp-fsharp/provision.ts +74 -0
- package/plugins/ragents.lsp-fsharp/server/index.ts +16 -0
- package/plugins/ragents.lsp-fsharp/web/index.tsx +7 -0
- package/plugins/ragents.lsp-roslyn/provision.ts +54 -0
- package/plugins/ragents.lsp-roslyn/server/index.ts +15 -0
- package/plugins/ragents.lsp-roslyn/web/api.ts +10 -0
- package/plugins/ragents.lsp-roslyn/web/index.tsx +7 -0
- package/plugins/ragents.lsp-roslyn/web/language-server-plugin.tsx +236 -0
- package/plugins/ragents.lsp-typescript/server/index.ts +7 -0
- package/plugins/ragents.lsp-typescript/web/index.tsx +7 -0
- package/plugins/ragents.model-relay/server/config.ts +37 -0
- package/plugins/ragents.model-relay/server/index.ts +31 -0
- package/plugins/ragents.model-relay/server/relay.ts +213 -0
- package/plugins/ragents.orchestration/canvas.hbs +50 -0
- package/plugins/ragents.orchestration/contract.ts +322 -0
- package/plugins/ragents.orchestration/orchestration.hbs +105 -0
- package/plugins/ragents.orchestration/server/canvas-tool.ts +248 -0
- package/plugins/ragents.orchestration/server/index.ts +64 -0
- package/plugins/ragents.orchestration/server/run-stop-tool.ts +30 -0
- package/plugins/ragents.orchestration/tiled-layout.ts +47 -0
- package/plugins/ragents.orchestration/web/ActorCanvasControls.tsx +159 -0
- package/plugins/ragents.orchestration/web/ActorChat.tsx +56 -0
- package/plugins/ragents.orchestration/web/ActorChatControls.tsx +64 -0
- package/plugins/ragents.orchestration/web/ActorChatPreview.tsx +36 -0
- package/plugins/ragents.orchestration/web/ActorNet.tsx +607 -0
- package/plugins/ragents.orchestration/web/ActorPopout.tsx +36 -0
- package/plugins/ragents.orchestration/web/ActorShortcut.tsx +76 -0
- package/plugins/ragents.orchestration/web/ActorTile.tsx +22 -0
- package/plugins/ragents.orchestration/web/CanvasStartup.tsx +14 -0
- package/plugins/ragents.orchestration/web/CanvasTiles.tsx +47 -0
- package/plugins/ragents.orchestration/web/CardSizeSettings.tsx +42 -0
- package/plugins/ragents.orchestration/web/Center.tsx +576 -0
- package/plugins/ragents.orchestration/web/DocumentsSection.tsx +37 -0
- package/plugins/ragents.orchestration/web/ExecutionsPanel.tsx +109 -0
- package/plugins/ragents.orchestration/web/FlowInspector.tsx +932 -0
- package/plugins/ragents.orchestration/web/JournalStatus.tsx +87 -0
- package/plugins/ragents.orchestration/web/MaterialBody.tsx +104 -0
- package/plugins/ragents.orchestration/web/ScriptActorCard.tsx +56 -0
- package/plugins/ragents.orchestration/web/StopRunButton.tsx +52 -0
- package/plugins/ragents.orchestration/web/TiledCanvas.tsx +281 -0
- package/plugins/ragents.orchestration/web/ZoomSettings.tsx +38 -0
- package/plugins/ragents.orchestration/web/actor-conversation.ts +64 -0
- package/plugins/ragents.orchestration/web/actor-header-settings.ts +41 -0
- package/plugins/ragents.orchestration/web/api.ts +33 -0
- package/plugins/ragents.orchestration/web/canvas-layout-storage.ts +39 -0
- package/plugins/ragents.orchestration/web/canvas-layout.ts +326 -0
- package/plugins/ragents.orchestration/web/canvas-scene.ts +311 -0
- package/plugins/ragents.orchestration/web/canvas-stage.ts +21 -0
- package/plugins/ragents.orchestration/web/canvas-startup.ts +36 -0
- package/plugins/ragents.orchestration/web/canvas-view-settings.ts +48 -0
- package/plugins/ragents.orchestration/web/card-size-settings.ts +36 -0
- package/plugins/ragents.orchestration/web/column/AddresseeControl.tsx +116 -0
- package/plugins/ragents.orchestration/web/column/ColumnSettings.tsx +50 -0
- package/plugins/ragents.orchestration/web/column/RunColumn.tsx +370 -0
- package/plugins/ragents.orchestration/web/column/column-actors.ts +38 -0
- package/plugins/ragents.orchestration/web/column/column-settings.ts +47 -0
- package/plugins/ragents.orchestration/web/column/column-state.ts +59 -0
- package/plugins/ragents.orchestration/web/column/sheet-status.ts +30 -0
- package/plugins/ragents.orchestration/web/constants.ts +10 -0
- package/plugins/ragents.orchestration/web/contract.ts +25 -0
- package/plugins/ragents.orchestration/web/executions.ts +124 -0
- package/plugins/ragents.orchestration/web/format.ts +4 -0
- package/plugins/ragents.orchestration/web/index.tsx +182 -0
- package/plugins/ragents.orchestration/web/keyboard-navigation.ts +55 -0
- package/plugins/ragents.orchestration/web/material-layout.ts +14 -0
- package/plugins/ragents.orchestration/web/run-view.ts +199 -0
- package/plugins/ragents.orchestration/web/tile-docking.ts +99 -0
- package/plugins/ragents.orchestration/web/tiled-view-settings.ts +76 -0
- package/plugins/ragents.orchestration/web/useCanvasMeasurements.ts +78 -0
- package/plugins/ragents.orchestration/web/zoom-settings.ts +28 -0
- package/plugins/ragents.overseer/contract.ts +165 -0
- package/plugins/ragents.overseer/server/api.ts +82 -0
- package/plugins/ragents.overseer/server/coordinator-prompt.ts +13 -0
- package/plugins/ragents.overseer/server/index.ts +71 -0
- package/plugins/ragents.overseer/server/orientation.ts +33 -0
- package/plugins/ragents.overseer/server/quick-answer.ts +54 -0
- package/plugins/ragents.overseer/server/reset-method.ts +5 -0
- package/plugins/ragents.overseer/server/run-directory.ts +49 -0
- package/plugins/ragents.overseer/server/settings-method.ts +8 -0
- package/plugins/ragents.overseer/server/settings.ts +83 -0
- package/plugins/ragents.overseer/server/user-location.ts +96 -0
- package/plugins/ragents.overseer/web/ModelSettings.tsx +70 -0
- package/plugins/ragents.overseer/web/chat-display.ts +10 -0
- package/plugins/ragents.overseer/web/index.tsx +208 -0
- package/plugins/ragents.overseer/web/model-settings.ts +61 -0
- package/plugins/ragents.overseer/web/quick-answers.ts +64 -0
- package/plugins/ragents.processes/contract.ts +61 -0
- package/plugins/ragents.processes/server/index.ts +36 -0
- package/plugins/ragents.processes/server/methods.ts +39 -0
- package/plugins/ragents.processes/server/observer.ts +179 -0
- package/plugins/ragents.processes/server/process-table.ts +395 -0
- package/plugins/ragents.processes/server/snapshot.ts +63 -0
- package/plugins/ragents.processes/server/terminator.ts +164 -0
- package/plugins/ragents.processes/web/ProcessHeader.tsx +157 -0
- package/plugins/ragents.processes/web/index.tsx +23 -0
- package/plugins/ragents.processes/web/processes.ts +75 -0
- package/plugins/ragents.product/model-settings-contract.ts +10 -0
- package/plugins/ragents.product/preamble.hbs +9 -0
- package/plugins/ragents.product/server/config.ts +73 -0
- package/plugins/ragents.product/server/index.ts +117 -0
- package/plugins/ragents.product/server/relay.ts +118 -0
- package/plugins/ragents.product/server/runtime.ts +30 -0
- package/plugins/ragents.product/web/ModelControl.tsx +81 -0
- package/plugins/ragents.product/web/ProductModelSettings.tsx +131 -0
- package/plugins/ragents.product/web/SystemPromptControl.tsx +136 -0
- package/plugins/ragents.product/web/index.tsx +29 -0
- package/plugins/ragents.product/web/model-settings.ts +39 -0
- package/plugins/ragents.product/web/start-options.tsx +12 -0
- package/plugins/ragents.profile-distribution/contract.ts +38 -0
- package/plugins/ragents.profile-distribution/server/archive.ts +159 -0
- package/plugins/ragents.profile-distribution/server/config.ts +27 -0
- package/plugins/ragents.profile-distribution/server/index.ts +93 -0
- package/plugins/ragents.profile-distribution/server/web.ts +48 -0
- package/plugins/ragents.reference/examples.ts +33 -0
- package/plugins/ragents.reference/run-scripts/balcony-wizard/RUN.md +27 -0
- package/plugins/ragents.reference/run-scripts/balcony-wizard/actors/balcony-app/package.json +10 -0
- package/plugins/ragents.reference/run-scripts/balcony-wizard/actors/balcony-app/src/client.tsx +80 -0
- package/plugins/ragents.reference/run-scripts/balcony-wizard/actors/balcony-app/src/conversation.ts +82 -0
- package/plugins/ragents.reference/run-scripts/balcony-wizard/actors/balcony-app/tests/conversation.test.ts +154 -0
- package/plugins/ragents.reference/run-scripts/balcony-wizard/package.json +9 -0
- package/plugins/ragents.reference/run-scripts/balcony-wizard/src/server.ts +32 -0
- package/plugins/ragents.reference/run-scripts/balcony-wizard/tests/program.test.ts +59 -0
- package/plugins/ragents.reference/run-scripts/conversation-circle/RUN.md +14 -0
- package/plugins/ragents.reference/run-scripts/conversation-circle/package.json +9 -0
- package/plugins/ragents.reference/run-scripts/conversation-circle/src/server.ts +87 -0
- package/plugins/ragents.reference/run-scripts/conversation-circle/tests/helpers.ts +26 -0
- package/plugins/ragents.reference/run-scripts/conversation-circle/tests/program.test.ts +32 -0
- package/plugins/ragents.reference/run-scripts/learning-afternoon/RUN.md +24 -0
- package/plugins/ragents.reference/run-scripts/learning-afternoon/package.json +10 -0
- package/plugins/ragents.reference/run-scripts/learning-afternoon/prompts/experiment.md +1 -0
- package/plugins/ragents.reference/run-scripts/learning-afternoon/prompts/helper.md +5 -0
- package/plugins/ragents.reference/run-scripts/learning-afternoon/prompts/quiz.md +1 -0
- package/plugins/ragents.reference/run-scripts/learning-afternoon/src/client.tsx +27 -0
- package/plugins/ragents.reference/run-scripts/learning-afternoon/src/server.ts +127 -0
- package/plugins/ragents.reference/run-scripts/learning-afternoon/src/state.ts +38 -0
- package/plugins/ragents.reference/run-scripts/learning-afternoon/src/view.tsx +42 -0
- package/plugins/ragents.reference/run-scripts/learning-afternoon/src/workflow.ts +38 -0
- package/plugins/ragents.reference/run-scripts/learning-afternoon/tests/program.test.ts +223 -0
- package/plugins/ragents.reference/run-scripts/moderated-round/RUN.md +12 -0
- package/plugins/ragents.reference/run-scripts/moderated-round/package.json +9 -0
- package/plugins/ragents.reference/run-scripts/moderated-round/src/server.ts +60 -0
- package/plugins/ragents.reference/run-scripts/moderated-round/tests/helpers.ts +26 -0
- package/plugins/ragents.reference/run-scripts/moderated-round/tests/program.test.ts +24 -0
- package/plugins/ragents.reference/run-scripts/shared-actor-list/RUN.md +18 -0
- package/plugins/ragents.reference/run-scripts/shared-actor-list/actors/shared-list/package.json +16 -0
- package/plugins/ragents.reference/run-scripts/shared-actor-list/actors/shared-list/src/client.tsx +39 -0
- package/plugins/ragents.reference/run-scripts/shared-actor-list/actors/shared-list/src/contract.ts +15 -0
- package/plugins/ragents.reference/run-scripts/shared-actor-list/actors/shared-list/src/server.ts +14 -0
- package/plugins/ragents.reference/run-scripts/shared-actor-list/actors/shared-list/tests/program.test.ts +13 -0
- package/plugins/ragents.reference/run-scripts/shared-actor-list/package.json +9 -0
- package/plugins/ragents.reference/run-scripts/shared-actor-list/src/server.ts +65 -0
- package/plugins/ragents.reference/run-scripts/shared-actor-list/tests/helpers.ts +26 -0
- package/plugins/ragents.reference/run-scripts/shared-actor-list/tests/program.test.ts +42 -0
- package/plugins/ragents.reference/run-scripts/word-game/RUN.md +25 -0
- package/plugins/ragents.reference/run-scripts/word-game/package.json +11 -0
- package/plugins/ragents.reference/run-scripts/word-game/src/client.tsx +27 -0
- package/plugins/ragents.reference/run-scripts/word-game/src/contract.ts +23 -0
- package/plugins/ragents.reference/run-scripts/word-game/src/server.ts +106 -0
- package/plugins/ragents.reference/run-scripts/word-game/src/state.ts +22 -0
- package/plugins/ragents.reference/run-scripts/word-game/src/view.tsx +54 -0
- package/plugins/ragents.reference/run-scripts/word-game/tests/program.test.ts +253 -0
- package/plugins/ragents.reference/server/index.ts +12 -0
- package/plugins/ragents.reference/skills/100-shared-actor-list/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/110-all-card-slots/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/120-canvas-conversation-circle/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/130-canvas-pipeline-with-approval/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/140-canvas-team-tree-and-topic-grid/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/150-editorial-workbench/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/160-learning-companion/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/170-photo-collection/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/180-decision-workbench/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/190-review-queue/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/20-circle-of-four/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/200-typescript-diagnostics/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/210-moderator-handover/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/220-actor-approval-list/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/230-shared-state-views/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/240-live-result-list/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/250-balcony-wizard/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/30-llm-without-runtime-knowledge/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/35-actor-input-fifo/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/40-subscription-matrix/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/50-subscription-removal/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/60-stop-in-the-circle/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/65-artifact-least-privilege/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/70-headless-counter/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/75-lsp-demo/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/80-actor-text-analysis/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/90-actor-notes/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/95-hello-world/SKILL.md +12 -0
- package/plugins/ragents.reference/skills/decision-brief/SKILL.md +33 -0
- package/plugins/ragents.reference/skills/learning-sprint/SKILL.md +33 -0
- package/plugins/ragents.reference/walkthroughs.ts +219 -0
- package/plugins/ragents.reference/web/StartGuides.tsx +89 -0
- package/plugins/ragents.reference/web/index.tsx +10 -0
- package/plugins/ragents.todo/contract.ts +60 -0
- package/plugins/ragents.todo/server/index.ts +10 -0
- package/plugins/ragents.todo/server/todo-tool.ts +70 -0
- package/plugins/ragents.todo/server/tool-contributor.ts +9 -0
- package/plugins/ragents.todo/web/TodoSection.tsx +47 -0
- package/plugins/ragents.todo/web/index.ts +12 -0
- package/plugins/ragents.transcript/server/index.ts +20 -0
- package/plugins/ragents.transcript/server/transcript.ts +78 -0
- package/plugins/ragents.watch/contract.ts +48 -0
- package/plugins/ragents.watch/server/condition.ts +56 -0
- package/plugins/ragents.watch/server/contract.ts +4 -0
- package/plugins/ragents.watch/server/functions.ts +62 -0
- package/plugins/ragents.watch/server/index.ts +39 -0
- package/plugins/ragents.watch/server/observation.ts +69 -0
- package/plugins/ragents.watch/server/service.ts +294 -0
- package/plugins/ragents.workspace/client/transport.ts +13 -0
- package/plugins/ragents.workspace/client/workspace-client.ts +247 -0
- package/plugins/ragents.workspace/contract.ts +182 -0
- package/plugins/ragents.workspace/prompt.hbs +14 -0
- package/plugins/ragents.workspace/server/binding.ts +92 -0
- package/plugins/ragents.workspace/server/browse-route.ts +134 -0
- package/plugins/ragents.workspace/server/clients.ts +161 -0
- package/plugins/ragents.workspace/server/index.ts +91 -0
- package/plugins/ragents.workspace/server/runtime.ts +170 -0
- package/plugins/ragents.workspace/web/FileBrowser.tsx +271 -0
- package/plugins/ragents.workspace/web/WorkspaceBinding.tsx +216 -0
- package/plugins/ragents.workspace/web/api.ts +8 -0
- package/plugins/ragents.workspace/web/file-icons.tsx +94 -0
- package/plugins/ragents.workspace/web/index.tsx +37 -0
- package/ragents.config.core.ts +65 -0
- package/ragents.config.developer.ts +46 -0
- package/scripts/agent/agent-cli.ts +461 -0
- package/scripts/agent/journal.ts +125 -0
- package/scripts/package/build-package.ts +249 -0
- package/scripts/package/host-links.d.mts +1 -0
- package/scripts/package/host-links.mjs +39 -0
- package/scripts/package/publish-package.ts +129 -0
- package/scripts/package/ragents.mjs +59 -0
- package/scripts/provision/run-provision.ts +72 -0
- package/scripts/remote/connect.ts +265 -0
- package/scripts/remote/start.ts +91 -0
- package/scripts/workspace-client/run-workspace-client.ts +112 -0
|
@@ -0,0 +1,1184 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
3
|
+
import type { InlineExtension } from "@aicontainer/agent";
|
|
4
|
+
import { Value } from "typebox/value";
|
|
5
|
+
import { canStartEntry, defaultHttpRights, unrestrictedAccess, type AccessContext } from "./access.ts";
|
|
6
|
+
import { assertJsonValue, type JsonValue } from "./domain/json.ts";
|
|
7
|
+
import { canonicalHash } from "./runtime/canonical-hash.ts";
|
|
8
|
+
import { schemaComplaints } from "./agents/toolset.ts";
|
|
9
|
+
import type { AgentProfile, CatalogModel } from "./agents/catalog.ts";
|
|
10
|
+
import type { ToolContributor } from "./agents/plugins.ts";
|
|
11
|
+
import { describeToolAvailability, type RunFunction } from "./agents/tools.ts";
|
|
12
|
+
import type { ChannelContribution, ChannelDescriptor, MethodContribution, MethodDescriptor } from "./rpc/contribution.ts";
|
|
13
|
+
import type {
|
|
14
|
+
AgentAudience,
|
|
15
|
+
HttpRouteContribution,
|
|
16
|
+
OperationContext,
|
|
17
|
+
OperationContribution,
|
|
18
|
+
RegisteredOperationDescriptor,
|
|
19
|
+
AgentContribution,
|
|
20
|
+
AgentContributionContext,
|
|
21
|
+
AgentToolDescriptor,
|
|
22
|
+
PluginConfigDescriptor,
|
|
23
|
+
PluginManifest,
|
|
24
|
+
PluginRegistration,
|
|
25
|
+
PluginStorage,
|
|
26
|
+
PluginStorageModes,
|
|
27
|
+
ProductDescriptor,
|
|
28
|
+
ModelProviderRegistration,
|
|
29
|
+
ProfileContribution,
|
|
30
|
+
PromptContribution,
|
|
31
|
+
PromptRenderContext,
|
|
32
|
+
PublicAgentExtensionContribution,
|
|
33
|
+
PublicPluginConfigDescriptor,
|
|
34
|
+
PublicPluginManifest,
|
|
35
|
+
PublicPluginProfile,
|
|
36
|
+
PublicPromptContribution,
|
|
37
|
+
PublicStartEntry,
|
|
38
|
+
PublicPromptSnapshot,
|
|
39
|
+
PublicSkillContribution,
|
|
40
|
+
PublicToolDescriptor,
|
|
41
|
+
RAgentsPlugin,
|
|
42
|
+
ServiceToken,
|
|
43
|
+
RegisteredStartOption,
|
|
44
|
+
SessionLifecycleContribution,
|
|
45
|
+
SessionMetadataContribution,
|
|
46
|
+
SkillContribution,
|
|
47
|
+
RunScriptPackage,
|
|
48
|
+
StartEntryContribution,
|
|
49
|
+
StartOptionContext,
|
|
50
|
+
StartOptionContribution,
|
|
51
|
+
ScriptContribution,
|
|
52
|
+
ScriptFactoryContext,
|
|
53
|
+
ScriptRuntime,
|
|
54
|
+
} from "./plugin-types.ts";
|
|
55
|
+
|
|
56
|
+
const PLUGIN_ID = /^[a-z0-9]+(?:[.-][a-z0-9]+)*$/;
|
|
57
|
+
const OPERATION_ID = /^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/;
|
|
58
|
+
const START_OPTION_ID = /^[a-z0-9]+(?:[.-][a-z0-9]+)*$/;
|
|
59
|
+
const RUN_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
60
|
+
const DEFAULT_PLUGIN_STOP_TIMEOUT_MS = 15_000;
|
|
61
|
+
|
|
62
|
+
type Owned<T> = { owner: string; value: T };
|
|
63
|
+
|
|
64
|
+
class ContributionRegistry<T extends { id: string }> {
|
|
65
|
+
readonly #kind: string;
|
|
66
|
+
readonly #entries: Owned<T>[] = [];
|
|
67
|
+
|
|
68
|
+
constructor(kind: string) {
|
|
69
|
+
this.#kind = kind;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
register(owner: string, values: readonly T[]): void {
|
|
73
|
+
for (const value of values) {
|
|
74
|
+
const existing = this.#entries.find((entry) => entry.value.id === value.id);
|
|
75
|
+
if (existing) {
|
|
76
|
+
throw new Error(`${this.#kind} ${value.id} wird bereits von ${existing.owner} bereitgestellt`);
|
|
77
|
+
}
|
|
78
|
+
this.#entries.push({ owner, value });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
entries(): readonly Owned<T>[] {
|
|
83
|
+
return this.#entries;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export class MethodContributionRegistry {
|
|
88
|
+
readonly #methods = new ContributionRegistry<{ id: string; contribution: MethodContribution }>("Methode");
|
|
89
|
+
|
|
90
|
+
register(owner: string, contributions: readonly MethodContribution[]): void {
|
|
91
|
+
this.#methods.register(owner, contributions.map((contribution) => ({ id: contribution.contract.id, contribution })));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
find(id: string): { owner: string; contribution: MethodContribution } | undefined {
|
|
95
|
+
const found = this.#methods.entries().find(({ value }) => value.id === id);
|
|
96
|
+
return found ? { owner: found.owner, contribution: found.value.contribution } : undefined;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
describe(): readonly MethodDescriptor[] {
|
|
100
|
+
return this.#methods.entries().map(({ owner, value }) => {
|
|
101
|
+
const { id, description, rights, input, result, implementedBy } = value.contribution.contract;
|
|
102
|
+
return Object.freeze({ owner, id, description, rights, input, result, implementedBy });
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export class ChannelContributionRegistry {
|
|
108
|
+
readonly #channels = new ContributionRegistry<{ id: string; contribution: ChannelContribution }>("Kanal");
|
|
109
|
+
|
|
110
|
+
register(owner: string, contributions: readonly ChannelContribution[]): void {
|
|
111
|
+
this.#channels.register(owner, contributions.map((contribution) => ({ id: contribution.contract.id, contribution })));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
find(id: string): { owner: string; contribution: ChannelContribution } | undefined {
|
|
115
|
+
const found = this.#channels.entries().find(({ value }) => value.id === id);
|
|
116
|
+
return found ? { owner: found.owner, contribution: found.value.contribution } : undefined;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
describe(): readonly ChannelDescriptor[] {
|
|
120
|
+
return this.#channels.entries().map(({ owner, value }) => {
|
|
121
|
+
const { id, description, rights, params, message } = value.contribution.contract;
|
|
122
|
+
return Object.freeze({ owner, id, description, rights, params, message });
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export class HttpContributionRegistry {
|
|
128
|
+
readonly #routes = new ContributionRegistry<HttpRouteContribution>("HTTP-Route");
|
|
129
|
+
|
|
130
|
+
register(owner: string, routes: readonly HttpRouteContribution[]): void {
|
|
131
|
+
this.#routes.register(owner, routes);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
isApiPath(pathname: string): boolean {
|
|
135
|
+
return this.#routes.entries().some(({ value }) => value.isApiPath(pathname));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async dispatch(request: IncomingMessage, response: ServerResponse, url: URL, access: AccessContext = unrestrictedAccess): Promise<boolean> {
|
|
139
|
+
const route = this.#routes.entries().find(({ value }) => value.matches(request, url));
|
|
140
|
+
if (!route) return false;
|
|
141
|
+
const policy = route.value.requiredRights;
|
|
142
|
+
const rights = typeof policy === "function" ? policy(request, url) : policy ?? defaultHttpRights(request.method);
|
|
143
|
+
const missing = rights.find((right) => !access.can(right));
|
|
144
|
+
if (missing) {
|
|
145
|
+
response.writeHead(403, { "Content-Type": "application/json", "Cache-Control": "no-store" });
|
|
146
|
+
response.end(JSON.stringify({ error: `Das Recht ${missing} fehlt.`, code: "access-denied", right: missing }));
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
await route.value.handle({ request, response, url, access });
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export class OperationContributionRegistry {
|
|
155
|
+
readonly #operations = new ContributionRegistry<OperationContribution>("Operation");
|
|
156
|
+
|
|
157
|
+
register(owner: string, operations: readonly OperationContribution[]): void {
|
|
158
|
+
for (const operation of operations) {
|
|
159
|
+
if (!OPERATION_ID.test(operation.id)) throw new Error(`Ungültige Operation-Id: ${operation.id}`);
|
|
160
|
+
if (!operation.label.trim()) throw new Error(`Operation ${operation.id} hat kein Label`);
|
|
161
|
+
if (!operation.description.trim()) throw new Error(`Operation ${operation.id} hat keine Beschreibung`);
|
|
162
|
+
if (operation.operator !== "direct" && operation.operator !== "confirm" && operation.operator !== "unavailable") {
|
|
163
|
+
throw new Error(`Operation ${operation.id} hat eine ungültige Operator-Policy`);
|
|
164
|
+
}
|
|
165
|
+
if (typeof operation.execute !== "function") throw new Error(`Operation ${operation.id} hat keine Ausführung`);
|
|
166
|
+
}
|
|
167
|
+
this.#operations.register(owner, operations);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
operation(id: string): RegisteredOperationDescriptor | undefined {
|
|
171
|
+
const found = this.#operations.entries().find(({ value }) => value.id === id);
|
|
172
|
+
if (!found) return undefined;
|
|
173
|
+
const { execute: _execute, ...descriptor } = found.value;
|
|
174
|
+
return Object.freeze({ owner: found.owner, ...descriptor });
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
describe(): readonly RegisteredOperationDescriptor[] {
|
|
178
|
+
return this.#operations.entries().map(({ value, owner }) => {
|
|
179
|
+
const { execute: _execute, ...descriptor } = value;
|
|
180
|
+
return Object.freeze({ owner, ...descriptor });
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async invoke(id: string, context: OperationContext, input: unknown): Promise<JsonValue> {
|
|
185
|
+
const operation = this.#operations.entries().find(({ value }) => value.id === id)?.value;
|
|
186
|
+
if (!operation) throw new Error(`Operation ${id} ist nicht registriert`);
|
|
187
|
+
assertJsonValue(input, `Operation ${id} input`);
|
|
188
|
+
|
|
189
|
+
if (!Value.Check(operation.schema, input)) {
|
|
190
|
+
const first = [...Value.Errors(operation.schema, input)].at(0);
|
|
191
|
+
throw new Error(`Ungültige Eingabe für Operation ${id}: ${first?.message ?? "Schema nicht erfüllt"}`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (context.principal.kind === "operator") {
|
|
195
|
+
if (operation.operator === "unavailable") {
|
|
196
|
+
throw new Error(`Operation ${id} ist für den Bediener nicht verfügbar`);
|
|
197
|
+
}
|
|
198
|
+
if (operation.operator === "confirm") {
|
|
199
|
+
const confirmation = "operatorConfirmation" in context ? context.operatorConfirmation : undefined;
|
|
200
|
+
if (!confirmation
|
|
201
|
+
|| confirmation.operationId !== id
|
|
202
|
+
|| confirmation.invocationId !== context.invocationId
|
|
203
|
+
|| confirmation.inputHash !== canonicalHash(input)) {
|
|
204
|
+
throw new Error(`Operation ${id} erfordert eine an diesen Aufruf gebundene Bestätigung`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
context.signal.throwIfAborted();
|
|
210
|
+
const result = await operation.execute(context, input);
|
|
211
|
+
if (!Value.Check(operation.resultSchema, result)) {
|
|
212
|
+
const first = [...Value.Errors(operation.resultSchema, result)].at(0);
|
|
213
|
+
throw new Error(`Ungültiges Ergebnis von Operation ${id}: ${first?.message ?? "Schema nicht erfüllt"}`);
|
|
214
|
+
}
|
|
215
|
+
assertJsonValue(result, `Operation ${id} output`);
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const namedExtension = (extension: InlineExtension): string | undefined =>
|
|
221
|
+
typeof extension === "function" ? undefined : extension.name;
|
|
222
|
+
|
|
223
|
+
const extensionFactoryName = (extension: InlineExtension): string | null => {
|
|
224
|
+
if (typeof extension !== "function") return extension.name;
|
|
225
|
+
return extension.name || null;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
export class AgentContributionRegistry {
|
|
229
|
+
readonly #contributions = new ContributionRegistry<AgentContribution>("Agent-Beitrag");
|
|
230
|
+
readonly #toolOwners = new Map<string, string>();
|
|
231
|
+
|
|
232
|
+
register(owner: string, contributions: readonly AgentContribution[]): void {
|
|
233
|
+
const names = new Set<string>();
|
|
234
|
+
for (const contribution of contributions) {
|
|
235
|
+
if (contribution.tools.length > 0 && (contribution.global?.length ?? 0) === 0 && !contribution.resolve) {
|
|
236
|
+
throw new Error(`Agent-Beitrag ${contribution.id} deklariert Werkzeuge, aber keine Extension-Factory`);
|
|
237
|
+
}
|
|
238
|
+
for (const tool of contribution.tools) {
|
|
239
|
+
if (!tool.name.trim() || !tool.description.trim() || !tool.availabilityDetail.trim()) {
|
|
240
|
+
throw new Error(`Agent-Beitrag ${contribution.id} hat einen unvollständigen Werkzeug-Descriptor`);
|
|
241
|
+
}
|
|
242
|
+
if (names.has(tool.name)) {
|
|
243
|
+
throw new Error(`Agent-Werkzeug ${tool.name} ist innerhalb der Registrierung mehrfach deklariert`);
|
|
244
|
+
}
|
|
245
|
+
const existing = this.#toolOwners.get(tool.name);
|
|
246
|
+
if (existing) throw new Error(`Agent-Werkzeug ${tool.name} wird bereits von ${existing} deklariert`);
|
|
247
|
+
names.add(tool.name);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
this.#contributions.register(owner, contributions);
|
|
251
|
+
for (const name of names) this.#toolOwners.set(name, owner);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
global(): readonly InlineExtension[] {
|
|
255
|
+
return this.#unique(this.#contributions.entries().flatMap(({ value }) => value.global ?? []));
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async resolve(context: AgentContributionContext): Promise<readonly InlineExtension[]> {
|
|
259
|
+
const contextual = await Promise.all(this.#contributions.entries().map(async ({ value }) =>
|
|
260
|
+
value.resolve ? await value.resolve(context) : []));
|
|
261
|
+
return this.#unique([...this.global(), ...contextual.flat()]);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
describe(): readonly PublicAgentExtensionContribution[] {
|
|
265
|
+
return this.#contributions.entries().map(({ owner, value }) => ({
|
|
266
|
+
id: value.id,
|
|
267
|
+
owner,
|
|
268
|
+
kind: "plugin" as const,
|
|
269
|
+
factories: (value.global ?? []).map((extension) => ({
|
|
270
|
+
name: extensionFactoryName(extension),
|
|
271
|
+
scope: "global" as const,
|
|
272
|
+
})),
|
|
273
|
+
resolvesPerAgent: Boolean(value.resolve),
|
|
274
|
+
}));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
describeTools(): readonly PublicToolDescriptor[] {
|
|
278
|
+
return this.#contributions.entries().flatMap(({ owner, value }) =>
|
|
279
|
+
value.tools.map((tool) => ({
|
|
280
|
+
id: `agent-extension:${owner}:${value.id}:${tool.name}`,
|
|
281
|
+
owner,
|
|
282
|
+
source: value.id,
|
|
283
|
+
kind: "agent-extension" as const,
|
|
284
|
+
...tool,
|
|
285
|
+
nativeTool: true,
|
|
286
|
+
})));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
tools(): readonly AgentToolDescriptor[] {
|
|
290
|
+
return this.#contributions.entries().flatMap(({ value }) => value.tools);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
#unique(extensions: readonly InlineExtension[]): readonly InlineExtension[] {
|
|
294
|
+
const names = new Set<string>();
|
|
295
|
+
for (const extension of extensions) {
|
|
296
|
+
const name = namedExtension(extension);
|
|
297
|
+
if (!name) continue;
|
|
298
|
+
if (names.has(name)) throw new Error(`Agent-Extension ${name} ist mehrfach registriert`);
|
|
299
|
+
names.add(name);
|
|
300
|
+
}
|
|
301
|
+
return extensions;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export class ToolContributionRegistry {
|
|
306
|
+
readonly #contributors: Owned<ToolContributor>[] = [];
|
|
307
|
+
|
|
308
|
+
register(owner: string, contributors: readonly ToolContributor[]): void {
|
|
309
|
+
for (const contributor of contributors) {
|
|
310
|
+
const existing = this.#contributors.find((entry) => entry.value.name === contributor.name);
|
|
311
|
+
if (existing) {
|
|
312
|
+
throw new Error(`Werkzeugbeitrag ${contributor.name} wird bereits von ${existing.owner} bereitgestellt`);
|
|
313
|
+
}
|
|
314
|
+
this.#contributors.push({ owner, value: contributor });
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
registerFunctions(owner: string, functions: readonly (RunFunction | ToolContributor)[]): void {
|
|
319
|
+
for (const fn of functions) {
|
|
320
|
+
if (!("run" in fn)) {
|
|
321
|
+
this.register(owner, [fn]);
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
this.register(owner, [{
|
|
325
|
+
name: `${owner}:function:${fn.name}`,
|
|
326
|
+
descriptors: [{
|
|
327
|
+
name: fn.name,
|
|
328
|
+
description: fn.description,
|
|
329
|
+
scope: "per-turn",
|
|
330
|
+
nativeTool: fn.nativeTool === true,
|
|
331
|
+
...describeToolAvailability(fn.available),
|
|
332
|
+
}],
|
|
333
|
+
tools: () => [fn],
|
|
334
|
+
}]);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
entries(): readonly ToolContributor[] {
|
|
339
|
+
return this.#contributors.map(({ value }) => value);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
describe(): readonly PublicToolDescriptor[] {
|
|
343
|
+
return this.#contributors.flatMap(({ owner, value }) => value.descriptors.map((tool) => ({
|
|
344
|
+
id: `plugin:${owner}:${value.name}:${tool.name}`,
|
|
345
|
+
owner,
|
|
346
|
+
source: value.name,
|
|
347
|
+
kind: "plugin" as const,
|
|
348
|
+
...tool,
|
|
349
|
+
nativeTool: tool.nativeTool === true,
|
|
350
|
+
})));
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export class PromptContributionRegistry {
|
|
355
|
+
readonly #prompts = new ContributionRegistry<PromptContribution>("Prompt-Beitrag");
|
|
356
|
+
|
|
357
|
+
register(owner: string, prompts: readonly PromptContribution[]): void {
|
|
358
|
+
this.#prompts.register(owner, prompts);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
async render(context: PromptRenderContext): Promise<string> {
|
|
362
|
+
return (await this.snapshot(context)).content;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
async snapshot(context: PromptRenderContext): Promise<PublicPromptSnapshot> {
|
|
366
|
+
const contributions = await this.describe(context);
|
|
367
|
+
return {
|
|
368
|
+
content: contributions.map((entry) => entry.content).filter(Boolean).join("\n\n"),
|
|
369
|
+
contributions,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
async describe(context: PromptRenderContext, selection?: {
|
|
374
|
+
delivery: "initial" | "on-demand";
|
|
375
|
+
toolNames: readonly string[];
|
|
376
|
+
}): Promise<readonly PublicPromptContribution[]> {
|
|
377
|
+
const entries = [...this.#prompts.entries()]
|
|
378
|
+
.filter(({ value }) => !selection || (value.delivery ?? "initial") === selection.delivery
|
|
379
|
+
&& (value.requiresTools?.some((name) => selection.toolNames.includes(name)) ?? false))
|
|
380
|
+
.sort((left, right) => left.value.order - right.value.order || left.value.id.localeCompare(right.value.id));
|
|
381
|
+
return Promise.all(entries.map(async ({ owner, value }) => ({
|
|
382
|
+
id: value.id,
|
|
383
|
+
owner,
|
|
384
|
+
order: value.order,
|
|
385
|
+
delivery: value.delivery ?? "initial",
|
|
386
|
+
content: (await value.render(context)).trim(),
|
|
387
|
+
requiresTools: value.requiresTools ?? [],
|
|
388
|
+
})));
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/** Die Beiträge, die für diesen Run anders lauten als im Schnappschuss; alles andere bleibt der gerenderte Text. */
|
|
392
|
+
runOverrides(runId: string): ReadonlyMap<string, string> {
|
|
393
|
+
return new Map([...this.#prompts.entries()].flatMap(({ value }) =>
|
|
394
|
+
value.renderForRun ? [[value.id, value.renderForRun(runId).trim()] as const] : []));
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
static handlebarsContext(context: PromptRenderContext): Record<string, unknown> {
|
|
398
|
+
return {};
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export class SkillContributionRegistry {
|
|
403
|
+
readonly #skills = new ContributionRegistry<SkillContribution>("Skill-Beitrag");
|
|
404
|
+
|
|
405
|
+
register(owner: string, skills: readonly SkillContribution[]): void {
|
|
406
|
+
for (const skill of skills) {
|
|
407
|
+
const audiences = skill.audiences ?? [];
|
|
408
|
+
if (new Set(audiences).size !== audiences.length) {
|
|
409
|
+
throw new Error(`Skill-Beitrag ${skill.id} enthält eine Zielgruppe mehrfach`);
|
|
410
|
+
}
|
|
411
|
+
if (audiences.some((audience) => audience !== "coordinator" && audience !== "agent")) {
|
|
412
|
+
throw new Error(`Skill-Beitrag ${skill.id} enthält eine ungültige Zielgruppe`);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
this.#skills.register(owner, skills);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
global(): Promise<readonly string[]> {
|
|
419
|
+
return this.resolve(undefined);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
async resolve(context: AgentContributionContext | undefined): Promise<readonly string[]> {
|
|
423
|
+
const paths = (await this.describe(context)).flatMap((entry) => entry.paths);
|
|
424
|
+
const unique = new Set(paths);
|
|
425
|
+
if (unique.size !== paths.length) throw new Error("Ein Agent-Skill-Pfad ist mehrfach registriert");
|
|
426
|
+
return [...unique];
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
async describe(context: AgentContributionContext | undefined): Promise<readonly PublicSkillContribution[]> {
|
|
430
|
+
const allAudiences = ["coordinator", "agent"] as const satisfies readonly AgentAudience[];
|
|
431
|
+
const entries = this.#skills.entries().filter(({ value }) =>
|
|
432
|
+
!context || !value.audiences || value.audiences.includes(context.audience));
|
|
433
|
+
return Promise.all(entries.map(async ({ owner, value }) => ({
|
|
434
|
+
id: value.id,
|
|
435
|
+
owner,
|
|
436
|
+
audiences: value.audiences ?? allAudiences,
|
|
437
|
+
paths: await value.paths(context),
|
|
438
|
+
})));
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const SKILL_NAME = /^[a-z0-9][a-z0-9-]*$/;
|
|
443
|
+
const GUIDE_ID = /^[a-z0-9][a-z0-9.-]*$/;
|
|
444
|
+
const SCRIPT_HANDLE = /^[a-z0-9][a-z0-9-]*$/;
|
|
445
|
+
|
|
446
|
+
const requireText = (entry: { id: unknown }, value: unknown, field: string): void => {
|
|
447
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
448
|
+
throw new Error(`Einstieg ${String(entry.id)} hat kein gültiges ${field}`);
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
const assertKnownFields = (entry: { id: unknown }, value: object, fields: readonly string[], label: string): void => {
|
|
453
|
+
const unknown = Object.keys(value).filter((field) => !fields.includes(field));
|
|
454
|
+
if (unknown.length > 0) {
|
|
455
|
+
throw new Error(`${label} ${String(entry.id)} enthält unbekannte Felder: ${unknown.join(", ")}`);
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
const validateProgramFiles = (entry: StartEntryContribution, files: unknown): void => {
|
|
460
|
+
if (!Array.isArray(files) || files.length === 0)
|
|
461
|
+
throw new Error(`Run-Script ${entry.id}: files braucht Paketdateien`);
|
|
462
|
+
const names = new Set<string>();
|
|
463
|
+
for (const file of files) {
|
|
464
|
+
if (typeof file !== "object" || file === null || typeof file.path !== "string" || typeof file.content !== "string")
|
|
465
|
+
throw new Error(`Run-Script ${entry.id}: jede Datei braucht path und content`);
|
|
466
|
+
assertKnownFields(entry, file, ["path", "content"], "Paketdatei");
|
|
467
|
+
if (!file.path || file.path.includes("\\") || file.path.includes("\0") || path.posix.isAbsolute(file.path)
|
|
468
|
+
|| file.path.split("/").some((part: string) => !part || part === "." || part === ".."))
|
|
469
|
+
throw new Error(`Run-Script ${entry.id}: ungültiger Paketpfad ${file.path}`);
|
|
470
|
+
if (names.has(file.path)) throw new Error(`Run-Script ${entry.id}: Datei ${file.path} ist doppelt`);
|
|
471
|
+
names.add(file.path);
|
|
472
|
+
}
|
|
473
|
+
if (!names.has("package.json")) throw new Error(`Run-Script ${entry.id}: package.json fehlt`);
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
const validateScriptPackage = (entry: StartEntryContribution, script: unknown): void => {
|
|
477
|
+
if (typeof script !== "object" || script === null)
|
|
478
|
+
throw new Error(`Einstieg ${entry.id} hat kein Run-Script-Paket`);
|
|
479
|
+
assertKnownFields(entry, script, ["handle", "coordinator", "files", "programs"], "Run-Script");
|
|
480
|
+
const value = script as Record<string, unknown>;
|
|
481
|
+
if (typeof value.handle !== "string" || !SCRIPT_HANDLE.test(value.handle))
|
|
482
|
+
throw new Error(`Run-Script ${entry.id}: handle muss ein Handle wie gespraechsrunde sein (Kleinbuchstaben, Ziffern, Bindestrich)`);
|
|
483
|
+
if (typeof value.coordinator !== "boolean")
|
|
484
|
+
throw new Error(`Run-Script ${entry.id}: coordinator muss true oder false sein`);
|
|
485
|
+
validateProgramFiles(entry, value.files);
|
|
486
|
+
if (!Array.isArray(value.programs)) throw new Error(`Run-Script ${entry.id}: programs muss eine Liste sein`);
|
|
487
|
+
const names = new Set<string>();
|
|
488
|
+
for (const program of value.programs) {
|
|
489
|
+
if (typeof program !== "object" || program === null || typeof program.name !== "string" || !SCRIPT_HANDLE.test(program.name))
|
|
490
|
+
throw new Error(`Run-Script ${entry.id}: ungültiger Programmname`);
|
|
491
|
+
assertKnownFields(entry, program, ["name", "files"], "Actor-Programm");
|
|
492
|
+
if (program.name === value.handle || names.has(program.name))
|
|
493
|
+
throw new Error(`Run-Script ${entry.id}: Programm ${program.name} ist doppelt`);
|
|
494
|
+
names.add(program.name);
|
|
495
|
+
validateProgramFiles(entry, program.files);
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
const validateStartEntry = (entry: StartEntryContribution): void => {
|
|
500
|
+
const base = ["id", "title", "description", "order", "guide", "tags", "action"];
|
|
501
|
+
for (const field of ["id", "title", "description"] as const) requireText(entry, entry[field], field);
|
|
502
|
+
if (entry.order !== undefined && (typeof entry.order !== "number" || !Number.isFinite(entry.order))) {
|
|
503
|
+
throw new Error(`Einstieg ${entry.id} hat keine gültige Ordnungszahl`);
|
|
504
|
+
}
|
|
505
|
+
if (entry.guide !== undefined && (typeof entry.guide !== "string" || !GUIDE_ID.test(entry.guide))) {
|
|
506
|
+
throw new Error(`Einstieg ${entry.id} nennt keine gültige Leitfaden-Kennung: ${String(entry.guide)}`);
|
|
507
|
+
}
|
|
508
|
+
if (entry.tags !== undefined && (!Array.isArray(entry.tags)
|
|
509
|
+
|| entry.tags.some((tag) => typeof tag !== "string" || !tag.trim() || tag !== tag.trim())
|
|
510
|
+
|| new Set(entry.tags).size !== entry.tags.length)) {
|
|
511
|
+
throw new Error(`Einstieg ${entry.id}: tags müssen eindeutige, nicht leere Schlagworte sein`);
|
|
512
|
+
}
|
|
513
|
+
switch (entry.action) {
|
|
514
|
+
case "skill":
|
|
515
|
+
assertKnownFields(entry, entry, [...base, "skill", "prompt", "category"], "Einstieg");
|
|
516
|
+
requireText(entry, entry.category, "category");
|
|
517
|
+
if (entry.category !== entry.category.trim()) throw new Error(`Einstieg ${entry.id}: category muss ein einzelner nicht leerer Text sein`);
|
|
518
|
+
requireText(entry, entry.prompt, "prompt");
|
|
519
|
+
requireText(entry, entry.skill, "skill");
|
|
520
|
+
if (!SKILL_NAME.test(entry.skill)) {
|
|
521
|
+
throw new Error(`Einstieg ${entry.id} nennt keinen gültigen Skill-Namen: ${entry.skill}`);
|
|
522
|
+
}
|
|
523
|
+
return;
|
|
524
|
+
case "script":
|
|
525
|
+
assertKnownFields(entry, entry, [...base, "script"], "Einstieg");
|
|
526
|
+
validateScriptPackage(entry, entry.script);
|
|
527
|
+
return;
|
|
528
|
+
default:
|
|
529
|
+
throw new Error(
|
|
530
|
+
`Einstieg ${String((entry as { id: unknown }).id)} hat die unbekannte Aktion ${String((entry as { action: unknown }).action)}; `
|
|
531
|
+
+ "gültig sind skill und script",
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
const byOrderThenId = (left: { order?: number; id: string }, right: { order?: number; id: string }): number =>
|
|
537
|
+
(left.order ?? 0) - (right.order ?? 0) || left.id.localeCompare(right.id);
|
|
538
|
+
|
|
539
|
+
/** Skills with a start prompt and executable run scripts share one registry. */
|
|
540
|
+
export class StartEntryContributionRegistry {
|
|
541
|
+
readonly #entries = new ContributionRegistry<StartEntryContribution>("Einstieg");
|
|
542
|
+
|
|
543
|
+
register(owner: string, entries: readonly StartEntryContribution[]): void {
|
|
544
|
+
for (const entry of entries) validateStartEntry(entry);
|
|
545
|
+
this.#entries.register(owner, entries);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
assertSkillsKnown(skills: readonly PublicSkillContribution[]): void {
|
|
549
|
+
const names = new Set(skills.flatMap((skill) =>
|
|
550
|
+
skill.paths.map((entry) => entry.split(/[\\/]/).filter(Boolean).at(-1) ?? "")));
|
|
551
|
+
for (const { owner, value } of this.#entries.entries()) {
|
|
552
|
+
if (value.action === "skill" && !names.has(value.skill)) {
|
|
553
|
+
throw new Error(`Einstieg ${value.id} von ${owner} verweist auf den unbekannten Skill ${value.skill}`);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
describe(): readonly PublicStartEntry[] {
|
|
559
|
+
return this.#entries
|
|
560
|
+
.entries()
|
|
561
|
+
.map(({ owner, value }): PublicStartEntry => {
|
|
562
|
+
const base = {
|
|
563
|
+
id: value.id,
|
|
564
|
+
owner,
|
|
565
|
+
title: value.title,
|
|
566
|
+
description: value.description,
|
|
567
|
+
...(value.order !== undefined ? { order: value.order } : {}),
|
|
568
|
+
...(value.guide !== undefined ? { guide: value.guide } : {}),
|
|
569
|
+
...(value.tags !== undefined ? { tags: [...value.tags] } : {}),
|
|
570
|
+
};
|
|
571
|
+
switch (value.action) {
|
|
572
|
+
case "skill":
|
|
573
|
+
return { ...base, action: "skill", skill: value.skill, category: value.category, prompt: value.prompt };
|
|
574
|
+
case "script":
|
|
575
|
+
return { ...base, action: "script", coordinator: value.script.coordinator };
|
|
576
|
+
}
|
|
577
|
+
})
|
|
578
|
+
.sort(byOrderThenId);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/** The run script behind a script entry; undefined for unknown ids and entries of another action. */
|
|
582
|
+
scriptPackage(entryId: string): (RunScriptPackage & { entry: PublicStartEntry }) | undefined {
|
|
583
|
+
const found = this.#entries.entries().find(({ value }) => value.id === entryId);
|
|
584
|
+
if (!found || found.value.action !== "script") return undefined;
|
|
585
|
+
const entry = this.describe().find((candidate) => candidate.id === entryId);
|
|
586
|
+
if (!entry) return undefined;
|
|
587
|
+
return { ...found.value.script, entry };
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
export class ProfileContributionRegistry {
|
|
592
|
+
readonly #profiles = new ContributionRegistry<ProfileContribution>("Profil-Beitrag");
|
|
593
|
+
|
|
594
|
+
register(owner: string, contributions: readonly ProfileContribution[]): void {
|
|
595
|
+
this.#profiles.register(owner, contributions);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
models(): readonly CatalogModel[] {
|
|
599
|
+
const models = this.#profiles.entries().flatMap(({ value }) => value.models());
|
|
600
|
+
const keys = models.map((model) => `${model.driver}:${model.provider}:${model.model}`);
|
|
601
|
+
if (new Set(keys).size !== keys.length) throw new Error("Ein Modell ist mehrfach registriert");
|
|
602
|
+
return models;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
profiles(): readonly AgentProfile[] {
|
|
606
|
+
const profiles = this.#profiles.entries().flatMap(({ value }) => value.profiles());
|
|
607
|
+
const names = profiles.map((profile) => profile.name);
|
|
608
|
+
if (new Set(names).size !== names.length) throw new Error("Ein Agentenprofil ist mehrfach registriert");
|
|
609
|
+
return profiles;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
async providers(): Promise<readonly ModelProviderRegistration[]> {
|
|
613
|
+
const registrations = (await Promise.all(this.#profiles.entries().map(({ value }) => value.providers?.() ?? []))).flat();
|
|
614
|
+
const ids = registrations.map((registration) => registration.id);
|
|
615
|
+
if (new Set(ids).size !== ids.length) throw new Error("Ein Modellanbieter ist mehrfach registriert");
|
|
616
|
+
return registrations;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
export class ScriptContributionRegistry {
|
|
621
|
+
readonly #script = new ContributionRegistry<ScriptContribution>("Logik-Beitrag");
|
|
622
|
+
|
|
623
|
+
register(owner: string, contributions: readonly ScriptContribution[]): void {
|
|
624
|
+
this.#script.register(owner, contributions);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
create(context: ScriptFactoryContext): ScriptRuntime | undefined {
|
|
628
|
+
const entries = this.#script.entries();
|
|
629
|
+
if (entries.length > 1) {
|
|
630
|
+
throw new Error(`Die Engine verträgt höchstens einen Logik-Beitrag, registriert sind ${entries.length}`);
|
|
631
|
+
}
|
|
632
|
+
return entries[0]?.value.create(context);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
type SessionStopAttempt = {
|
|
637
|
+
bounded: Promise<void>;
|
|
638
|
+
settled: Promise<void>;
|
|
639
|
+
result: PromiseSettledResult<void> | undefined;
|
|
640
|
+
timeoutError: Error | undefined;
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
type ContributionStopOperation = {
|
|
644
|
+
bounded: Promise<void>;
|
|
645
|
+
settled: Promise<void>;
|
|
646
|
+
isSettled: () => boolean;
|
|
647
|
+
release: () => void;
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
export interface PluginStopOperation {
|
|
651
|
+
bounded: Promise<void>;
|
|
652
|
+
settled: Promise<void>;
|
|
653
|
+
release: () => void;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
export class LifecycleContributionRegistry {
|
|
657
|
+
readonly #lifecycle = new ContributionRegistry<SessionLifecycleContribution>("Lifecycle-Beitrag");
|
|
658
|
+
readonly #stopTimeoutMs: number;
|
|
659
|
+
readonly #stopAttempts = new Map<string, SessionStopAttempt>();
|
|
660
|
+
|
|
661
|
+
constructor(options: { stopTimeoutMs?: number } = {}) {
|
|
662
|
+
const stopTimeoutMs = options.stopTimeoutMs ?? DEFAULT_PLUGIN_STOP_TIMEOUT_MS;
|
|
663
|
+
if (!Number.isSafeInteger(stopTimeoutMs) || stopTimeoutMs < 1) {
|
|
664
|
+
throw new Error("Die Plugin-Stopp-Zeitgrenze muss eine positive ganze Zahl sein");
|
|
665
|
+
}
|
|
666
|
+
this.#stopTimeoutMs = stopTimeoutMs;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
register(owner: string, contributions: readonly SessionLifecycleContribution[]): void {
|
|
670
|
+
this.#lifecycle.register(owner, contributions);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
async initialize(): Promise<void> {
|
|
674
|
+
for (const { value } of this.#lifecycle.entries()) await value.initialize?.();
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
async prepareSession(runId: string): Promise<void> {
|
|
678
|
+
for (const { value } of this.#lifecycle.entries()) await value.prepareSession?.({ runId });
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
beginStopSession(runId: string): PluginStopOperation {
|
|
682
|
+
return this.#beginStopPhase(runId, "stopSession");
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
beginAfterStopSession(runId: string): PluginStopOperation {
|
|
686
|
+
return this.#beginStopPhase(runId, "afterStopSession");
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
#beginStopPhase(runId: string, phase: "stopSession" | "afterStopSession"): PluginStopOperation {
|
|
690
|
+
const contributions = [...this.#lifecycle.entries()].reverse()
|
|
691
|
+
.flatMap(({ value }) => value[phase] ? [this.#beginStopContribution(value, runId, phase)] : []);
|
|
692
|
+
const bounded = this.#settleParallel("Plugin-Stopp", contributions.map(({ bounded: promise }) => promise));
|
|
693
|
+
const settled = this.#settleParallel("Plugin-Stopp-Nachlauf", contributions.map(({ settled: promise }) => promise));
|
|
694
|
+
|
|
695
|
+
return {
|
|
696
|
+
bounded,
|
|
697
|
+
settled,
|
|
698
|
+
release: () => {
|
|
699
|
+
if (contributions.some((contribution) => !contribution.isSettled())) {
|
|
700
|
+
throw new Error(`Plugin-Stopp für ${runId} kann vor dem Ende aller Beiträge nicht freigegeben werden`);
|
|
701
|
+
}
|
|
702
|
+
contributions.forEach((contribution) => contribution.release());
|
|
703
|
+
},
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
stopSession(runId: string): Promise<void> {
|
|
708
|
+
const operation = this.beginStopSession(runId);
|
|
709
|
+
void operation.settled.then(
|
|
710
|
+
() => operation.release(),
|
|
711
|
+
() => operation.release(),
|
|
712
|
+
);
|
|
713
|
+
return operation.bounded;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
async deleteSession(runId: string): Promise<void> {
|
|
717
|
+
const pendingStops = [...this.#stopAttempts.entries()]
|
|
718
|
+
.filter(([key]) => key.startsWith(`${runId}\0`))
|
|
719
|
+
.map(([, attempt]) => attempt.settled);
|
|
720
|
+
await Promise.allSettled(pendingStops);
|
|
721
|
+
await this.#settle("Plugin-Löschung", [...this.#lifecycle.entries()].reverse()
|
|
722
|
+
.map(({ value }) => () => value.deleteSession?.({ runId })));
|
|
723
|
+
this.#releaseStopAttempts(runId);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
shutdown(): Promise<void> {
|
|
727
|
+
const pendingStops = [...new Set([...this.#stopAttempts.values()].map((attempt) => attempt.settled))];
|
|
728
|
+
return this.#settle("Plugin-Shutdown", [
|
|
729
|
+
...[...this.#lifecycle.entries()].reverse().map(({ value }) => () => value.shutdown?.()),
|
|
730
|
+
...pendingStops.map((settled) => () => settled),
|
|
731
|
+
]);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
async #settleParallel(name: string, operations: readonly Promise<void>[]): Promise<void> {
|
|
735
|
+
const results = await Promise.allSettled(operations);
|
|
736
|
+
const failures = results
|
|
737
|
+
.filter((result): result is PromiseRejectedResult => result.status === "rejected")
|
|
738
|
+
.map((result) => result.reason);
|
|
739
|
+
if (failures.length > 0) throw new AggregateError(failures, `${name} ist in ${failures.length} Plugin(s) fehlgeschlagen`);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
#beginStopContribution(
|
|
743
|
+
contribution: SessionLifecycleContribution,
|
|
744
|
+
runId: string,
|
|
745
|
+
phase: "stopSession" | "afterStopSession",
|
|
746
|
+
): ContributionStopOperation {
|
|
747
|
+
const stopSession = contribution[phase];
|
|
748
|
+
if (!stopSession) throw new Error(`Lifecycle-Beitrag ${contribution.id} hat keinen Stopp-Hook`);
|
|
749
|
+
const key = `${runId}\0${phase}\0${contribution.id}`;
|
|
750
|
+
const existing = this.#stopAttempts.get(key);
|
|
751
|
+
if (existing) {
|
|
752
|
+
return this.#contributionStopOperation(key, existing);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
const controller = new AbortController();
|
|
756
|
+
const attempt: SessionStopAttempt = {
|
|
757
|
+
bounded: Promise.resolve(),
|
|
758
|
+
settled: Promise.resolve(),
|
|
759
|
+
result: undefined,
|
|
760
|
+
timeoutError: undefined,
|
|
761
|
+
};
|
|
762
|
+
attempt.settled = Promise.resolve().then(() => stopSession({ runId, signal: controller.signal }));
|
|
763
|
+
void attempt.settled.then(
|
|
764
|
+
() => {
|
|
765
|
+
attempt.result = { status: "fulfilled", value: undefined };
|
|
766
|
+
},
|
|
767
|
+
(reason) => {
|
|
768
|
+
attempt.result = { status: "rejected", reason };
|
|
769
|
+
},
|
|
770
|
+
);
|
|
771
|
+
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
772
|
+
const deadline = new Promise<never>((_, reject) => {
|
|
773
|
+
timeout = setTimeout(() => {
|
|
774
|
+
const error = new Error(
|
|
775
|
+
`Plugin-Stopp ${contribution.id} (${phase}) hat die Zeitgrenze von ${this.#stopTimeoutMs} ms überschritten`,
|
|
776
|
+
);
|
|
777
|
+
attempt.timeoutError = error;
|
|
778
|
+
controller.abort(error);
|
|
779
|
+
reject(error);
|
|
780
|
+
}, this.#stopTimeoutMs);
|
|
781
|
+
});
|
|
782
|
+
attempt.bounded = Promise.race([attempt.settled, deadline]);
|
|
783
|
+
this.#stopAttempts.set(key, attempt);
|
|
784
|
+
void attempt.bounded.then(
|
|
785
|
+
() => { if (timeout) clearTimeout(timeout); },
|
|
786
|
+
() => { if (timeout) clearTimeout(timeout); },
|
|
787
|
+
);
|
|
788
|
+
return this.#contributionStopOperation(key, attempt);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
#contributionStopOperation(key: string, attempt: SessionStopAttempt): ContributionStopOperation {
|
|
792
|
+
const bounded = attempt.result?.status === "fulfilled"
|
|
793
|
+
? Promise.resolve()
|
|
794
|
+
: attempt.result?.status === "rejected"
|
|
795
|
+
? Promise.reject(attempt.result.reason)
|
|
796
|
+
: attempt.timeoutError
|
|
797
|
+
? Promise.reject(attempt.timeoutError)
|
|
798
|
+
: attempt.bounded;
|
|
799
|
+
|
|
800
|
+
return {
|
|
801
|
+
bounded,
|
|
802
|
+
settled: attempt.settled,
|
|
803
|
+
isSettled: () => attempt.result !== undefined,
|
|
804
|
+
release: () => {
|
|
805
|
+
if (this.#stopAttempts.get(key) === attempt) this.#stopAttempts.delete(key);
|
|
806
|
+
},
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
#releaseStopAttempts(runId: string): void {
|
|
811
|
+
for (const key of this.#stopAttempts.keys()) {
|
|
812
|
+
if (key.startsWith(`${runId}\0`)) this.#stopAttempts.delete(key);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
async #settle(name: string, operations: ReadonlyArray<() => void | Promise<void> | undefined>): Promise<void> {
|
|
817
|
+
const failures: unknown[] = [];
|
|
818
|
+
for (const operation of operations) {
|
|
819
|
+
try {
|
|
820
|
+
await operation();
|
|
821
|
+
} catch (error) {
|
|
822
|
+
failures.push(error);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
if (failures.length > 0) throw new AggregateError(failures, `${name} ist in ${failures.length} Plugin(s) fehlgeschlagen`);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
export class SessionMetadataContributionRegistry {
|
|
830
|
+
readonly #metadata = new ContributionRegistry<SessionMetadataContribution>("Session-Metadaten-Beitrag");
|
|
831
|
+
|
|
832
|
+
register(owner: string, contributions: readonly SessionMetadataContribution[]): void {
|
|
833
|
+
this.#metadata.register(owner, contributions);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
async describe(runId: string): Promise<Readonly<Record<string, unknown>>> {
|
|
837
|
+
const entries = await Promise.all(this.#metadata.entries().map(async ({ value }) => [
|
|
838
|
+
value.id,
|
|
839
|
+
await value.describe({ runId }),
|
|
840
|
+
] as const));
|
|
841
|
+
return Object.fromEntries(entries);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
export class StartOptionContributionRegistry {
|
|
846
|
+
readonly #options = new ContributionRegistry<StartOptionContribution>("Startoption");
|
|
847
|
+
|
|
848
|
+
register(owner: string, contributions: readonly StartOptionContribution[]): void {
|
|
849
|
+
for (const contribution of contributions) {
|
|
850
|
+
if (!START_OPTION_ID.test(contribution.id)) throw new Error(`Ungültige Startoption-Id: ${contribution.id}`);
|
|
851
|
+
if (typeof contribution.schema !== "object" || contribution.schema === null) {
|
|
852
|
+
throw new Error(`Startoption ${contribution.id} hat kein Schema`);
|
|
853
|
+
}
|
|
854
|
+
for (const name of ["selectable", "defaultValue", "accept", "describe"] as const) {
|
|
855
|
+
if (typeof contribution[name] !== "function") throw new Error(`Startoption ${contribution.id} hat kein ${name}`);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
this.#options.register(owner, contributions);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
entries(): readonly RegisteredStartOption[] {
|
|
862
|
+
return this.#options.entries().map(({ owner, value }) => ({ owner, option: value }));
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
entry(id: string): RegisteredStartOption | undefined {
|
|
866
|
+
const found = this.#options.entries().find(({ value }) => value.id === id);
|
|
867
|
+
return found ? { owner: found.owner, option: found.value } : undefined;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
describe(): readonly { id: string; owner: string }[] {
|
|
871
|
+
return this.#options.entries().map(({ owner, value }) => ({ id: value.id, owner }));
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
defaultValue(id: string, context: StartOptionContext): JsonValue {
|
|
875
|
+
const { option } = this.#require(id);
|
|
876
|
+
const value = option.defaultValue(context);
|
|
877
|
+
this.#check(option, value, "Standardwert");
|
|
878
|
+
return value;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
accept(id: string, value: unknown, context: StartOptionContext): JsonValue {
|
|
882
|
+
const { option } = this.#require(id);
|
|
883
|
+
assertJsonValue(value, `Startoption ${id} value`);
|
|
884
|
+
this.#check(option, value, "Wert");
|
|
885
|
+
const accepted = option.accept(value, context);
|
|
886
|
+
this.#check(option, accepted, "Ergebnis von accept");
|
|
887
|
+
return accepted;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
#require(id: string): RegisteredStartOption {
|
|
891
|
+
const entry = this.entry(id);
|
|
892
|
+
if (!entry) throw new Error(`Startoption ${id} ist nicht registriert`);
|
|
893
|
+
return entry;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
#check(option: StartOptionContribution, value: unknown, label: string): void {
|
|
897
|
+
if (Value.Check(option.schema, value)) return;
|
|
898
|
+
const first = [...Value.Errors(option.schema, value)].at(0);
|
|
899
|
+
throw new Error(`Ungültiger ${label} für Startoption ${option.id}: ${first?.message ?? "Schema nicht erfüllt"}`);
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
export class ConfigContributionRegistry {
|
|
904
|
+
readonly #entries: Array<{ owners: string[]; value: PluginConfigDescriptor }> = [];
|
|
905
|
+
|
|
906
|
+
register(owner: string, descriptors: readonly PluginConfigDescriptor[]): void {
|
|
907
|
+
for (const descriptor of descriptors) {
|
|
908
|
+
const existing = this.#entries.find((entry) => entry.value.key === descriptor.key);
|
|
909
|
+
if (!existing) {
|
|
910
|
+
this.#entries.push({ owners: [owner], value: descriptor });
|
|
911
|
+
continue;
|
|
912
|
+
}
|
|
913
|
+
if (existing.value.source !== descriptor.source || Boolean(existing.value.secret) !== Boolean(descriptor.secret)) {
|
|
914
|
+
throw new Error(`Konfiguration ${descriptor.key} ist widersprüchlich deklariert`);
|
|
915
|
+
}
|
|
916
|
+
if (existing.owners.includes(owner)) {
|
|
917
|
+
throw new Error(`Konfiguration ${descriptor.key} ist in ${owner} mehrfach deklariert`);
|
|
918
|
+
}
|
|
919
|
+
existing.owners.push(owner);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
entries(): readonly PluginConfigDescriptor[] {
|
|
924
|
+
return this.#entries.map(({ value }) => value);
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
secretKeys(): readonly string[] {
|
|
928
|
+
return this.#entries
|
|
929
|
+
.filter(({ value }) => value.secret)
|
|
930
|
+
.map(({ value }) => value.key);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
publicEntries(owner: string): readonly PublicPluginConfigDescriptor[] {
|
|
934
|
+
return this.#entries
|
|
935
|
+
.filter((entry) => entry.owners.includes(owner))
|
|
936
|
+
.map(({ value }) => ({
|
|
937
|
+
key: value.key,
|
|
938
|
+
source: value.secret ? "environment" : value.source,
|
|
939
|
+
secret: Boolean(value.secret),
|
|
940
|
+
}));
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
const joinSafe = (base: string, segments: readonly string[]): string => {
|
|
945
|
+
for (const segment of segments) {
|
|
946
|
+
if (!segment || segment === "." || segment === ".." || path.isAbsolute(segment)
|
|
947
|
+
|| segment.includes("/") || segment.includes("\\")) {
|
|
948
|
+
throw new Error(`Ungültiges Plugin-Speichersegment: ${segment}`);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
return path.join(base, ...segments);
|
|
952
|
+
};
|
|
953
|
+
|
|
954
|
+
export class StorageRegistry {
|
|
955
|
+
readonly #dataDirectory: string;
|
|
956
|
+
readonly #modes: PluginStorageModes;
|
|
957
|
+
readonly #scopes = new Map<string, PluginStorage>();
|
|
958
|
+
|
|
959
|
+
constructor(dataDirectory: string, modes: PluginStorageModes) {
|
|
960
|
+
this.#dataDirectory = dataDirectory;
|
|
961
|
+
this.#modes = Object.freeze({ ...modes });
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
register(manifest: PluginManifest): PluginStorage {
|
|
965
|
+
if (this.#scopes.has(manifest.id)) throw new Error(`Speicher für ${manifest.id} ist bereits registriert`);
|
|
966
|
+
const pluginDirectory = path.join("plugins", manifest.id);
|
|
967
|
+
const scope: PluginStorage = Object.freeze({
|
|
968
|
+
sessionsRoot: path.join(this.#dataDirectory, "sessions"),
|
|
969
|
+
modes: this.#modes,
|
|
970
|
+
root: (...segments: string[]) => joinSafe(path.join(this.#dataDirectory, pluginDirectory), segments),
|
|
971
|
+
session: (runId: string, ...segments: string[]) => {
|
|
972
|
+
if (!RUN_ID.test(runId)) throw new Error(`Ungültige Session-Id: ${runId}`);
|
|
973
|
+
return joinSafe(path.join(this.#dataDirectory, "sessions", runId, pluginDirectory), segments);
|
|
974
|
+
},
|
|
975
|
+
});
|
|
976
|
+
this.#scopes.set(manifest.id, scope);
|
|
977
|
+
return scope;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
of(pluginId: string): PluginStorage {
|
|
981
|
+
const scope = this.#scopes.get(pluginId);
|
|
982
|
+
if (!scope) throw new Error(`Speicher für ${pluginId} ist nicht registriert`);
|
|
983
|
+
return scope;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
class ClientConfigRegistry {
|
|
988
|
+
readonly #values = new Map<string, Record<string, unknown>>();
|
|
989
|
+
|
|
990
|
+
register(owner: string, values: Readonly<Record<string, unknown>>): void {
|
|
991
|
+
const existing = this.#values.get(owner) ?? {};
|
|
992
|
+
for (const key of Object.keys(values)) {
|
|
993
|
+
if (Object.hasOwn(existing, key)) {
|
|
994
|
+
throw new Error(`Client-Konfiguration ${key} ist in ${owner} mehrfach gesetzt`);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
this.#values.set(owner, { ...existing, ...values });
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
valuesFor(owner: string): Readonly<Record<string, unknown>> | undefined {
|
|
1001
|
+
return this.#values.get(owner);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
class ServiceRegistry {
|
|
1006
|
+
readonly #services = new Map<string, { owner: string; value: unknown }>();
|
|
1007
|
+
|
|
1008
|
+
provide<T>(owner: string, token: ServiceToken<T>, service: T): void {
|
|
1009
|
+
const existing = this.#services.get(token.id);
|
|
1010
|
+
if (existing) throw new Error(`Service ${token.id} wird bereits von ${existing.owner} bereitgestellt`);
|
|
1011
|
+
this.#services.set(token.id, { owner, value: service });
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
require<T>(token: ServiceToken<T>): T {
|
|
1015
|
+
const entry = this.#services.get(token.id);
|
|
1016
|
+
if (!entry) throw new Error(`Erforderlicher Plugin-Service ${token.id} ist nicht registriert`);
|
|
1017
|
+
return entry.value as T;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
optional<T>(token: ServiceToken<T>): T | undefined {
|
|
1021
|
+
return this.#services.get(token.id)?.value as T | undefined;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
export interface PluginHostOptions {
|
|
1026
|
+
product: ProductDescriptor;
|
|
1027
|
+
dataDirectory: string;
|
|
1028
|
+
storageModes: PluginStorageModes;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
const HOST_OWNER = "host";
|
|
1032
|
+
|
|
1033
|
+
export class PluginHost {
|
|
1034
|
+
readonly methods = new MethodContributionRegistry();
|
|
1035
|
+
readonly channels = new ChannelContributionRegistry();
|
|
1036
|
+
readonly http = new HttpContributionRegistry();
|
|
1037
|
+
readonly operations = new OperationContributionRegistry();
|
|
1038
|
+
readonly agentRuntime = new AgentContributionRegistry();
|
|
1039
|
+
readonly tools = new ToolContributionRegistry();
|
|
1040
|
+
readonly prompts = new PromptContributionRegistry();
|
|
1041
|
+
readonly skills = new SkillContributionRegistry();
|
|
1042
|
+
readonly startEntries = new StartEntryContributionRegistry();
|
|
1043
|
+
readonly profiles = new ProfileContributionRegistry();
|
|
1044
|
+
readonly script = new ScriptContributionRegistry();
|
|
1045
|
+
readonly lifecycle = new LifecycleContributionRegistry();
|
|
1046
|
+
readonly sessionMetadata = new SessionMetadataContributionRegistry();
|
|
1047
|
+
readonly startOptions = new StartOptionContributionRegistry();
|
|
1048
|
+
readonly config = new ConfigContributionRegistry();
|
|
1049
|
+
readonly storage: StorageRegistry;
|
|
1050
|
+
readonly #product: ProductDescriptor;
|
|
1051
|
+
readonly #services = new ServiceRegistry();
|
|
1052
|
+
readonly #clientConfig = new ClientConfigRegistry();
|
|
1053
|
+
readonly #manifests: PluginManifest[] = [];
|
|
1054
|
+
#sealed = false;
|
|
1055
|
+
|
|
1056
|
+
constructor(options: PluginHostOptions) {
|
|
1057
|
+
this.#product = Object.freeze({ ...options.product });
|
|
1058
|
+
this.storage = new StorageRegistry(options.dataDirectory, options.storageModes);
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
provideHost<T>(token: ServiceToken<T>, service: T): void {
|
|
1062
|
+
this.#services.provide(HOST_OWNER, token, service);
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
register(plugin: RAgentsPlugin): this {
|
|
1066
|
+
if (this.#sealed) throw new Error("Nach dem Start können keine Plugins mehr registriert werden");
|
|
1067
|
+
const { manifest } = plugin;
|
|
1068
|
+
if (!PLUGIN_ID.test(manifest.id)) throw new Error(`Ungültige Plugin-Id: ${manifest.id}`);
|
|
1069
|
+
if (this.#manifests.some((entry) => entry.id === manifest.id)) {
|
|
1070
|
+
throw new Error(`Plugin ${manifest.id} ist bereits registriert`);
|
|
1071
|
+
}
|
|
1072
|
+
this.#manifests.push(manifest);
|
|
1073
|
+
const storage = this.storage.register(manifest);
|
|
1074
|
+
const registration: PluginRegistration = {
|
|
1075
|
+
manifest,
|
|
1076
|
+
storage,
|
|
1077
|
+
clientConfig: (values) => this.#clientConfig.register(manifest.id, values),
|
|
1078
|
+
config: (...entries) => this.config.register(manifest.id, entries),
|
|
1079
|
+
channels: (...entries) => this.channels.register(manifest.id, entries),
|
|
1080
|
+
methods: (...entries) => this.methods.register(manifest.id, entries),
|
|
1081
|
+
http: (...entries) => this.http.register(manifest.id, entries),
|
|
1082
|
+
lifecycle: (...entries) => this.lifecycle.register(manifest.id, entries),
|
|
1083
|
+
operation: (id) => this.operations.operation(id),
|
|
1084
|
+
operations: (...entries) => this.operations.register(manifest.id, entries),
|
|
1085
|
+
invokeOperation: (id, context, input) => this.operations.invoke(id, context, input),
|
|
1086
|
+
agentRuntime: (...entries) => this.agentRuntime.register(manifest.id, entries),
|
|
1087
|
+
profiles: (...entries) => this.profiles.register(manifest.id, entries),
|
|
1088
|
+
prompts: (...entries) => this.prompts.register(manifest.id, entries),
|
|
1089
|
+
provide: (token, service) => this.#services.provide(manifest.id, token, service),
|
|
1090
|
+
service: (token) => this.#services.require(token),
|
|
1091
|
+
optionalService: (token) => this.#services.optional(token),
|
|
1092
|
+
sessionMetadata: (...entries) => this.sessionMetadata.register(manifest.id, entries),
|
|
1093
|
+
skills: (...entries) => this.skills.register(manifest.id, entries),
|
|
1094
|
+
startEntries: (...entries) => this.startEntries.register(manifest.id, entries),
|
|
1095
|
+
startOptions: (...entries) => this.startOptions.register(manifest.id, entries),
|
|
1096
|
+
functions: (...entries) => this.tools.registerFunctions(manifest.id, entries),
|
|
1097
|
+
script: (...entries) => this.script.register(manifest.id, entries),
|
|
1098
|
+
};
|
|
1099
|
+
plugin.register(registration);
|
|
1100
|
+
return this;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
seal(): void {
|
|
1104
|
+
if (this.#sealed) return;
|
|
1105
|
+
const positions = new Map(this.#manifests.map((manifest, index) => [manifest.id, index]));
|
|
1106
|
+
for (const [index, manifest] of this.#manifests.entries()) {
|
|
1107
|
+
for (const dependency of manifest.requires ?? []) {
|
|
1108
|
+
const position = positions.get(dependency);
|
|
1109
|
+
if (position === undefined) throw new Error(`Plugin ${manifest.id} benötigt das fehlende Plugin ${dependency}`);
|
|
1110
|
+
if (position >= index) throw new Error(`Plugin ${dependency} muss vor ${manifest.id} registriert werden`);
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
this.#sealed = true;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
async initialize(): Promise<void> {
|
|
1117
|
+
this.seal();
|
|
1118
|
+
this.startEntries.assertSkillsKnown(await this.skills.describe(undefined));
|
|
1119
|
+
await this.lifecycle.initialize();
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
publicProfile(access: AccessContext = unrestrictedAccess): PublicPluginProfile {
|
|
1123
|
+
this.seal();
|
|
1124
|
+
return {
|
|
1125
|
+
product: this.#product,
|
|
1126
|
+
startEntries: this.startEntries.describe().filter((entry) => canStartEntry(access, entry.id)
|
|
1127
|
+
&& (entry.action === "script" || access.can("runs.create"))),
|
|
1128
|
+
plugins: this.#manifests.map((manifest) => {
|
|
1129
|
+
const config = this.#mergedClientConfig(manifest);
|
|
1130
|
+
return {
|
|
1131
|
+
id: manifest.id,
|
|
1132
|
+
web: manifest.web === true,
|
|
1133
|
+
...(config ? { config } : {}),
|
|
1134
|
+
};
|
|
1135
|
+
}),
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
publicManifests(): readonly PublicPluginManifest[] {
|
|
1140
|
+
this.seal();
|
|
1141
|
+
return this.#manifests.map((manifest) => {
|
|
1142
|
+
const clientConfig = this.#mergedClientConfig(manifest);
|
|
1143
|
+
return {
|
|
1144
|
+
id: manifest.id,
|
|
1145
|
+
requires: [...(manifest.requires ?? [])],
|
|
1146
|
+
...(clientConfig ? { clientConfig } : {}),
|
|
1147
|
+
configuration: this.config.publicEntries(manifest.id),
|
|
1148
|
+
};
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
#mergedClientConfig(manifest: PluginManifest): Readonly<Record<string, unknown>> | undefined {
|
|
1153
|
+
const registered = this.#clientConfig.valuesFor(manifest.id);
|
|
1154
|
+
const declared = manifest.client?.config;
|
|
1155
|
+
if (!declared && !registered) return undefined;
|
|
1156
|
+
return { ...(declared ?? {}), ...(registered ?? {}) };
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
isApiPath(pathname: string): boolean {
|
|
1160
|
+
return pathname === "/api/plugins" || this.http.isApiPath(pathname);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
async dispatchHttp(request: IncomingMessage, response: ServerResponse, url: URL, access: AccessContext = unrestrictedAccess): Promise<boolean> {
|
|
1164
|
+
if (request.method === "GET" && url.pathname === "/api/plugins") {
|
|
1165
|
+
response.writeHead(200, { "Cache-Control": "no-store", "Content-Type": "application/json" });
|
|
1166
|
+
response.end(JSON.stringify(this.publicProfile(access)));
|
|
1167
|
+
return true;
|
|
1168
|
+
}
|
|
1169
|
+
return this.http.dispatch(request, response, url, access);
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
scriptRuntime(context: ScriptFactoryContext): ScriptRuntime | undefined {
|
|
1173
|
+
this.seal();
|
|
1174
|
+
return this.script.create(context);
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
service<T>(token: ServiceToken<T>): T {
|
|
1178
|
+
return this.#services.require(token);
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
optionalService<T>(token: ServiceToken<T>): T | undefined {
|
|
1182
|
+
return this.#services.optional(token);
|
|
1183
|
+
}
|
|
1184
|
+
}
|