@agent-native/core 0.4.5 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -43
- package/dist/a2a/agent-card.d.ts.map +1 -1
- package/dist/a2a/agent-card.js +12 -1
- package/dist/a2a/agent-card.js.map +1 -1
- package/dist/a2a/client.d.ts +18 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +62 -4
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/handlers.d.ts +6 -3
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +45 -39
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/index.d.ts +2 -2
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +3 -3
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/server.d.ts +11 -2
- package/dist/a2a/server.d.ts.map +1 -1
- package/dist/a2a/server.js +99 -14
- package/dist/a2a/server.js.map +1 -1
- package/dist/a2a/task-store.d.ts +6 -6
- package/dist/a2a/task-store.d.ts.map +1 -1
- package/dist/a2a/task-store.js +102 -42
- package/dist/a2a/task-store.js.map +1 -1
- package/dist/a2a/types.d.ts +3 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/action.d.ts +80 -0
- package/dist/action.d.ts.map +1 -0
- package/dist/action.js +232 -0
- package/dist/action.js.map +1 -0
- package/dist/agent/engine/ai-sdk-engine.d.ts +24 -0
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -0
- package/dist/agent/engine/ai-sdk-engine.js +302 -0
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -0
- package/dist/agent/engine/anthropic-engine.d.ts +24 -0
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -0
- package/dist/agent/engine/anthropic-engine.js +169 -0
- package/dist/agent/engine/anthropic-engine.js.map +1 -0
- package/dist/agent/engine/builtin.d.ts +12 -0
- package/dist/agent/engine/builtin.d.ts.map +1 -0
- package/dist/agent/engine/builtin.js +72 -0
- package/dist/agent/engine/builtin.js.map +1 -0
- package/dist/agent/engine/index.d.ts +9 -0
- package/dist/agent/engine/index.d.ts.map +1 -0
- package/dist/agent/engine/index.js +8 -0
- package/dist/agent/engine/index.js.map +1 -0
- package/dist/agent/engine/registry.d.ts +61 -0
- package/dist/agent/engine/registry.d.ts.map +1 -0
- package/dist/agent/engine/registry.js +101 -0
- package/dist/agent/engine/registry.js.map +1 -0
- package/dist/agent/engine/translate-ai-sdk.d.ts +20 -0
- package/dist/agent/engine/translate-ai-sdk.d.ts.map +1 -0
- package/dist/agent/engine/translate-ai-sdk.js +174 -0
- package/dist/agent/engine/translate-ai-sdk.js.map +1 -0
- package/dist/agent/engine/translate-anthropic.d.ts +23 -0
- package/dist/agent/engine/translate-anthropic.d.ts.map +1 -0
- package/dist/agent/engine/translate-anthropic.js +140 -0
- package/dist/agent/engine/translate-anthropic.js.map +1 -0
- package/dist/agent/engine/types.d.ts +168 -0
- package/dist/agent/engine/types.d.ts.map +1 -0
- package/dist/agent/engine/types.js +13 -0
- package/dist/agent/engine/types.js.map +1 -0
- package/dist/agent/index.d.ts +2 -2
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/production-agent.d.ts +69 -7
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +480 -127
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +43 -0
- package/dist/agent/run-manager.d.ts.map +1 -0
- package/dist/agent/run-manager.js +364 -0
- package/dist/agent/run-manager.js.map +1 -0
- package/dist/agent/run-store.d.ts +26 -0
- package/dist/agent/run-store.d.ts.map +1 -0
- package/dist/agent/run-store.js +145 -0
- package/dist/agent/run-store.js.map +1 -0
- package/dist/agent/thread-data-builder.d.ts +31 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -0
- package/dist/agent/thread-data-builder.js +91 -0
- package/dist/agent/thread-data-builder.js.map +1 -0
- package/dist/agent/types.d.ts +73 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/application-state/emitter.d.ts +3 -2
- package/dist/application-state/emitter.d.ts.map +1 -1
- package/dist/application-state/emitter.js +14 -4
- package/dist/application-state/emitter.js.map +1 -1
- package/dist/application-state/handlers.d.ts +8 -8
- package/dist/application-state/handlers.d.ts.map +1 -1
- package/dist/application-state/handlers.js +15 -17
- package/dist/application-state/handlers.js.map +1 -1
- package/dist/application-state/script-helpers.d.ts +1 -1
- package/dist/application-state/script-helpers.d.ts.map +1 -1
- package/dist/application-state/script-helpers.js +56 -8
- package/dist/application-state/script-helpers.js.map +1 -1
- package/dist/application-state/store.d.ts +4 -3
- package/dist/application-state/store.d.ts.map +1 -1
- package/dist/application-state/store.js +31 -59
- package/dist/application-state/store.js.map +1 -1
- package/dist/chat-threads/emitter.d.ts +9 -0
- package/dist/chat-threads/emitter.d.ts.map +1 -0
- package/dist/chat-threads/emitter.js +14 -0
- package/dist/chat-threads/emitter.js.map +1 -0
- package/dist/chat-threads/store.d.ts +42 -0
- package/dist/chat-threads/store.d.ts.map +1 -0
- package/dist/chat-threads/store.js +156 -0
- package/dist/chat-threads/store.js.map +1 -0
- package/dist/cli/create.d.ts +8 -2
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +288 -47
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +49 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/setup-agents.d.ts +11 -0
- package/dist/cli/setup-agents.d.ts.map +1 -0
- package/dist/cli/setup-agents.js +123 -0
- package/dist/cli/setup-agents.js.map +1 -0
- package/dist/client/AgentPanel.d.ts +13 -2
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +771 -38
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AgentTaskCard.d.ts +12 -0
- package/dist/client/AgentTaskCard.d.ts.map +1 -0
- package/dist/client/AgentTaskCard.js +146 -0
- package/dist/client/AgentTaskCard.js.map +1 -0
- package/dist/client/AssistantChat.d.ts +36 -3
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +838 -86
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ClientOnly.d.ts +14 -0
- package/dist/client/ClientOnly.d.ts.map +1 -0
- package/dist/client/ClientOnly.js +17 -0
- package/dist/client/ClientOnly.js.map +1 -0
- package/dist/client/CommandMenu.d.ts +71 -0
- package/dist/client/CommandMenu.d.ts.map +1 -0
- package/dist/client/CommandMenu.js +257 -0
- package/dist/client/CommandMenu.js.map +1 -0
- package/dist/client/DefaultSpinner.d.ts +7 -0
- package/dist/client/DefaultSpinner.d.ts.map +1 -0
- package/dist/client/DefaultSpinner.js +28 -0
- package/dist/client/DefaultSpinner.js.map +1 -0
- package/dist/client/MultiTabAssistantChat.d.ts +40 -2
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +630 -59
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/PoweredByBadge.d.ts.map +1 -1
- package/dist/client/PoweredByBadge.js +4 -3
- package/dist/client/PoweredByBadge.js.map +1 -1
- package/dist/client/Turnstile.d.ts.map +1 -1
- package/dist/client/Turnstile.js +2 -3
- package/dist/client/Turnstile.js.map +1 -1
- package/dist/client/active-run-state.d.ts +10 -0
- package/dist/client/active-run-state.d.ts.map +1 -0
- package/dist/client/active-run-state.js +32 -0
- package/dist/client/active-run-state.js.map +1 -0
- package/dist/client/agent-chat-adapter.d.ts +2 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +145 -130
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-chat.d.ts +14 -1
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +6 -4
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/components/ApiKeySettings.d.ts +2 -2
- package/dist/client/components/ApiKeySettings.js +4 -4
- package/dist/client/components/ApiKeySettings.js.map +1 -1
- package/dist/client/components/CodeAgentIndicator.d.ts +14 -0
- package/dist/client/components/CodeAgentIndicator.d.ts.map +1 -0
- package/dist/client/components/CodeAgentIndicator.js +29 -0
- package/dist/client/components/CodeAgentIndicator.js.map +1 -0
- package/dist/client/components/CodeRequiredDialog.d.ts.map +1 -1
- package/dist/client/components/CodeRequiredDialog.js +4 -3
- package/dist/client/components/CodeRequiredDialog.js.map +1 -1
- package/dist/client/composer/MentionPopover.d.ts +29 -0
- package/dist/client/composer/MentionPopover.d.ts.map +1 -0
- package/dist/client/composer/MentionPopover.js +160 -0
- package/dist/client/composer/MentionPopover.js.map +1 -0
- package/dist/client/composer/TiptapComposer.d.ts +26 -0
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -0
- package/dist/client/composer/TiptapComposer.js +545 -0
- package/dist/client/composer/TiptapComposer.js.map +1 -0
- package/dist/client/composer/extensions/FileReference.d.ts +3 -0
- package/dist/client/composer/extensions/FileReference.d.ts.map +1 -0
- package/dist/client/composer/extensions/FileReference.js +36 -0
- package/dist/client/composer/extensions/FileReference.js.map +1 -0
- package/dist/client/composer/extensions/MentionReference.d.ts +3 -0
- package/dist/client/composer/extensions/MentionReference.d.ts.map +1 -0
- package/dist/client/composer/extensions/MentionReference.js +63 -0
- package/dist/client/composer/extensions/MentionReference.js.map +1 -0
- package/dist/client/composer/extensions/SkillReference.d.ts +3 -0
- package/dist/client/composer/extensions/SkillReference.d.ts.map +1 -0
- package/dist/client/composer/extensions/SkillReference.js +40 -0
- package/dist/client/composer/extensions/SkillReference.js.map +1 -0
- package/dist/client/composer/index.d.ts +8 -0
- package/dist/client/composer/index.d.ts.map +1 -0
- package/dist/client/composer/index.js +7 -0
- package/dist/client/composer/index.js.map +1 -0
- package/dist/client/composer/types.d.ts +37 -0
- package/dist/client/composer/types.d.ts.map +1 -0
- package/dist/client/composer/types.js +2 -0
- package/dist/client/composer/types.js.map +1 -0
- package/dist/client/composer/use-file-search.d.ts +6 -0
- package/dist/client/composer/use-file-search.d.ts.map +1 -0
- package/dist/client/composer/use-file-search.js +40 -0
- package/dist/client/composer/use-file-search.js.map +1 -0
- package/dist/client/composer/use-mention-search.d.ts +6 -0
- package/dist/client/composer/use-mention-search.d.ts.map +1 -0
- package/dist/client/composer/use-mention-search.js +72 -0
- package/dist/client/composer/use-mention-search.js.map +1 -0
- package/dist/client/composer/use-skills.d.ts +7 -0
- package/dist/client/composer/use-skills.d.ts.map +1 -0
- package/dist/client/composer/use-skills.js +38 -0
- package/dist/client/composer/use-skills.js.map +1 -0
- package/dist/client/frame-protocol.d.ts +54 -0
- package/dist/client/frame-protocol.d.ts.map +1 -0
- package/dist/client/frame-protocol.js +9 -0
- package/dist/client/frame-protocol.js.map +1 -0
- package/dist/client/frame.d.ts +56 -0
- package/dist/client/frame.d.ts.map +1 -0
- package/dist/client/{harness.js → frame.js} +49 -26
- package/dist/client/frame.js.map +1 -0
- package/dist/client/index.d.ts +15 -6
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +13 -5
- package/dist/client/index.js.map +1 -1
- package/dist/client/integrations/IntegrationCard.d.ts +6 -0
- package/dist/client/integrations/IntegrationCard.d.ts.map +1 -0
- package/dist/client/integrations/IntegrationCard.js +45 -0
- package/dist/client/integrations/IntegrationCard.js.map +1 -0
- package/dist/client/integrations/IntegrationsPanel.d.ts +2 -0
- package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -0
- package/dist/client/integrations/IntegrationsPanel.js +149 -0
- package/dist/client/integrations/IntegrationsPanel.js.map +1 -0
- package/dist/client/integrations/index.d.ts +4 -0
- package/dist/client/integrations/index.d.ts.map +1 -0
- package/dist/client/integrations/index.js +3 -0
- package/dist/client/integrations/index.js.map +1 -0
- package/dist/client/integrations/useIntegrationStatus.d.ts +15 -0
- package/dist/client/integrations/useIntegrationStatus.d.ts.map +1 -0
- package/dist/client/integrations/useIntegrationStatus.js +37 -0
- package/dist/client/integrations/useIntegrationStatus.js.map +1 -0
- package/dist/client/org/InvitationBanner.d.ts +9 -0
- package/dist/client/org/InvitationBanner.d.ts.map +1 -0
- package/dist/client/org/InvitationBanner.js +17 -0
- package/dist/client/org/InvitationBanner.js.map +1 -0
- package/dist/client/org/OrgSwitcher.d.ts +14 -0
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -0
- package/dist/client/org/OrgSwitcher.js +51 -0
- package/dist/client/org/OrgSwitcher.js.map +1 -0
- package/dist/client/org/TeamPage.d.ts +23 -0
- package/dist/client/org/TeamPage.d.ts.map +1 -0
- package/dist/client/org/TeamPage.js +145 -0
- package/dist/client/org/TeamPage.js.map +1 -0
- package/dist/client/org/hooks.d.ts +14 -0
- package/dist/client/org/hooks.d.ts.map +1 -0
- package/dist/client/org/hooks.js +101 -0
- package/dist/client/org/hooks.js.map +1 -0
- package/dist/client/org/index.d.ts +6 -0
- package/dist/client/org/index.d.ts.map +1 -0
- package/dist/client/org/index.js +6 -0
- package/dist/client/org/index.js.map +1 -0
- package/dist/client/resources/ResourceEditor.d.ts +14 -0
- package/dist/client/resources/ResourceEditor.d.ts.map +1 -0
- package/dist/client/resources/ResourceEditor.js +932 -0
- package/dist/client/resources/ResourceEditor.js.map +1 -0
- package/dist/client/resources/ResourceTree.d.ts +17 -0
- package/dist/client/resources/ResourceTree.d.ts.map +1 -0
- package/dist/client/resources/ResourceTree.js +137 -0
- package/dist/client/resources/ResourceTree.js.map +1 -0
- package/dist/client/resources/ResourcesPanel.d.ts +2 -0
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -0
- package/dist/client/resources/ResourcesPanel.js +366 -0
- package/dist/client/resources/ResourcesPanel.js.map +1 -0
- package/dist/client/resources/index.d.ts +5 -0
- package/dist/client/resources/index.d.ts.map +1 -0
- package/dist/client/resources/index.js +5 -0
- package/dist/client/resources/index.js.map +1 -0
- package/dist/client/resources/use-resources.d.ts +55 -0
- package/dist/client/resources/use-resources.d.ts.map +1 -0
- package/dist/client/resources/use-resources.js +102 -0
- package/dist/client/resources/use-resources.js.map +1 -0
- package/dist/client/sse-event-processor.d.ts +58 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -0
- package/dist/client/sse-event-processor.js +300 -0
- package/dist/client/sse-event-processor.js.map +1 -0
- package/dist/client/terminal/AgentTerminal.d.ts +5 -5
- package/dist/client/terminal/AgentTerminal.d.ts.map +1 -1
- package/dist/client/terminal/AgentTerminal.js +25 -20
- package/dist/client/terminal/AgentTerminal.js.map +1 -1
- package/dist/client/use-action.d.ts +51 -0
- package/dist/client/use-action.d.ts.map +1 -0
- package/dist/client/use-action.js +102 -0
- package/dist/client/use-action.js.map +1 -0
- package/dist/client/use-agent-chat.d.ts +1 -1
- package/dist/client/use-agent-chat.d.ts.map +1 -1
- package/dist/client/use-agent-chat.js +3 -3
- package/dist/client/use-agent-chat.js.map +1 -1
- package/dist/client/use-avatar.d.ts +15 -0
- package/dist/client/use-avatar.d.ts.map +1 -0
- package/dist/client/use-avatar.js +116 -0
- package/dist/client/use-avatar.js.map +1 -0
- package/dist/client/use-chat-threads.d.ts +36 -0
- package/dist/client/use-chat-threads.d.ts.map +1 -0
- package/dist/client/use-chat-threads.js +191 -0
- package/dist/client/use-chat-threads.js.map +1 -0
- package/dist/client/use-db-sync.d.ts +35 -0
- package/dist/client/use-db-sync.d.ts.map +1 -0
- package/dist/client/use-db-sync.js +74 -0
- package/dist/client/use-db-sync.js.map +1 -0
- package/dist/client/use-dev-mode.d.ts +4 -2
- package/dist/client/use-dev-mode.d.ts.map +1 -1
- package/dist/client/use-dev-mode.js +41 -12
- package/dist/client/use-dev-mode.js.map +1 -1
- package/dist/client/use-send-to-agent-chat.d.ts +7 -4
- package/dist/client/use-send-to-agent-chat.d.ts.map +1 -1
- package/dist/client/use-send-to-agent-chat.js +31 -10
- package/dist/client/use-send-to-agent-chat.js.map +1 -1
- package/dist/client/use-session.d.ts +1 -1
- package/dist/client/use-session.js +2 -2
- package/dist/client/use-session.js.map +1 -1
- package/dist/client/useProductionAgent.d.ts +1 -1
- package/dist/client/useProductionAgent.d.ts.map +1 -1
- package/dist/client/useProductionAgent.js +38 -3
- package/dist/client/useProductionAgent.js.map +1 -1
- package/dist/collab/awareness.d.ts +41 -0
- package/dist/collab/awareness.d.ts.map +1 -0
- package/dist/collab/awareness.js +82 -0
- package/dist/collab/awareness.js.map +1 -0
- package/dist/collab/client.d.ts +49 -0
- package/dist/collab/client.d.ts.map +1 -0
- package/dist/collab/client.js +250 -0
- package/dist/collab/client.js.map +1 -0
- package/dist/collab/emitter.d.ts +12 -0
- package/dist/collab/emitter.d.ts.map +1 -0
- package/dist/collab/emitter.js +16 -0
- package/dist/collab/emitter.js.map +1 -0
- package/dist/collab/index.d.ts +7 -0
- package/dist/collab/index.d.ts.map +1 -0
- package/dist/collab/index.js +14 -0
- package/dist/collab/index.js.map +1 -0
- package/dist/collab/routes.d.ts +69 -0
- package/dist/collab/routes.d.ts.map +1 -0
- package/dist/collab/routes.js +98 -0
- package/dist/collab/routes.js.map +1 -0
- package/dist/collab/storage.d.ts +18 -0
- package/dist/collab/storage.d.ts.map +1 -0
- package/dist/collab/storage.js +94 -0
- package/dist/collab/storage.js.map +1 -0
- package/dist/collab/text-to-yjs.d.ts +23 -0
- package/dist/collab/text-to-yjs.d.ts.map +1 -0
- package/dist/collab/text-to-yjs.js +63 -0
- package/dist/collab/text-to-yjs.js.map +1 -0
- package/dist/collab/xml-ops.d.ts +20 -0
- package/dist/collab/xml-ops.d.ts.map +1 -0
- package/dist/collab/xml-ops.js +59 -0
- package/dist/collab/xml-ops.js.map +1 -0
- package/dist/collab/ydoc-manager.d.ts +52 -0
- package/dist/collab/ydoc-manager.d.ts.map +1 -0
- package/dist/collab/ydoc-manager.js +154 -0
- package/dist/collab/ydoc-manager.js.map +1 -0
- package/dist/credentials/index.d.ts +18 -0
- package/dist/credentials/index.d.ts.map +1 -0
- package/dist/credentials/index.js +32 -0
- package/dist/credentials/index.js.map +1 -0
- package/dist/db/client.d.ts +45 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +289 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/create-get-db.d.ts.map +1 -1
- package/dist/db/create-get-db.js +103 -16
- package/dist/db/create-get-db.js.map +1 -1
- package/dist/db/index.d.ts +10 -6
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +10 -4
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts +9 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +67 -41
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/schema.d.ts +52 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +72 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/deploy/build.js +636 -42
- package/dist/deploy/build.js.map +1 -1
- package/dist/deploy/route-discovery.d.ts +25 -3
- package/dist/deploy/route-discovery.d.ts.map +1 -1
- package/dist/deploy/route-discovery.js +135 -24
- package/dist/deploy/route-discovery.js.map +1 -1
- package/dist/index.browser.d.ts +3 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +5 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts +10 -0
- package/dist/integrations/adapters/slack.d.ts.map +1 -0
- package/dist/integrations/adapters/slack.js +215 -0
- package/dist/integrations/adapters/slack.js.map +1 -0
- package/dist/integrations/adapters/telegram.d.ts +12 -0
- package/dist/integrations/adapters/telegram.d.ts.map +1 -0
- package/dist/integrations/adapters/telegram.js +184 -0
- package/dist/integrations/adapters/telegram.js.map +1 -0
- package/dist/integrations/adapters/whatsapp.d.ts +14 -0
- package/dist/integrations/adapters/whatsapp.d.ts.map +1 -0
- package/dist/integrations/adapters/whatsapp.js +205 -0
- package/dist/integrations/adapters/whatsapp.js.map +1 -0
- package/dist/integrations/config-store.d.ts +24 -0
- package/dist/integrations/config-store.d.ts.map +1 -0
- package/dist/integrations/config-store.js +92 -0
- package/dist/integrations/config-store.js.map +1 -0
- package/dist/integrations/index.d.ts +8 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +10 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/plugin.d.ts +20 -0
- package/dist/integrations/plugin.d.ts.map +1 -0
- package/dist/integrations/plugin.js +213 -0
- package/dist/integrations/plugin.js.map +1 -0
- package/dist/integrations/thread-mapping-store.d.ts +25 -0
- package/dist/integrations/thread-mapping-store.d.ts.map +1 -0
- package/dist/integrations/thread-mapping-store.js +95 -0
- package/dist/integrations/thread-mapping-store.js.map +1 -0
- package/dist/integrations/types.d.ts +111 -0
- package/dist/integrations/types.d.ts.map +1 -0
- package/dist/integrations/types.js +2 -0
- package/dist/integrations/types.js.map +1 -0
- package/dist/integrations/webhook-handler.d.ts +31 -0
- package/dist/integrations/webhook-handler.d.ts.map +1 -0
- package/dist/integrations/webhook-handler.js +210 -0
- package/dist/integrations/webhook-handler.js.map +1 -0
- package/dist/jobs/cron.d.ts +14 -0
- package/dist/jobs/cron.d.ts.map +1 -0
- package/dist/jobs/cron.js +100 -0
- package/dist/jobs/cron.js.map +1 -0
- package/dist/jobs/index.d.ts +4 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +4 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/jobs/scheduler.d.ts +29 -0
- package/dist/jobs/scheduler.d.ts.map +1 -0
- package/dist/jobs/scheduler.js +205 -0
- package/dist/jobs/scheduler.js.map +1 -0
- package/dist/jobs/tools.d.ts +3 -0
- package/dist/jobs/tools.d.ts.map +1 -0
- package/dist/jobs/tools.js +192 -0
- package/dist/jobs/tools.js.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +26 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +182 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/oauth-tokens/index.d.ts +1 -1
- package/dist/oauth-tokens/index.d.ts.map +1 -1
- package/dist/oauth-tokens/index.js +1 -1
- package/dist/oauth-tokens/index.js.map +1 -1
- package/dist/oauth-tokens/store.d.ts +5 -0
- package/dist/oauth-tokens/store.d.ts.map +1 -1
- package/dist/oauth-tokens/store.js +67 -82
- package/dist/oauth-tokens/store.js.map +1 -1
- package/dist/org/context.d.ts +11 -0
- package/dist/org/context.d.ts.map +1 -0
- package/dist/org/context.js +61 -0
- package/dist/org/context.js.map +1 -0
- package/dist/org/handlers.d.ts +66 -0
- package/dist/org/handlers.d.ts.map +1 -0
- package/dist/org/handlers.js +306 -0
- package/dist/org/handlers.js.map +1 -0
- package/dist/org/index.d.ts +7 -0
- package/dist/org/index.d.ts.map +1 -0
- package/dist/org/index.js +11 -0
- package/dist/org/index.js.map +1 -0
- package/dist/org/migrations.d.ts +10 -0
- package/dist/org/migrations.d.ts.map +1 -0
- package/dist/org/migrations.js +39 -0
- package/dist/org/migrations.js.map +1 -0
- package/dist/org/plugin.d.ts +26 -0
- package/dist/org/plugin.d.ts.map +1 -0
- package/dist/org/plugin.js +94 -0
- package/dist/org/plugin.js.map +1 -0
- package/dist/org/schema.d.ts +301 -0
- package/dist/org/schema.d.ts.map +1 -0
- package/dist/org/schema.js +23 -0
- package/dist/org/schema.js.map +1 -0
- package/dist/org/types.d.ts +42 -0
- package/dist/org/types.d.ts.map +1 -0
- package/dist/org/types.js +5 -0
- package/dist/org/types.js.map +1 -0
- package/dist/resources/emitter.d.ts +13 -0
- package/dist/resources/emitter.d.ts.map +1 -0
- package/dist/resources/emitter.js +32 -0
- package/dist/resources/emitter.js.map +1 -0
- package/dist/resources/handlers.d.ts +54 -0
- package/dist/resources/handlers.d.ts.map +1 -0
- package/dist/resources/handlers.js +292 -0
- package/dist/resources/handlers.js.map +1 -0
- package/dist/resources/index.d.ts +5 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +5 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/script-helpers.d.ts +24 -0
- package/dist/resources/script-helpers.d.ts.map +1 -0
- package/dist/resources/script-helpers.js +36 -0
- package/dist/resources/script-helpers.js.map +1 -0
- package/dist/resources/store.d.ts +40 -0
- package/dist/resources/store.d.ts.map +1 -0
- package/dist/resources/store.js +497 -0
- package/dist/resources/store.js.map +1 -0
- package/dist/scripts/agent-engines/list-agent-engines.d.ts +7 -0
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -0
- package/dist/scripts/agent-engines/list-agent-engines.js +42 -0
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -0
- package/dist/scripts/agent-engines/set-agent-engine.d.ts +7 -0
- package/dist/scripts/agent-engines/set-agent-engine.d.ts.map +1 -0
- package/dist/scripts/agent-engines/set-agent-engine.js +57 -0
- package/dist/scripts/agent-engines/set-agent-engine.js.map +1 -0
- package/dist/scripts/agent-engines/test-agent-engine.d.ts +7 -0
- package/dist/scripts/agent-engines/test-agent-engine.d.ts.map +1 -0
- package/dist/scripts/agent-engines/test-agent-engine.js +102 -0
- package/dist/scripts/agent-engines/test-agent-engine.js.map +1 -0
- package/dist/scripts/call-agent.d.ts +5 -0
- package/dist/scripts/call-agent.d.ts.map +1 -0
- package/dist/scripts/call-agent.js +111 -0
- package/dist/scripts/call-agent.js.map +1 -0
- package/dist/scripts/chat/index.d.ts +2 -0
- package/dist/scripts/chat/index.d.ts.map +1 -0
- package/dist/scripts/chat/index.js +5 -0
- package/dist/scripts/chat/index.js.map +1 -0
- package/dist/scripts/chat/open-chat.d.ts +11 -0
- package/dist/scripts/chat/open-chat.d.ts.map +1 -0
- package/dist/scripts/chat/open-chat.js +48 -0
- package/dist/scripts/chat/open-chat.js.map +1 -0
- package/dist/scripts/chat/search-chats.d.ts +10 -0
- package/dist/scripts/chat/search-chats.d.ts.map +1 -0
- package/dist/scripts/chat/search-chats.js +89 -0
- package/dist/scripts/chat/search-chats.js.map +1 -0
- package/dist/scripts/core-scripts.d.ts.map +1 -1
- package/dist/scripts/core-scripts.js +4 -0
- package/dist/scripts/core-scripts.js.map +1 -1
- package/dist/scripts/db/check-scoping.d.ts +14 -0
- package/dist/scripts/db/check-scoping.d.ts.map +1 -0
- package/dist/scripts/db/check-scoping.js +174 -0
- package/dist/scripts/db/check-scoping.js.map +1 -0
- package/dist/scripts/db/exec.d.ts +7 -2
- package/dist/scripts/db/exec.d.ts.map +1 -1
- package/dist/scripts/db/exec.js +143 -36
- package/dist/scripts/db/exec.js.map +1 -1
- package/dist/scripts/db/index.d.ts.map +1 -1
- package/dist/scripts/db/index.js +2 -0
- package/dist/scripts/db/index.js.map +1 -1
- package/dist/scripts/db/patch.d.ts +50 -0
- package/dist/scripts/db/patch.d.ts.map +1 -0
- package/dist/scripts/db/patch.js +392 -0
- package/dist/scripts/db/patch.js.map +1 -0
- package/dist/scripts/db/query.d.ts +7 -2
- package/dist/scripts/db/query.d.ts.map +1 -1
- package/dist/scripts/db/query.js +89 -45
- package/dist/scripts/db/query.js.map +1 -1
- package/dist/scripts/db/schema.d.ts +2 -2
- package/dist/scripts/db/schema.d.ts.map +1 -1
- package/dist/scripts/db/schema.js +145 -6
- package/dist/scripts/db/schema.js.map +1 -1
- package/dist/scripts/db/scoping.d.ts +42 -0
- package/dist/scripts/db/scoping.d.ts.map +1 -0
- package/dist/scripts/db/scoping.js +216 -0
- package/dist/scripts/db/scoping.js.map +1 -0
- package/dist/scripts/dev/index.d.ts +2 -2
- package/dist/scripts/dev/index.d.ts.map +1 -1
- package/dist/scripts/dev/index.js +65 -2
- package/dist/scripts/dev/index.js.map +1 -1
- package/dist/scripts/dev/list-files.d.ts +2 -2
- package/dist/scripts/dev/read-file.d.ts +2 -2
- package/dist/scripts/dev/read-file.js +1 -1
- package/dist/scripts/dev/read-file.js.map +1 -1
- package/dist/scripts/dev/search-files.d.ts +2 -2
- package/dist/scripts/dev/search-files.js +1 -1
- package/dist/scripts/dev/search-files.js.map +1 -1
- package/dist/scripts/dev/shell.d.ts +2 -2
- package/dist/scripts/dev/shell.js +1 -1
- package/dist/scripts/dev/shell.js.map +1 -1
- package/dist/scripts/dev/write-file.d.ts +2 -2
- package/dist/scripts/dev/write-file.js +1 -1
- package/dist/scripts/dev/write-file.js.map +1 -1
- package/dist/scripts/parse-args.d.ts +14 -0
- package/dist/scripts/parse-args.d.ts.map +1 -0
- package/dist/scripts/parse-args.js +45 -0
- package/dist/scripts/parse-args.js.map +1 -0
- package/dist/scripts/resources/delete.d.ts +10 -0
- package/dist/scripts/resources/delete.d.ts.map +1 -0
- package/dist/scripts/resources/delete.js +38 -0
- package/dist/scripts/resources/delete.js.map +1 -0
- package/dist/scripts/resources/index.d.ts +2 -0
- package/dist/scripts/resources/index.d.ts.map +1 -0
- package/dist/scripts/resources/index.js +8 -0
- package/dist/scripts/resources/index.js.map +1 -0
- package/dist/scripts/resources/list.d.ts +10 -0
- package/dist/scripts/resources/list.d.ts.map +1 -0
- package/dist/scripts/resources/list.js +57 -0
- package/dist/scripts/resources/list.js.map +1 -0
- package/dist/scripts/resources/migrate-learnings.d.ts +10 -0
- package/dist/scripts/resources/migrate-learnings.d.ts.map +1 -0
- package/dist/scripts/resources/migrate-learnings.js +23 -0
- package/dist/scripts/resources/migrate-learnings.js.map +1 -0
- package/dist/scripts/resources/read.d.ts +10 -0
- package/dist/scripts/resources/read.d.ts.map +1 -0
- package/dist/scripts/resources/read.js +59 -0
- package/dist/scripts/resources/read.js.map +1 -0
- package/dist/scripts/resources/write.d.ts +10 -0
- package/dist/scripts/resources/write.d.ts.map +1 -0
- package/dist/scripts/resources/write.js +67 -0
- package/dist/scripts/resources/write.js.map +1 -0
- package/dist/scripts/runner.d.ts +7 -7
- package/dist/scripts/runner.d.ts.map +1 -1
- package/dist/scripts/runner.js +78 -29
- package/dist/scripts/runner.js.map +1 -1
- package/dist/scripts/utils.d.ts +5 -10
- package/dist/scripts/utils.d.ts.map +1 -1
- package/dist/scripts/utils.js +7 -43
- package/dist/scripts/utils.js.map +1 -1
- package/dist/server/action-discovery.d.ts +40 -0
- package/dist/server/action-discovery.d.ts.map +1 -0
- package/dist/server/action-discovery.js +257 -0
- package/dist/server/action-discovery.js.map +1 -0
- package/dist/server/action-routes.d.ts +15 -0
- package/dist/server/action-routes.d.ts.map +1 -0
- package/dist/server/action-routes.js +105 -0
- package/dist/server/action-routes.js.map +1 -0
- package/dist/server/agent-chat-plugin.d.ts +32 -23
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +1983 -39
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-discovery.d.ts +21 -0
- package/dist/server/agent-discovery.d.ts.map +1 -0
- package/dist/server/agent-discovery.js +197 -0
- package/dist/server/agent-discovery.js.map +1 -0
- package/dist/server/agent-teams.d.ts +70 -0
- package/dist/server/agent-teams.d.ts.map +1 -0
- package/dist/server/agent-teams.js +367 -0
- package/dist/server/agent-teams.js.map +1 -0
- package/dist/server/agents-bundle.d.ts +87 -0
- package/dist/server/agents-bundle.d.ts.map +1 -0
- package/dist/server/agents-bundle.js +231 -0
- package/dist/server/agents-bundle.js.map +1 -0
- package/dist/server/auth-plugin.d.ts +5 -0
- package/dist/server/auth-plugin.d.ts.map +1 -1
- package/dist/server/auth-plugin.js +13 -3
- package/dist/server/auth-plugin.js.map +1 -1
- package/dist/server/auth.d.ts +54 -31
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +671 -294
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts +72 -0
- package/dist/server/better-auth-instance.d.ts.map +1 -0
- package/dist/server/better-auth-instance.js +144 -0
- package/dist/server/better-auth-instance.js.map +1 -0
- package/dist/server/collab-plugin.d.ts +29 -0
- package/dist/server/collab-plugin.d.ts.map +1 -0
- package/dist/server/collab-plugin.js +85 -0
- package/dist/server/collab-plugin.js.map +1 -0
- package/dist/server/core-routes-plugin.d.ts +54 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -0
- package/dist/server/core-routes-plugin.js +195 -0
- package/dist/server/core-routes-plugin.js.map +1 -0
- package/dist/server/create-server.d.ts +5 -5
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +44 -21
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts +47 -0
- package/dist/server/framework-request-handler.d.ts.map +1 -0
- package/dist/server/framework-request-handler.js +168 -0
- package/dist/server/framework-request-handler.js.map +1 -0
- package/dist/server/google-auth-plugin.d.ts +4 -0
- package/dist/server/google-auth-plugin.d.ts.map +1 -1
- package/dist/server/google-auth-plugin.js +16 -15
- package/dist/server/google-auth-plugin.js.map +1 -1
- package/dist/server/google-oauth.d.ts +72 -0
- package/dist/server/google-oauth.d.ts.map +1 -0
- package/dist/server/google-oauth.js +209 -0
- package/dist/server/google-oauth.js.map +1 -0
- package/dist/server/h3-helpers.d.ts +23 -0
- package/dist/server/h3-helpers.d.ts.map +1 -0
- package/dist/server/h3-helpers.js +37 -0
- package/dist/server/h3-helpers.js.map +1 -0
- package/dist/server/index.d.ts +17 -5
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +19 -4
- package/dist/server/index.js.map +1 -1
- package/dist/server/local-migration.d.ts +32 -0
- package/dist/server/local-migration.d.ts.map +1 -0
- package/dist/server/local-migration.js +205 -0
- package/dist/server/local-migration.js.map +1 -0
- package/dist/server/oauth-helpers.d.ts +14 -0
- package/dist/server/oauth-helpers.d.ts.map +1 -0
- package/dist/server/oauth-helpers.js +23 -0
- package/dist/server/oauth-helpers.js.map +1 -0
- package/dist/server/onboarding-html.d.ts +24 -0
- package/dist/server/onboarding-html.d.ts.map +1 -0
- package/dist/server/onboarding-html.js +347 -0
- package/dist/server/onboarding-html.js.map +1 -0
- package/dist/server/poll.d.ts +45 -0
- package/dist/server/poll.d.ts.map +1 -0
- package/dist/server/poll.js +96 -0
- package/dist/server/poll.js.map +1 -0
- package/dist/server/resources-plugin.d.ts +27 -0
- package/dist/server/resources-plugin.d.ts.map +1 -0
- package/dist/server/resources-plugin.js +75 -0
- package/dist/server/resources-plugin.js.map +1 -0
- package/dist/server/schema-prompt.d.ts +16 -0
- package/dist/server/schema-prompt.d.ts.map +1 -0
- package/dist/server/schema-prompt.js +275 -0
- package/dist/server/schema-prompt.js.map +1 -0
- package/dist/server/script-discovery.d.ts +6 -0
- package/dist/server/script-discovery.d.ts.map +1 -0
- package/dist/server/script-discovery.js +6 -0
- package/dist/server/script-discovery.js.map +1 -0
- package/dist/server/sse.d.ts +4 -21
- package/dist/server/sse.d.ts.map +1 -1
- package/dist/server/sse.js +2 -30
- package/dist/server/sse.js.map +1 -1
- package/dist/server/ssr-handler.d.ts +6 -0
- package/dist/server/ssr-handler.d.ts.map +1 -0
- package/dist/server/ssr-handler.js +55 -0
- package/dist/server/ssr-handler.js.map +1 -0
- package/dist/settings/handlers.d.ts +6 -6
- package/dist/settings/handlers.d.ts.map +1 -1
- package/dist/settings/handlers.js +9 -6
- package/dist/settings/handlers.js.map +1 -1
- package/dist/settings/index.d.ts +2 -1
- package/dist/settings/index.d.ts.map +1 -1
- package/dist/settings/index.js +2 -0
- package/dist/settings/index.js.map +1 -1
- package/dist/settings/org-settings.d.ts +22 -0
- package/dist/settings/org-settings.d.ts.map +1 -0
- package/dist/settings/org-settings.js +45 -0
- package/dist/settings/org-settings.js.map +1 -0
- package/dist/settings/store.d.ts +6 -2
- package/dist/settings/store.d.ts.map +1 -1
- package/dist/settings/store.js +26 -63
- package/dist/settings/store.js.map +1 -1
- package/dist/settings/user-settings.d.ts +3 -2
- package/dist/settings/user-settings.d.ts.map +1 -1
- package/dist/settings/user-settings.js +5 -5
- package/dist/settings/user-settings.js.map +1 -1
- package/dist/shared/agent-chat.d.ts +5 -5
- package/dist/shared/agent-chat.d.ts.map +1 -1
- package/dist/shared/agent-chat.js +8 -8
- package/dist/shared/agent-chat.js.map +1 -1
- package/dist/shared/agent-env.d.ts +1 -1
- package/dist/shared/agent-env.js +1 -1
- package/dist/shared/runtime.d.ts +14 -0
- package/dist/shared/runtime.d.ts.map +1 -0
- package/dist/shared/runtime.js +25 -0
- package/dist/shared/runtime.js.map +1 -0
- package/dist/tailwind.preset.d.ts +7 -6
- package/dist/tailwind.preset.d.ts.map +1 -1
- package/dist/tailwind.preset.js +18 -1
- package/dist/tailwind.preset.js.map +1 -1
- package/dist/templates/default/.agents/skills/actions/SKILL.md +142 -0
- package/dist/templates/default/.agents/skills/agent-engines/SKILL.md +127 -0
- package/dist/templates/default/.agents/skills/capture-learnings/SKILL.md +50 -0
- package/dist/templates/default/.agents/skills/create-skill/SKILL.md +167 -0
- package/dist/templates/default/.agents/skills/delegate-to-agent/SKILL.md +90 -0
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +69 -0
- package/dist/templates/default/.agents/skills/real-time-collab/SKILL.md +183 -0
- package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +112 -0
- package/dist/templates/default/.agents/skills/security/SKILL.md +108 -0
- package/dist/templates/default/.agents/skills/self-modifying-code/SKILL.md +79 -0
- package/{src/templates/default/.agents/skills/files-as-database → dist/templates/default/.agents/skills/storing-data}/SKILL.md +2 -2
- package/dist/templates/default/.claude/settings.json +100 -0
- package/dist/templates/default/.env.example +5 -0
- package/dist/templates/default/.prettierrc +5 -0
- package/dist/templates/default/AGENTS.md +110 -0
- package/dist/templates/default/DEVELOPING.md +117 -0
- package/dist/templates/default/_gitignore +37 -0
- package/{src/templates/default/scripts → dist/templates/default/actions}/hello.ts +1 -1
- package/dist/templates/default/actions/navigate.ts +53 -0
- package/dist/templates/default/actions/view-screen.ts +39 -0
- package/dist/templates/default/app/entry.client.tsx +4 -0
- package/dist/templates/default/app/entry.server.tsx +56 -0
- package/dist/templates/default/app/global.css +95 -0
- package/dist/templates/default/app/lib/utils.ts +1 -0
- package/dist/templates/default/app/root.tsx +107 -0
- package/dist/templates/default/app/routes/_index.tsx +62 -0
- package/dist/templates/default/app/routes.ts +4 -0
- package/dist/templates/default/app/vite-env.d.ts +6 -0
- package/dist/templates/default/components.json +20 -0
- package/dist/templates/default/data/.gitkeep +0 -0
- package/dist/templates/default/data/sync-config.json +1 -0
- package/dist/templates/default/learnings.defaults.md +5 -0
- package/dist/templates/default/learnings.md +0 -0
- package/dist/templates/default/package.json +46 -0
- package/dist/templates/default/postcss.config.js +6 -0
- package/dist/templates/default/public/icon-180.svg +4 -0
- package/dist/templates/default/public/icon-192.svg +4 -0
- package/dist/templates/default/public/icon-512.svg +4 -0
- package/dist/templates/default/public/manifest.json +13 -0
- package/dist/templates/default/react-router.config.ts +6 -0
- package/dist/templates/default/server/middleware/auth.ts +15 -0
- package/dist/templates/default/server/plugins/.gitkeep +0 -0
- package/dist/templates/default/server/routes/[...page].get.ts +5 -0
- package/dist/templates/default/server/routes/api/hello.get.ts +5 -0
- package/dist/templates/default/shared/api.ts +6 -0
- package/dist/templates/default/ssr-entry.ts +20 -0
- package/dist/templates/default/tailwind.config.ts +7 -0
- package/dist/templates/default/tsconfig.json +11 -0
- package/dist/templates/default/vite.config.ts +6 -0
- package/dist/templates/templates/default/.agents/skills/actions/SKILL.md +142 -0
- package/dist/templates/templates/default/.agents/skills/agent-engines/SKILL.md +127 -0
- package/dist/templates/templates/default/.agents/skills/capture-learnings/SKILL.md +50 -0
- package/dist/templates/templates/default/.agents/skills/create-skill/SKILL.md +167 -0
- package/dist/templates/templates/default/.agents/skills/delegate-to-agent/SKILL.md +90 -0
- package/dist/templates/templates/default/.agents/skills/frontend-design/SKILL.md +69 -0
- package/dist/templates/templates/default/.agents/skills/real-time-collab/SKILL.md +183 -0
- package/dist/templates/templates/default/.agents/skills/real-time-sync/SKILL.md +112 -0
- package/dist/templates/templates/default/.agents/skills/security/SKILL.md +108 -0
- package/dist/templates/templates/default/.agents/skills/self-modifying-code/SKILL.md +79 -0
- package/dist/templates/templates/default/.agents/skills/storing-data/SKILL.md +110 -0
- package/dist/templates/templates/default/.claude/settings.json +100 -0
- package/dist/templates/templates/default/.env.example +5 -0
- package/dist/templates/templates/default/.ignore +0 -0
- package/dist/templates/templates/default/.prettierrc +5 -0
- package/dist/templates/templates/default/AGENTS.md +110 -0
- package/dist/templates/templates/default/DEVELOPING.md +117 -0
- package/dist/templates/templates/default/_gitignore +37 -0
- package/dist/templates/templates/default/actions/hello.ts +20 -0
- package/dist/templates/templates/default/actions/navigate.ts +53 -0
- package/dist/templates/templates/default/actions/run.ts +2 -0
- package/dist/templates/templates/default/actions/view-screen.ts +39 -0
- package/dist/templates/templates/default/app/entry.client.tsx +4 -0
- package/dist/templates/templates/default/app/entry.server.tsx +56 -0
- package/dist/templates/templates/default/app/global.css +95 -0
- package/dist/templates/templates/default/app/lib/utils.ts +1 -0
- package/dist/templates/templates/default/app/root.tsx +107 -0
- package/dist/templates/templates/default/app/routes/_index.tsx +62 -0
- package/dist/templates/templates/default/app/routes.ts +4 -0
- package/dist/templates/templates/default/app/vite-env.d.ts +6 -0
- package/dist/templates/templates/default/components.json +20 -0
- package/dist/templates/templates/default/data/.gitkeep +0 -0
- package/dist/templates/templates/default/data/sync-config.json +1 -0
- package/dist/templates/templates/default/learnings.defaults.md +5 -0
- package/dist/templates/templates/default/learnings.md +0 -0
- package/dist/templates/templates/default/package.json +46 -0
- package/dist/templates/templates/default/postcss.config.js +6 -0
- package/dist/templates/templates/default/public/icon-180.svg +4 -0
- package/dist/templates/templates/default/public/icon-192.svg +4 -0
- package/dist/templates/templates/default/public/icon-512.svg +4 -0
- package/dist/templates/templates/default/public/manifest.json +13 -0
- package/dist/templates/templates/default/react-router.config.ts +6 -0
- package/dist/templates/templates/default/server/middleware/auth.ts +15 -0
- package/dist/templates/templates/default/server/plugins/.gitkeep +0 -0
- package/dist/templates/templates/default/server/routes/[...page].get.ts +5 -0
- package/dist/templates/templates/default/server/routes/api/hello.get.ts +5 -0
- package/dist/templates/templates/default/shared/api.ts +6 -0
- package/dist/templates/templates/default/ssr-entry.ts +20 -0
- package/dist/templates/templates/default/tailwind.config.ts +7 -0
- package/dist/templates/templates/default/tsconfig.json +11 -0
- package/dist/templates/templates/default/vite.config.ts +6 -0
- package/dist/terminal/cli-registry.d.ts +2 -2
- package/dist/terminal/cli-registry.d.ts.map +1 -1
- package/dist/terminal/cli-registry.js +8 -8
- package/dist/terminal/cli-registry.js.map +1 -1
- package/dist/terminal/pty-server.d.ts +1 -1
- package/dist/terminal/pty-server.d.ts.map +1 -1
- package/dist/terminal/pty-server.js +94 -18
- package/dist/terminal/pty-server.js.map +1 -1
- package/dist/terminal/terminal-plugin.d.ts +1 -10
- package/dist/terminal/terminal-plugin.d.ts.map +1 -1
- package/dist/terminal/terminal-plugin.js +77 -28
- package/dist/terminal/terminal-plugin.js.map +1 -1
- package/dist/usage/store.d.ts +29 -0
- package/dist/usage/store.d.ts.map +1 -0
- package/dist/usage/store.js +102 -0
- package/dist/usage/store.js.map +1 -0
- package/dist/vite/action-types-plugin.d.ts +13 -0
- package/dist/vite/action-types-plugin.d.ts.map +1 -0
- package/dist/vite/action-types-plugin.js +132 -0
- package/dist/vite/action-types-plugin.js.map +1 -0
- package/dist/vite/agents-bundle-plugin.d.ts +3 -0
- package/dist/vite/agents-bundle-plugin.d.ts.map +1 -0
- package/dist/vite/agents-bundle-plugin.js +87 -0
- package/dist/vite/agents-bundle-plugin.js.map +1 -0
- package/dist/vite/client.d.ts +5 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +310 -19
- package/dist/vite/client.js.map +1 -1
- package/dist/vite/index.d.ts +2 -1
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +2 -1
- package/dist/vite/index.js.map +1 -1
- package/package.json +78 -14
- package/src/templates/default/.agents/skills/actions/SKILL.md +142 -0
- package/src/templates/default/.agents/skills/agent-engines/SKILL.md +127 -0
- package/src/templates/default/.agents/skills/create-skill/SKILL.md +1 -1
- package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +1 -1
- package/src/templates/default/.agents/skills/real-time-collab/SKILL.md +183 -0
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +112 -0
- package/src/templates/default/.agents/skills/security/SKILL.md +108 -0
- package/src/templates/default/.agents/skills/storing-data/SKILL.md +110 -0
- package/src/templates/default/.claude/settings.json +13 -0
- package/src/templates/default/AGENTS.md +72 -164
- package/src/templates/default/DEVELOPING.md +117 -0
- package/src/templates/default/actions/hello.ts +20 -0
- package/src/templates/default/actions/navigate.ts +53 -0
- package/src/templates/default/actions/run.ts +2 -0
- package/src/templates/default/actions/view-screen.ts +39 -0
- package/src/templates/default/app/global.css +2 -2
- package/src/templates/default/app/root.tsx +19 -16
- package/src/templates/default/app/routes/_index.tsx +1 -1
- package/src/templates/default/package.json +6 -2
- package/src/templates/default/server/middleware/auth.ts +15 -0
- package/src/templates/default/server/plugins/.gitkeep +0 -0
- package/src/templates/default/server/routes/[...page].get.ts +2 -9
- package/src/templates/default/ssr-entry.ts +20 -0
- package/dist/a2a/middleware.d.ts +0 -3
- package/dist/a2a/middleware.d.ts.map +0 -1
- package/dist/a2a/middleware.js +0 -36
- package/dist/a2a/middleware.js.map +0 -1
- package/dist/adapters/convex/adapter.d.ts +0 -24
- package/dist/adapters/convex/adapter.d.ts.map +0 -1
- package/dist/adapters/convex/adapter.js +0 -125
- package/dist/adapters/convex/adapter.js.map +0 -1
- package/dist/adapters/convex/index.d.ts +0 -4
- package/dist/adapters/convex/index.d.ts.map +0 -1
- package/dist/adapters/convex/index.js +0 -3
- package/dist/adapters/convex/index.js.map +0 -1
- package/dist/adapters/drizzle/adapter.d.ts +0 -36
- package/dist/adapters/drizzle/adapter.d.ts.map +0 -1
- package/dist/adapters/drizzle/adapter.js +0 -210
- package/dist/adapters/drizzle/adapter.js.map +0 -1
- package/dist/adapters/drizzle/index.d.ts +0 -3
- package/dist/adapters/drizzle/index.d.ts.map +0 -1
- package/dist/adapters/drizzle/index.js +0 -3
- package/dist/adapters/drizzle/index.js.map +0 -1
- package/dist/adapters/drizzle/schema.d.ts +0 -146
- package/dist/adapters/drizzle/schema.d.ts.map +0 -1
- package/dist/adapters/drizzle/schema.js +0 -20
- package/dist/adapters/drizzle/schema.js.map +0 -1
- package/dist/adapters/firestore/adapter.d.ts +0 -48
- package/dist/adapters/firestore/adapter.d.ts.map +0 -1
- package/dist/adapters/firestore/adapter.js +0 -62
- package/dist/adapters/firestore/adapter.js.map +0 -1
- package/dist/adapters/firestore/index.d.ts +0 -4
- package/dist/adapters/firestore/index.d.ts.map +0 -1
- package/dist/adapters/firestore/index.js +0 -3
- package/dist/adapters/firestore/index.js.map +0 -1
- package/dist/adapters/supabase/adapter.d.ts +0 -43
- package/dist/adapters/supabase/adapter.d.ts.map +0 -1
- package/dist/adapters/supabase/adapter.js +0 -137
- package/dist/adapters/supabase/adapter.js.map +0 -1
- package/dist/adapters/supabase/index.d.ts +0 -3
- package/dist/adapters/supabase/index.d.ts.map +0 -1
- package/dist/adapters/supabase/index.js +0 -3
- package/dist/adapters/supabase/index.js.map +0 -1
- package/dist/adapters/sync/config.d.ts +0 -40
- package/dist/adapters/sync/config.d.ts.map +0 -1
- package/dist/adapters/sync/config.js +0 -209
- package/dist/adapters/sync/config.js.map +0 -1
- package/dist/adapters/sync/create-file-sync.d.ts +0 -32
- package/dist/adapters/sync/create-file-sync.d.ts.map +0 -1
- package/dist/adapters/sync/create-file-sync.js +0 -218
- package/dist/adapters/sync/create-file-sync.js.map +0 -1
- package/dist/adapters/sync/file-sync.d.ts +0 -94
- package/dist/adapters/sync/file-sync.d.ts.map +0 -1
- package/dist/adapters/sync/file-sync.js +0 -671
- package/dist/adapters/sync/file-sync.js.map +0 -1
- package/dist/adapters/sync/index.d.ts +0 -6
- package/dist/adapters/sync/index.d.ts.map +0 -1
- package/dist/adapters/sync/index.js +0 -6
- package/dist/adapters/sync/index.js.map +0 -1
- package/dist/adapters/sync/merge.d.ts +0 -21
- package/dist/adapters/sync/merge.d.ts.map +0 -1
- package/dist/adapters/sync/merge.js +0 -132
- package/dist/adapters/sync/merge.js.map +0 -1
- package/dist/adapters/sync/types.d.ts +0 -62
- package/dist/adapters/sync/types.d.ts.map +0 -1
- package/dist/adapters/sync/types.js +0 -23
- package/dist/adapters/sync/types.js.map +0 -1
- package/dist/client/harness.d.ts +0 -48
- package/dist/client/harness.d.ts.map +0 -1
- package/dist/client/harness.js.map +0 -1
- package/dist/client/use-file-sync-status.d.ts +0 -21
- package/dist/client/use-file-sync-status.d.ts.map +0 -1
- package/dist/client/use-file-sync-status.js +0 -65
- package/dist/client/use-file-sync-status.js.map +0 -1
- package/dist/client/use-file-watcher.d.ts +0 -23
- package/dist/client/use-file-watcher.d.ts.map +0 -1
- package/dist/client/use-file-watcher.js +0 -50
- package/dist/client/use-file-watcher.js.map +0 -1
- package/dist/server/default-watcher.d.ts +0 -17
- package/dist/server/default-watcher.d.ts.map +0 -1
- package/dist/server/default-watcher.js +0 -37
- package/dist/server/default-watcher.js.map +0 -1
- package/dist/server/file-sync-plugin.d.ts +0 -7
- package/dist/server/file-sync-plugin.d.ts.map +0 -1
- package/dist/server/file-sync-plugin.js +0 -38
- package/dist/server/file-sync-plugin.js.map +0 -1
- package/dist/vite/dev-api-server.d.ts +0 -10
- package/dist/vite/dev-api-server.d.ts.map +0 -1
- package/dist/vite/dev-api-server.js +0 -160
- package/dist/vite/dev-api-server.js.map +0 -1
- package/src/templates/default/.agents/skills/scripts/SKILL.md +0 -121
- package/src/templates/default/.agents/skills/sse-file-watcher/SKILL.md +0 -80
- package/src/templates/default/server/plugins/agent-chat.ts +0 -1
- package/src/templates/default/server/plugins/auth.ts +0 -1
- package/src/templates/default/server/plugins/file-sync.ts +0 -1
- package/src/templates/default/server/plugins/terminal.ts +0 -1
- package/src/templates/default/server/routes/api/events.get.ts +0 -3
- package/src/templates/default/server/routes/api/file-sync/status.get.ts +0 -4
- /package/{src/templates/default/application-state/.gitkeep → dist/templates/default/.ignore} +0 -0
- /package/{src/templates/default/scripts → dist/templates/default/actions}/run.ts +0 -0
|
@@ -1,30 +1,780 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { getH3App } from "./framework-request-handler.js";
|
|
2
|
+
import { createProductionAgentHandler, runAgentLoop, actionsToEngineTools, getActiveRunForThreadAsync, abortRun, subscribeToRun, } from "../agent/production-agent.js";
|
|
3
|
+
import { resolveEngine, createAnthropicEngine } from "../agent/engine/index.js";
|
|
4
|
+
import { discoverAgents } from "./agent-discovery.js";
|
|
5
|
+
import { loadSchemaPromptBlock } from "./schema-prompt.js";
|
|
6
|
+
import { buildAssistantMessage, extractThreadMeta, } from "../agent/thread-data-builder.js";
|
|
7
|
+
import { defineEventHandler, setResponseStatus, setResponseHeader, getMethod, getQuery, } from "h3";
|
|
8
|
+
import { getSession } from "./auth.js";
|
|
9
|
+
import { createThread, getThread, listThreads, searchThreads, updateThreadData, deleteThread, } from "../chat-threads/store.js";
|
|
10
|
+
import { resourceListAccessible, resourceList, resourceGet, resourceGetByPath, ensurePersonalDefaults, SHARED_OWNER, } from "../resources/store.js";
|
|
11
|
+
import nodePath from "node:path";
|
|
12
|
+
import { readBody } from "./h3-helpers.js";
|
|
13
|
+
// Lazy fs — loaded via dynamic import() on first use.
|
|
14
|
+
// This avoids require() which bundlers convert to createRequire(import.meta.url)
|
|
15
|
+
// that crashes on CF Workers where import.meta.url is undefined.
|
|
16
|
+
let _fs;
|
|
17
|
+
async function lazyFs() {
|
|
18
|
+
if (!_fs) {
|
|
19
|
+
_fs = await import("node:fs");
|
|
20
|
+
}
|
|
21
|
+
return _fs;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Wraps a core CLI script (that writes to console.log) as a ActionEntry
|
|
25
|
+
* by capturing stdout.
|
|
26
|
+
*/
|
|
27
|
+
function wrapCliScript(tool, cliDefault) {
|
|
28
|
+
return {
|
|
29
|
+
tool,
|
|
30
|
+
run: async (args) => {
|
|
31
|
+
const cliArgs = [];
|
|
32
|
+
for (const [k, v] of Object.entries(args)) {
|
|
33
|
+
cliArgs.push(`--${k}`, v);
|
|
34
|
+
}
|
|
35
|
+
const logs = [];
|
|
36
|
+
const origLog = console.log;
|
|
37
|
+
const origError = console.error;
|
|
38
|
+
const origStdoutWrite = process.stdout.write;
|
|
39
|
+
console.log = (...a) => {
|
|
40
|
+
logs.push(a.map(String).join(" "));
|
|
41
|
+
};
|
|
42
|
+
console.error = (...a) => {
|
|
43
|
+
logs.push(a.map(String).join(" "));
|
|
44
|
+
};
|
|
45
|
+
// Intercept process.stdout.write so scripts that write directly
|
|
46
|
+
// (e.g. resource-read) have their output captured
|
|
47
|
+
process.stdout.write = ((chunk, ...rest) => {
|
|
48
|
+
if (typeof chunk === "string") {
|
|
49
|
+
logs.push(chunk);
|
|
50
|
+
}
|
|
51
|
+
else if (Buffer.isBuffer(chunk)) {
|
|
52
|
+
logs.push(chunk.toString());
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
});
|
|
56
|
+
try {
|
|
57
|
+
await cliDefault(cliArgs);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
logs.push(`Error: ${err?.message ?? String(err)}`);
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
console.log = origLog;
|
|
64
|
+
console.error = origError;
|
|
65
|
+
process.stdout.write = origStdoutWrite;
|
|
66
|
+
}
|
|
67
|
+
return logs.join("\n") || "(no output)";
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Creates resource ScriptEntries available in both prod and dev modes.
|
|
73
|
+
*/
|
|
74
|
+
async function createResourceScriptEntries() {
|
|
75
|
+
try {
|
|
76
|
+
const [list, read, write, del] = await Promise.all([
|
|
77
|
+
import("../scripts/resources/list.js"),
|
|
78
|
+
import("../scripts/resources/read.js"),
|
|
79
|
+
import("../scripts/resources/write.js"),
|
|
80
|
+
import("../scripts/resources/delete.js"),
|
|
81
|
+
]);
|
|
82
|
+
return {
|
|
83
|
+
"resource-list": wrapCliScript({
|
|
84
|
+
description: "List resources (persistent files/notes). Returns file paths, sizes, and metadata.",
|
|
85
|
+
parameters: {
|
|
86
|
+
type: "object",
|
|
87
|
+
properties: {
|
|
88
|
+
prefix: {
|
|
89
|
+
type: "string",
|
|
90
|
+
description: "Filter by path prefix (e.g. 'notes/')",
|
|
91
|
+
},
|
|
92
|
+
scope: {
|
|
93
|
+
type: "string",
|
|
94
|
+
description: "Which resources to list: personal, shared, or all (default: all)",
|
|
95
|
+
enum: ["personal", "shared", "all"],
|
|
96
|
+
},
|
|
97
|
+
format: {
|
|
98
|
+
type: "string",
|
|
99
|
+
description: 'Output format: "json" or "text" (default: text)',
|
|
100
|
+
enum: ["json", "text"],
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
}, list.default),
|
|
105
|
+
"resource-read": wrapCliScript({
|
|
106
|
+
description: "Read a resource by path. Returns the file contents.",
|
|
107
|
+
parameters: {
|
|
108
|
+
type: "object",
|
|
109
|
+
properties: {
|
|
110
|
+
path: {
|
|
111
|
+
type: "string",
|
|
112
|
+
description: "Resource path (e.g. 'LEARNINGS.md', 'notes/ideas.md')",
|
|
113
|
+
},
|
|
114
|
+
scope: {
|
|
115
|
+
type: "string",
|
|
116
|
+
description: "personal or shared (default: personal, falls back to shared)",
|
|
117
|
+
enum: ["personal", "shared"],
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
required: ["path"],
|
|
121
|
+
},
|
|
122
|
+
}, read.default),
|
|
123
|
+
"resource-write": wrapCliScript({
|
|
124
|
+
description: "Write or update a resource. Creates the resource if it doesn't exist.",
|
|
125
|
+
parameters: {
|
|
126
|
+
type: "object",
|
|
127
|
+
properties: {
|
|
128
|
+
path: {
|
|
129
|
+
type: "string",
|
|
130
|
+
description: "Resource path (e.g. 'LEARNINGS.md', 'notes/ideas.md')",
|
|
131
|
+
},
|
|
132
|
+
content: {
|
|
133
|
+
type: "string",
|
|
134
|
+
description: "The content to write",
|
|
135
|
+
},
|
|
136
|
+
scope: {
|
|
137
|
+
type: "string",
|
|
138
|
+
description: "personal or shared (default: personal)",
|
|
139
|
+
enum: ["personal", "shared"],
|
|
140
|
+
},
|
|
141
|
+
mime: {
|
|
142
|
+
type: "string",
|
|
143
|
+
description: "MIME type (default: inferred from extension)",
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
required: ["path", "content"],
|
|
147
|
+
},
|
|
148
|
+
}, write.default),
|
|
149
|
+
"resource-delete": wrapCliScript({
|
|
150
|
+
description: "Delete a resource by path.",
|
|
151
|
+
parameters: {
|
|
152
|
+
type: "object",
|
|
153
|
+
properties: {
|
|
154
|
+
path: {
|
|
155
|
+
type: "string",
|
|
156
|
+
description: "Resource path to delete",
|
|
157
|
+
},
|
|
158
|
+
scope: {
|
|
159
|
+
type: "string",
|
|
160
|
+
description: "personal or shared (default: personal)",
|
|
161
|
+
enum: ["personal", "shared"],
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
required: ["path"],
|
|
165
|
+
},
|
|
166
|
+
}, del.default),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
// Resources not available — skip silently
|
|
171
|
+
return {};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Creates chat management ActionEntries (search-chats, open-chat).
|
|
176
|
+
*/
|
|
177
|
+
async function createChatScriptEntries() {
|
|
178
|
+
try {
|
|
179
|
+
const [searchMod, openMod] = await Promise.all([
|
|
180
|
+
import("../scripts/chat/search-chats.js"),
|
|
181
|
+
import("../scripts/chat/open-chat.js"),
|
|
182
|
+
]);
|
|
183
|
+
return {
|
|
184
|
+
"search-chats": wrapCliScript({
|
|
185
|
+
description: "Search or list past agent chat threads. Use this to find previous conversations by keyword.",
|
|
186
|
+
parameters: {
|
|
187
|
+
type: "object",
|
|
188
|
+
properties: {
|
|
189
|
+
query: {
|
|
190
|
+
type: "string",
|
|
191
|
+
description: "Search term to find chats by title, preview, or content",
|
|
192
|
+
},
|
|
193
|
+
limit: {
|
|
194
|
+
type: "string",
|
|
195
|
+
description: "Max number of results (default: 20)",
|
|
196
|
+
},
|
|
197
|
+
format: {
|
|
198
|
+
type: "string",
|
|
199
|
+
description: "Output format",
|
|
200
|
+
enum: ["json", "text"],
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
}, searchMod.default),
|
|
205
|
+
"open-chat": wrapCliScript({
|
|
206
|
+
description: "Open a chat thread in the UI as a new tab and focus it. Use search-chats first to find the thread ID.",
|
|
207
|
+
parameters: {
|
|
208
|
+
type: "object",
|
|
209
|
+
properties: {
|
|
210
|
+
id: {
|
|
211
|
+
type: "string",
|
|
212
|
+
description: "The chat thread ID to open",
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
required: ["id"],
|
|
216
|
+
},
|
|
217
|
+
}, openMod.default),
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return {};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Creates agent engine management tools (list-agent-engines, set-agent-engine,
|
|
226
|
+
* test-agent-engine). Let the agent inspect and configure the active LLM engine.
|
|
227
|
+
*/
|
|
228
|
+
async function createAgentEngineScriptEntries() {
|
|
229
|
+
try {
|
|
230
|
+
const [listMod, setMod, testMod] = await Promise.all([
|
|
231
|
+
import("../scripts/agent-engines/list-agent-engines.js"),
|
|
232
|
+
import("../scripts/agent-engines/set-agent-engine.js"),
|
|
233
|
+
import("../scripts/agent-engines/test-agent-engine.js"),
|
|
234
|
+
]);
|
|
235
|
+
return {
|
|
236
|
+
"list-agent-engines": { tool: listMod.tool, run: listMod.run },
|
|
237
|
+
"set-agent-engine": { tool: setMod.tool, run: setMod.run },
|
|
238
|
+
"test-agent-engine": { tool: testMod.tool, run: testMod.run },
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
return {};
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Creates the call-agent ActionEntry for cross-agent A2A communication.
|
|
247
|
+
* Binds selfAppId so the agent cannot call itself via call-agent.
|
|
248
|
+
*/
|
|
249
|
+
async function createCallAgentScriptEntry(selfAppId) {
|
|
250
|
+
try {
|
|
251
|
+
const mod = await import("../scripts/call-agent.js");
|
|
252
|
+
return {
|
|
253
|
+
"call-agent": {
|
|
254
|
+
tool: mod.tool,
|
|
255
|
+
run: (args, context) => mod.run(args, context, selfAppId),
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return {};
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Creates agent team orchestration tools (spawn-task, task-status, read-task-result).
|
|
265
|
+
* These let the main agent spawn sub-agents and coordinate work.
|
|
266
|
+
*/
|
|
267
|
+
function createTeamTools(deps) {
|
|
268
|
+
return {
|
|
269
|
+
"spawn-task": {
|
|
270
|
+
tool: {
|
|
271
|
+
description: "Spawn a sub-agent to handle a task in the background. The sub-agent runs independently with its own conversation thread. Use this to delegate work so the main chat stays free for new requests. A live preview card will appear in the chat showing the sub-agent's progress.",
|
|
272
|
+
parameters: {
|
|
273
|
+
type: "object",
|
|
274
|
+
properties: {
|
|
275
|
+
task: {
|
|
276
|
+
type: "string",
|
|
277
|
+
description: "Clear description of what the sub-agent should accomplish",
|
|
278
|
+
},
|
|
279
|
+
instructions: {
|
|
280
|
+
type: "string",
|
|
281
|
+
description: "Optional additional instructions or context for the sub-agent",
|
|
282
|
+
},
|
|
283
|
+
name: {
|
|
284
|
+
type: "string",
|
|
285
|
+
description: "Short name for the sub-agent tab (e.g. 'Research', 'Draft email'). If omitted, derived from the task.",
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
required: ["task"],
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
run: async (args) => {
|
|
292
|
+
// Capture the send function NOW (at spawn time) so that
|
|
293
|
+
// concurrent runs don't clobber each other's send reference.
|
|
294
|
+
const capturedSend = deps.getSend();
|
|
295
|
+
const { spawnTask } = await import("./agent-teams.js");
|
|
296
|
+
// Filter out team orchestration tools so sub-agents can't spawn sub-agents
|
|
297
|
+
const teamToolNames = new Set([
|
|
298
|
+
"spawn-task",
|
|
299
|
+
"task-status",
|
|
300
|
+
"read-task-result",
|
|
301
|
+
"send-to-task",
|
|
302
|
+
"list-tasks",
|
|
303
|
+
]);
|
|
304
|
+
const subAgentActions = Object.fromEntries(Object.entries(deps.getActions()).filter(([name]) => !teamToolNames.has(name)));
|
|
305
|
+
const task = await spawnTask({
|
|
306
|
+
description: args.task,
|
|
307
|
+
instructions: args.instructions,
|
|
308
|
+
ownerEmail: deps.getOwner(),
|
|
309
|
+
systemPrompt: deps.getSystemPrompt(),
|
|
310
|
+
actions: subAgentActions,
|
|
311
|
+
engine: deps.getEngine(),
|
|
312
|
+
model: deps.getModel(),
|
|
313
|
+
parentThreadId: deps.getParentThreadId(),
|
|
314
|
+
parentSend: (event) => {
|
|
315
|
+
if (capturedSend)
|
|
316
|
+
capturedSend(event);
|
|
317
|
+
},
|
|
318
|
+
});
|
|
319
|
+
return JSON.stringify({
|
|
320
|
+
taskId: task.taskId,
|
|
321
|
+
threadId: task.threadId,
|
|
322
|
+
status: task.status,
|
|
323
|
+
description: task.description,
|
|
324
|
+
name: args.name || "",
|
|
325
|
+
});
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
"task-status": {
|
|
329
|
+
tool: {
|
|
330
|
+
description: "Check the status of a sub-agent task. Returns current status, preview of output, and current step.",
|
|
331
|
+
parameters: {
|
|
332
|
+
type: "object",
|
|
333
|
+
properties: {
|
|
334
|
+
taskId: {
|
|
335
|
+
type: "string",
|
|
336
|
+
description: "The task ID returned by spawn-task",
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
required: ["taskId"],
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
run: async (args) => {
|
|
343
|
+
const { getTask } = await import("./agent-teams.js");
|
|
344
|
+
const task = await getTask(args.taskId);
|
|
345
|
+
if (!task)
|
|
346
|
+
return JSON.stringify({ error: "Task not found" });
|
|
347
|
+
return JSON.stringify({
|
|
348
|
+
taskId: task.taskId,
|
|
349
|
+
threadId: task.threadId,
|
|
350
|
+
status: task.status,
|
|
351
|
+
description: task.description,
|
|
352
|
+
preview: task.preview,
|
|
353
|
+
currentStep: task.currentStep,
|
|
354
|
+
summary: task.summary,
|
|
355
|
+
});
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
"read-task-result": {
|
|
359
|
+
tool: {
|
|
360
|
+
description: "Read the result of a completed sub-agent task. Returns the full output summary.",
|
|
361
|
+
parameters: {
|
|
362
|
+
type: "object",
|
|
363
|
+
properties: {
|
|
364
|
+
taskId: {
|
|
365
|
+
type: "string",
|
|
366
|
+
description: "The task ID returned by spawn-task",
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
required: ["taskId"],
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
run: async (args) => {
|
|
373
|
+
const { getTask } = await import("./agent-teams.js");
|
|
374
|
+
const task = await getTask(args.taskId);
|
|
375
|
+
if (!task)
|
|
376
|
+
return JSON.stringify({ error: "Task not found" });
|
|
377
|
+
if (task.status === "running") {
|
|
378
|
+
return JSON.stringify({
|
|
379
|
+
status: "running",
|
|
380
|
+
preview: task.preview,
|
|
381
|
+
message: "Task is still running. Check back later.",
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
return JSON.stringify({
|
|
385
|
+
taskId: task.taskId,
|
|
386
|
+
status: task.status,
|
|
387
|
+
summary: task.summary,
|
|
388
|
+
preview: task.preview,
|
|
389
|
+
});
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
"send-to-task": {
|
|
393
|
+
tool: {
|
|
394
|
+
description: "Send a message or update to a running sub-agent. Use this to redirect, add context, or give feedback to a sub-agent while it's working.",
|
|
395
|
+
parameters: {
|
|
396
|
+
type: "object",
|
|
397
|
+
properties: {
|
|
398
|
+
taskId: {
|
|
399
|
+
type: "string",
|
|
400
|
+
description: "The task ID returned by spawn-task",
|
|
401
|
+
},
|
|
402
|
+
message: {
|
|
403
|
+
type: "string",
|
|
404
|
+
description: "Message to send to the sub-agent",
|
|
405
|
+
},
|
|
406
|
+
},
|
|
407
|
+
required: ["taskId", "message"],
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
run: async (args) => {
|
|
411
|
+
const { sendToTask } = await import("./agent-teams.js");
|
|
412
|
+
const result = await sendToTask(args.taskId, args.message);
|
|
413
|
+
return JSON.stringify(result);
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
"list-tasks": {
|
|
417
|
+
tool: {
|
|
418
|
+
description: "List all sub-agent tasks and their current status. Use this to see what's running, completed, or failed.",
|
|
419
|
+
parameters: {
|
|
420
|
+
type: "object",
|
|
421
|
+
properties: {},
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
run: async () => {
|
|
425
|
+
const { listTasks } = await import("./agent-teams.js");
|
|
426
|
+
const tasks = await listTasks();
|
|
427
|
+
if (tasks.length === 0) {
|
|
428
|
+
return "No sub-agent tasks.";
|
|
429
|
+
}
|
|
430
|
+
return JSON.stringify(tasks.map((t) => ({
|
|
431
|
+
taskId: t.taskId,
|
|
432
|
+
threadId: t.threadId,
|
|
433
|
+
description: t.description,
|
|
434
|
+
status: t.status,
|
|
435
|
+
currentStep: t.currentStep,
|
|
436
|
+
hasResult: t.summary.length > 0,
|
|
437
|
+
})), null, 2);
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Framework-level instructions injected into every agent's system prompt.
|
|
444
|
+
* This is the single source of truth for the core philosophy, rules, and patterns.
|
|
445
|
+
* Template AGENTS.md resources only need template-specific content.
|
|
446
|
+
*/
|
|
447
|
+
/**
|
|
448
|
+
* Framework instructions shared across both modes. The mode-specific
|
|
449
|
+
* preamble is prepended by the prompt composition below.
|
|
450
|
+
*/
|
|
451
|
+
const FRAMEWORK_CORE = `
|
|
452
|
+
### Core Rules
|
|
453
|
+
|
|
454
|
+
1. **Data lives in SQL** — All app state is in a SQL database (could be SQLite, Postgres, Turso, or Cloudflare D1 — never assume which). Use the available database tools.
|
|
455
|
+
2. **Context awareness** — The user's current screen state is automatically included in each message as a \`<current-screen>\` block. Use it to understand what the user is looking at. You can still call \`view-screen\` for a more detailed snapshot if needed, but you should NOT need to call it before every action.
|
|
456
|
+
3. **Navigate the UI** — Use the \`navigate\` tool to switch views, open items, or focus elements for the user.
|
|
457
|
+
4. **Application state** — Ephemeral UI state (drafts, selections, navigation) lives in \`application_state\`. Use \`readAppState\`/\`writeAppState\` to read and write it. When you write state, the UI updates automatically.
|
|
458
|
+
5. **Resources for memory** — Use the Resources system for persistent notes and context. Update LEARNINGS.md when you learn user preferences or corrections. Update the shared AGENTS.md for instructions that should apply to all users.
|
|
459
|
+
|
|
460
|
+
### Resources
|
|
461
|
+
|
|
462
|
+
You have access to a Resources system for persistent notes, learnings, and context files.
|
|
463
|
+
Use resource-list, resource-read, resource-write, and resource-delete to manage resources.
|
|
464
|
+
Resources can be personal (per-user) or shared (team-wide). By default, resources are personal.
|
|
465
|
+
|
|
466
|
+
When you learn something important (user corrections, preferences, patterns), update the "LEARNINGS.md" resource. Keep it tidy — revise, consolidate, and remove outdated entries rather than only appending.
|
|
467
|
+
When the user gives instructions that should apply to all users/sessions, update the shared "AGENTS.md" resource instead.
|
|
468
|
+
|
|
469
|
+
### Navigation Rule
|
|
470
|
+
|
|
471
|
+
When the user says "show me", "go to", "open", "switch to", or similar navigation language, ALWAYS use the \`navigate\` action to update the UI. The user expects to SEE the result in the main app, not just read it in chat. Navigate first, then fetch/display data.
|
|
472
|
+
|
|
473
|
+
### Chat History
|
|
474
|
+
|
|
475
|
+
You can search and restore previous chat conversations:
|
|
476
|
+
- \`search-chats\` — Search or list past chat threads by keyword
|
|
477
|
+
- \`open-chat\` — Open a chat thread in the UI as a new tab and focus it
|
|
478
|
+
|
|
479
|
+
When the user asks to find a previous conversation, use \`search-chats\` first to find matching threads, then \`open-chat\` to restore the one they want.
|
|
480
|
+
|
|
481
|
+
### Agent Teams — Orchestration
|
|
482
|
+
|
|
483
|
+
You are an orchestrator. For complex or multi-step tasks, delegate to sub-agents:
|
|
484
|
+
- \`spawn-task\` — Spawn a sub-agent for a task. It runs in its own thread while you stay available. A live preview card appears in the chat.
|
|
485
|
+
- \`task-status\` — Check the progress of a running sub-agent.
|
|
486
|
+
- \`read-task-result\` — Read the result when a sub-agent finishes.
|
|
487
|
+
|
|
488
|
+
**When to delegate vs do directly:**
|
|
489
|
+
- **Delegate** when the task involves multiple tool calls, research, content generation, or anything that takes more than a few seconds. Examples: "create a deck about X", "analyze the data and write a report", "look up Y and draft an email about it".
|
|
490
|
+
- **Do directly** for quick single-step tasks like navigation, reading state, or answering simple questions.
|
|
491
|
+
- **Spawn multiple sub-agents** when the user asks for multiple independent things — they'll run in parallel.
|
|
492
|
+
|
|
493
|
+
**How to orchestrate:**
|
|
494
|
+
1. When the user asks for something complex, spawn a sub-agent with a clear task description.
|
|
495
|
+
2. Tell the user what you've started ("I'm having a sub-agent research that for you").
|
|
496
|
+
3. You can keep chatting — sub-agents run independently.
|
|
497
|
+
4. Use \`read-task-result\` to check results when needed, or the user can see live progress in the card.
|
|
498
|
+
5. If the user's request has multiple steps, you can spawn one sub-agent per step, or chain them.
|
|
499
|
+
|
|
500
|
+
Sub-agents have access to all template tools but **cannot spawn sub-agents themselves** — only you (the orchestrator) can do that. Give the sub-agent a specific, actionable task description — it will figure out which tools to use.
|
|
4
501
|
|
|
5
|
-
|
|
6
|
-
const DEFAULT_DEV_PROMPT = `You are a development assistant with full access to the project filesystem, shell, and database.
|
|
502
|
+
### Recurring Jobs
|
|
7
503
|
|
|
8
|
-
You can
|
|
9
|
-
- Read, write, and edit any file in the project (read-file, write-file)
|
|
10
|
-
- List and search files (list-files, search-files)
|
|
11
|
-
- Run shell commands (shell) — use for git, build, install, etc.
|
|
12
|
-
- Query and modify the database (db-schema, db-query, db-exec)
|
|
13
|
-
- Plus all application-specific tools
|
|
504
|
+
You can create recurring jobs that run on a cron schedule. Jobs are resource files under \`jobs/\`. Each job has a cron schedule and instructions that the agent executes automatically.
|
|
14
505
|
|
|
15
|
-
|
|
506
|
+
- \`create-job\` — Create a new recurring job with a cron schedule and instructions
|
|
507
|
+
- \`list-jobs\` — List all recurring jobs and their status (schedule, last run, next run, errors)
|
|
508
|
+
- \`update-job\` — Update a job's schedule, instructions, or toggle enabled/disabled
|
|
509
|
+
- Delete a job with \`resource-delete --path jobs/<name>.md\`
|
|
16
510
|
|
|
511
|
+
When the user asks for something recurring ("every morning", "daily at 9am", "weekly on Mondays"), create a job. Convert natural language to 5-field cron format:
|
|
512
|
+
- "every morning" / "daily at 9am" → \`0 9 * * *\`
|
|
513
|
+
- "every weekday at 9am" → \`0 9 * * 1-5\`
|
|
514
|
+
- "every hour" → \`0 * * * *\`
|
|
515
|
+
- "every 30 minutes" → \`*/30 * * * *\`
|
|
516
|
+
- "every monday at 9am" → \`0 9 * * 1\`
|
|
517
|
+
- "twice a day" / "morning and evening" → \`0 9,17 * * *\`
|
|
518
|
+
|
|
519
|
+
Job instructions should be self-contained — include which actions to call, what conditions to check, and what to do with results. The agent executing the job has access to all the same tools you do.
|
|
520
|
+
|
|
521
|
+
### call-agent — External Apps Only
|
|
522
|
+
|
|
523
|
+
The \`call-agent\` tool sends a message to a DIFFERENT, separately-deployed app's agent (A2A protocol). It is **not** for calling actions within the current app.
|
|
524
|
+
|
|
525
|
+
**NEVER use \`call-agent\` to:**
|
|
526
|
+
- Call your own app by name (if you are the "macros" agent, never do \`call-agent(agent="macros")\`)
|
|
527
|
+
- Perform tasks you can accomplish with your own registered tools
|
|
528
|
+
- Wrap your own actions in an A2A round-trip
|
|
529
|
+
|
|
530
|
+
**ONLY use \`call-agent\` when:**
|
|
531
|
+
- The user explicitly asks you to communicate with a different app (e.g., "ask the mail agent to...")
|
|
532
|
+
- You need data that only another deployed app can provide
|
|
533
|
+
- You are coordinating across genuinely separate apps
|
|
534
|
+
|
|
535
|
+
If \`call-agent\` returns an error saying the agent is yourself — stop and use your own tools instead.
|
|
536
|
+
|
|
537
|
+
### Auto-Memory
|
|
538
|
+
|
|
539
|
+
Proactively update \`LEARNINGS.md\` when you learn something important during conversations:
|
|
540
|
+
- User corrects your approach → capture the correct way
|
|
541
|
+
- User shares preferences (tone, style, workflow) → capture them
|
|
542
|
+
- You discover a non-obvious pattern or gotcha → capture it
|
|
543
|
+
- User provides personal context (contacts, team info, domain knowledge) → capture it
|
|
544
|
+
|
|
545
|
+
**Don't ask permission — just save it.** Keep entries concise (one line each, grouped by category). Don't save things that are obvious from reading the code or that are temporary.
|
|
17
546
|
`;
|
|
547
|
+
const PROD_FRAMEWORK_PROMPT = `## Agent-Native Framework — Production Mode
|
|
548
|
+
|
|
549
|
+
You are an AI agent in an agent-native application, running in **production mode**.
|
|
550
|
+
|
|
551
|
+
The agent and the UI are equal partners — everything the UI can do, you can do via your tools, and vice versa. They share the same SQL database and stay in sync automatically.
|
|
552
|
+
|
|
553
|
+
**In production mode, you operate through registered actions exposed as tools.** These are your capabilities — use them to read data, take actions, and help the user. You cannot edit source code or access the filesystem directly. Your tools are the app's API.
|
|
554
|
+
|
|
555
|
+
### Code Changes Not Available
|
|
556
|
+
|
|
557
|
+
When the user asks you to change the UI, modify code, add features, fix bugs in the app itself, change styles, or do anything that requires editing source files — you MUST respond with this exact message (replacing APP_NAME with the current app name from the URL hostname):
|
|
558
|
+
|
|
559
|
+
> This app is running in hosted mode and I can't make code changes here. To customize this app:
|
|
560
|
+
>
|
|
561
|
+
> **Option 1:** Connect to [Builder.io](https://www.builder.io/m/agent-native) for a full development environment
|
|
562
|
+
>
|
|
563
|
+
> **Option 2:** Clone and run locally:
|
|
564
|
+
> \`\`\`
|
|
565
|
+
> npx agent-native create APP_NAME
|
|
566
|
+
> \`\`\`
|
|
567
|
+
|
|
568
|
+
Do NOT attempt to work around this limitation. Do NOT say "I can't do that" without providing the options above. Always include both the Builder.io link and the CLI command.
|
|
569
|
+
${FRAMEWORK_CORE}`;
|
|
570
|
+
const DEV_FRAMEWORK_PROMPT = `## Agent-Native Framework — Development Mode
|
|
571
|
+
|
|
572
|
+
You are an AI agent in an agent-native application, running in **development mode**.
|
|
573
|
+
|
|
574
|
+
The agent and the UI are equal partners — everything the UI can do, you can do via tools/scripts, and vice versa. They share the same SQL database and stay in sync automatically.
|
|
575
|
+
|
|
576
|
+
**In development mode, you have UNRESTRICTED access.** You can:
|
|
577
|
+
- Run ANY shell command via the \`shell\` tool (bash, node, curl, pnpm, etc.)
|
|
578
|
+
- Execute arbitrary code: \`shell({ command: 'node -e "console.log(1+1)"' })\`
|
|
579
|
+
- Read/write any file on the filesystem
|
|
580
|
+
- Query and modify the database
|
|
581
|
+
- Call external APIs (via shell with curl, or via scripts)
|
|
582
|
+
- Edit source code, install packages, modify the app
|
|
583
|
+
|
|
584
|
+
**There are NO restrictions in dev mode.** If a dedicated tool/action doesn't exist for what you need, use \`shell\` to run any command. For example: \`shell({ command: 'curl -s https://api.example.com/data' })\`
|
|
585
|
+
|
|
586
|
+
**Template-specific actions are invoked via shell, NOT as direct tools.** In dev mode, the only tools registered as native tool calls are framework-level utilities (shell, file ops, resources, chat, teams, jobs). Anything from the template's \`actions/\` directory must be run through shell: \`shell({ command: 'pnpm action <name> --arg value' })\`. The "Available Actions" section below shows the exact CLI syntax for each one — copy that command verbatim and pass it to \`shell\`. Do not try to call template actions by name as if they were tools; they will not appear in your tool list.
|
|
587
|
+
|
|
588
|
+
When editing code, follow the agent-native architecture:
|
|
589
|
+
- Every feature needs all four areas: UI + scripts + skills/instructions + application-state sync
|
|
590
|
+
- All SQL must be dialect-agnostic (works on SQLite and Postgres)
|
|
591
|
+
- No Node.js-specific APIs in server routes (must work on Cloudflare Workers, etc.)
|
|
592
|
+
- Use shadcn/ui components and Tabler Icons for all UI work
|
|
593
|
+
${FRAMEWORK_CORE}`;
|
|
594
|
+
const DEFAULT_SYSTEM_PROMPT = PROD_FRAMEWORK_PROMPT;
|
|
595
|
+
/**
|
|
596
|
+
* Pre-load the agent's context: AGENTS.md (template instructions), the skills
|
|
597
|
+
* index, and LEARNINGS.md (user notes). These all get appended to the system
|
|
598
|
+
* prompt so the agent has everything it needs from the first turn — no tool
|
|
599
|
+
* calls required to figure out "what is this app".
|
|
600
|
+
*
|
|
601
|
+
* Three sources are layered:
|
|
602
|
+
*
|
|
603
|
+
* 1. `<template>` — AGENTS.md + skills index from the `virtual:agents-bundle`
|
|
604
|
+
* module (inlined at build time by the Vite plugin, falls back to a
|
|
605
|
+
* filesystem read from `process.cwd()` in dev). Canonical source for
|
|
606
|
+
* "what is this app, what can it do, what skills are available".
|
|
607
|
+
* 2. `<shared>` — LEARNINGS.md from the SQL shared scope. Team-level notes.
|
|
608
|
+
* 3. `<personal>` — LEARNINGS.md from the SQL personal scope. The current
|
|
609
|
+
* user's own notes.
|
|
610
|
+
*
|
|
611
|
+
* Each source is read independently — no copying between them. Editing
|
|
612
|
+
* AGENTS.md and restarting the server is all it takes; Vite HMR invalidates
|
|
613
|
+
* the bundle in dev so changes land instantly.
|
|
614
|
+
*/
|
|
615
|
+
async function loadResourcesForPrompt(owner) {
|
|
616
|
+
await ensurePersonalDefaults(owner);
|
|
617
|
+
const sections = [];
|
|
618
|
+
// 1. Template AGENTS.md + skills index — from the virtual bundle.
|
|
619
|
+
try {
|
|
620
|
+
const { loadAgentsBundle, generateSkillsPromptBlock } = await import("./agents-bundle.js");
|
|
621
|
+
const bundle = await loadAgentsBundle();
|
|
622
|
+
if (bundle.agentsMd.trim()) {
|
|
623
|
+
sections.push(`<resource name="AGENTS.md" scope="template">\n${bundle.agentsMd.trim()}\n</resource>`);
|
|
624
|
+
}
|
|
625
|
+
const skillsBlock = generateSkillsPromptBlock(bundle);
|
|
626
|
+
if (skillsBlock)
|
|
627
|
+
sections.push(skillsBlock);
|
|
628
|
+
}
|
|
629
|
+
catch { }
|
|
630
|
+
// LEARNINGS.md from SQL (template-level instructions are in AGENTS.md above).
|
|
631
|
+
// 2. Shared SQL scope
|
|
632
|
+
try {
|
|
633
|
+
const shared = await resourceGetByPath(SHARED_OWNER, "LEARNINGS.md");
|
|
634
|
+
if (shared?.content?.trim()) {
|
|
635
|
+
sections.push(`<resource name="LEARNINGS.md" scope="shared">\n${shared.content.trim()}\n</resource>`);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
catch { }
|
|
639
|
+
// 3. Personal SQL scope (skip if owner is the shared sentinel)
|
|
640
|
+
if (owner !== SHARED_OWNER) {
|
|
641
|
+
try {
|
|
642
|
+
const personal = await resourceGetByPath(owner, "LEARNINGS.md");
|
|
643
|
+
if (personal?.content?.trim()) {
|
|
644
|
+
sections.push(`<resource name="LEARNINGS.md" scope="personal">\n${personal.content.trim()}\n</resource>`);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
catch { }
|
|
648
|
+
}
|
|
649
|
+
if (sections.length === 0)
|
|
650
|
+
return "";
|
|
651
|
+
return ("\n\nThe following resources contain template-specific instructions and user context. Use the information in them to help the user.\n\n" +
|
|
652
|
+
sections.join("\n\n"));
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Build the per-request SQL-schema context block. Reads AGENT_ORG_ID live
|
|
656
|
+
* from the environment so scheduler/A2A/HTTP call sites all see whatever
|
|
657
|
+
* org was just resolved for this request.
|
|
658
|
+
*/
|
|
659
|
+
async function buildSchemaBlock(owner, hasRawDbTools) {
|
|
660
|
+
try {
|
|
661
|
+
return await loadSchemaPromptBlock({
|
|
662
|
+
owner,
|
|
663
|
+
orgId: process.env.AGENT_ORG_ID ?? null,
|
|
664
|
+
hasRawDbTools,
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
catch {
|
|
668
|
+
return "";
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
/** @deprecated Kept for backward compat — dev prompt is now part of DEV_FRAMEWORK_PROMPT */
|
|
672
|
+
const DEFAULT_DEV_PROMPT = "";
|
|
673
|
+
/**
|
|
674
|
+
* Generates a system prompt section describing registered template actions.
|
|
675
|
+
* This helps the agent prefer template-specific actions over raw db-query/db-exec.
|
|
676
|
+
*
|
|
677
|
+
* Two output modes:
|
|
678
|
+
*
|
|
679
|
+
* - `"tool"` — used in production, where template actions are registered
|
|
680
|
+
* as native Anthropic tools. Output reads `name(arg*: type; ...) — desc`.
|
|
681
|
+
* - `"cli"` — used in dev, where template actions are NOT registered as
|
|
682
|
+
* native tools and must be invoked via `shell(command="pnpm action ...")`.
|
|
683
|
+
* Output reads `pnpm action name --arg <type> [--opt <type>] — desc`.
|
|
684
|
+
*/
|
|
685
|
+
function generateActionsPrompt(registry, mode = "tool") {
|
|
686
|
+
if (!registry || Object.keys(registry).length === 0)
|
|
687
|
+
return "";
|
|
688
|
+
const lines = Object.entries(registry).map(([name, entry]) => {
|
|
689
|
+
const desc = entry.tool.description;
|
|
690
|
+
const params = entry.tool.parameters?.properties;
|
|
691
|
+
const requiredFields = new Set(entry.tool.parameters?.required ?? []);
|
|
692
|
+
if (mode === "cli") {
|
|
693
|
+
// CLI mode: emit `pnpm action <name> --required <type> [--optional <type>]`
|
|
694
|
+
if (!params || Object.keys(params).length === 0) {
|
|
695
|
+
return `- \`pnpm action ${name}\` — ${desc}`;
|
|
696
|
+
}
|
|
697
|
+
const entries = Object.entries(params);
|
|
698
|
+
// Required first (alphabetical), then optional (alphabetical)
|
|
699
|
+
entries.sort(([a], [b]) => {
|
|
700
|
+
const ar = requiredFields.has(a) ? 0 : 1;
|
|
701
|
+
const br = requiredFields.has(b) ? 0 : 1;
|
|
702
|
+
if (ar !== br)
|
|
703
|
+
return ar - br;
|
|
704
|
+
return a.localeCompare(b);
|
|
705
|
+
});
|
|
706
|
+
const required = [];
|
|
707
|
+
const optional = [];
|
|
708
|
+
const requiredNames = [];
|
|
709
|
+
for (const [k, v] of entries) {
|
|
710
|
+
const type = v.type ?? "any";
|
|
711
|
+
const flag = `--${k} <${type}>`;
|
|
712
|
+
if (requiredFields.has(k)) {
|
|
713
|
+
required.push(flag);
|
|
714
|
+
requiredNames.push(`--${k}`);
|
|
715
|
+
}
|
|
716
|
+
else {
|
|
717
|
+
optional.push(`[${flag}]`);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
const cmd = ["pnpm action " + name, ...required, ...optional].join(" ");
|
|
721
|
+
const requiredNote = requiredNames.length > 0
|
|
722
|
+
? ` Required: ${requiredNames.join(", ")}.`
|
|
723
|
+
: "";
|
|
724
|
+
return `- \`${cmd}\` — ${desc}.${requiredNote}`;
|
|
725
|
+
}
|
|
726
|
+
// tool mode (production / native tool calls)
|
|
727
|
+
if (params) {
|
|
728
|
+
// Order required params first, then optional. Mark required with "*"
|
|
729
|
+
// and include type + description so the agent knows exactly how to call.
|
|
730
|
+
const entries = Object.entries(params);
|
|
731
|
+
entries.sort(([a], [b]) => {
|
|
732
|
+
const ar = requiredFields.has(a) ? 0 : 1;
|
|
733
|
+
const br = requiredFields.has(b) ? 0 : 1;
|
|
734
|
+
if (ar !== br)
|
|
735
|
+
return ar - br;
|
|
736
|
+
return a.localeCompare(b);
|
|
737
|
+
});
|
|
738
|
+
const paramList = entries
|
|
739
|
+
.map(([k, v]) => {
|
|
740
|
+
const isRequired = requiredFields.has(k);
|
|
741
|
+
const type = v.type ?? "any";
|
|
742
|
+
const marker = isRequired ? "*" : "?";
|
|
743
|
+
const descPart = v.description ? ` — ${v.description}` : "";
|
|
744
|
+
return `${k}${marker}: ${type}${descPart}`;
|
|
745
|
+
})
|
|
746
|
+
.join("; ");
|
|
747
|
+
return `- \`${name}\`(${paramList}) — ${desc}`;
|
|
748
|
+
}
|
|
749
|
+
return `- \`${name}\`() — ${desc}`;
|
|
750
|
+
});
|
|
751
|
+
if (mode === "cli") {
|
|
752
|
+
return `\n\n## Available Actions
|
|
753
|
+
|
|
754
|
+
**These template actions are NOT exposed as direct tools in dev mode. To run any of them, use the \`shell\` tool with the exact command shown below.** Example: \`shell(command="pnpm action add-slide --deckId abc --content 'Hello'")\`.
|
|
755
|
+
|
|
756
|
+
Do NOT try to call these by name as if they were tools — they will not exist in your tool list. Always go through \`shell\`.
|
|
757
|
+
|
|
758
|
+
${lines.join("\n")}`;
|
|
759
|
+
}
|
|
760
|
+
return `\n\n## Available Actions
|
|
761
|
+
|
|
762
|
+
**Use these actions directly to accomplish tasks. Do NOT use \`db-schema\`, \`search-files\`, or \`shell\` to explore the app — these actions already connect to the correct database and services.**
|
|
763
|
+
|
|
764
|
+
Parameter notation: \`name*\` = required, \`name?\` = optional. Always pass the tool's parameters as a JSON object to the tool_use call — never via shell or string-concatenated CLI flags.
|
|
765
|
+
|
|
766
|
+
${lines.join("\n")}`;
|
|
767
|
+
}
|
|
18
768
|
/**
|
|
19
769
|
* Creates a Nitro plugin that mounts the agent chat endpoint.
|
|
20
770
|
*
|
|
21
771
|
* In dev mode (NODE_ENV !== "production"), automatically includes
|
|
22
|
-
* file system, shell, and database tools alongside any template-specific
|
|
772
|
+
* file system, shell, and database tools alongside any template-specific actions.
|
|
23
773
|
*
|
|
24
774
|
* Usage in templates:
|
|
25
775
|
* ```ts
|
|
26
776
|
* // server/plugins/agent-chat.ts
|
|
27
|
-
* import { createAgentChatPlugin } from "@agent-native/core/server";
|
|
777
|
+
* import { readBody, createAgentChatPlugin } from "@agent-native/core/server";
|
|
28
778
|
* import { scriptRegistry } from "../../scripts/registry.js";
|
|
29
779
|
*
|
|
30
780
|
* export default createAgentChatPlugin({
|
|
@@ -33,38 +783,682 @@ When editing code, maintain existing patterns and conventions. After writing fil
|
|
|
33
783
|
* });
|
|
34
784
|
* ```
|
|
35
785
|
*/
|
|
786
|
+
async function collectFiles(dir, prefix, depth, results) {
|
|
787
|
+
if (depth > 4 || results.length >= 500)
|
|
788
|
+
return;
|
|
789
|
+
const skip = new Set([
|
|
790
|
+
"node_modules",
|
|
791
|
+
".git",
|
|
792
|
+
".next",
|
|
793
|
+
".output",
|
|
794
|
+
"dist",
|
|
795
|
+
".cache",
|
|
796
|
+
".turbo",
|
|
797
|
+
"data",
|
|
798
|
+
]);
|
|
799
|
+
let entries;
|
|
800
|
+
try {
|
|
801
|
+
const fs = await lazyFs();
|
|
802
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
803
|
+
}
|
|
804
|
+
catch {
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
for (const entry of entries) {
|
|
808
|
+
if (results.length >= 500)
|
|
809
|
+
return;
|
|
810
|
+
if (skip.has(entry.name) || entry.name.startsWith("."))
|
|
811
|
+
continue;
|
|
812
|
+
const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
813
|
+
const isDir = entry.isDirectory();
|
|
814
|
+
results.push({
|
|
815
|
+
path: relPath,
|
|
816
|
+
name: entry.name,
|
|
817
|
+
type: isDir ? "folder" : "file",
|
|
818
|
+
});
|
|
819
|
+
if (isDir)
|
|
820
|
+
await collectFiles(nodePath.join(dir, entry.name), relPath, depth + 1, results);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
function parseSkillFrontmatter(content) {
|
|
824
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
825
|
+
if (!match)
|
|
826
|
+
return {};
|
|
827
|
+
const fm = match[1];
|
|
828
|
+
const name = fm.match(/^name:\s*(.+)$/m)?.[1]?.trim();
|
|
829
|
+
const description = fm.match(/^description:\s*(.+)$/m)?.[1]?.trim();
|
|
830
|
+
return { name, description };
|
|
831
|
+
}
|
|
832
|
+
function isLocalhost(event) {
|
|
833
|
+
try {
|
|
834
|
+
const host = event.node?.req?.headers?.host || event.headers?.get?.("host") || "";
|
|
835
|
+
const hostname = host.split(":")[0];
|
|
836
|
+
return (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1");
|
|
837
|
+
}
|
|
838
|
+
catch {
|
|
839
|
+
return false;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
36
842
|
export function createAgentChatPlugin(options) {
|
|
37
843
|
return async (nitroApp) => {
|
|
844
|
+
// Wait for default framework plugins (auth, core-routes, integrations, ...)
|
|
845
|
+
// to finish mounting their middleware before we register our own. Without
|
|
846
|
+
// this, requests can race ahead of the bootstrap and hit the SSR catch-all.
|
|
847
|
+
const { awaitBootstrap } = await import("./framework-request-handler.js");
|
|
848
|
+
await awaitBootstrap(nitroApp);
|
|
38
849
|
const env = process.env.NODE_ENV;
|
|
39
850
|
// AGENT_MODE=production forces production agent constraints even in dev
|
|
40
|
-
const
|
|
851
|
+
const canToggle = (env === "development" || env === "test") &&
|
|
41
852
|
process.env.AGENT_MODE !== "production";
|
|
42
|
-
const routePath = options?.path ?? "/
|
|
43
|
-
// Resolve
|
|
44
|
-
const
|
|
45
|
-
const templateScripts = typeof
|
|
46
|
-
? await
|
|
47
|
-
: (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
853
|
+
const routePath = options?.path ?? "/_agent-native/agent-chat";
|
|
854
|
+
// Resolve actions — prefer `actions`, fall back to deprecated `scripts`
|
|
855
|
+
const rawActions = options?.actions ?? options?.scripts;
|
|
856
|
+
const templateScripts = typeof rawActions === "function"
|
|
857
|
+
? await rawActions()
|
|
858
|
+
: (rawActions ?? {});
|
|
859
|
+
// Resource, chat, and cross-agent scripts are available in both prod and dev modes
|
|
860
|
+
const resourceScripts = await createResourceScriptEntries();
|
|
861
|
+
const engineScripts = await createAgentEngineScriptEntries();
|
|
862
|
+
const chatScripts = {
|
|
863
|
+
...(await createChatScriptEntries()),
|
|
864
|
+
...engineScripts,
|
|
865
|
+
};
|
|
866
|
+
const callAgentScript = await createCallAgentScriptEntry(options?.appId);
|
|
867
|
+
// Auto-mount A2A protocol endpoints so every app is discoverable
|
|
868
|
+
// and callable by other agents via the standard protocol.
|
|
869
|
+
// In dev mode, include dev scripts (filesystem-discovered) so the A2A agent
|
|
870
|
+
// has access to the same tools as the interactive agent.
|
|
871
|
+
let devScriptsForA2A = {};
|
|
872
|
+
let discoveredActions = {};
|
|
873
|
+
if (canToggle) {
|
|
874
|
+
try {
|
|
875
|
+
const { createDevScriptRegistry } = await import("../scripts/dev/index.js");
|
|
876
|
+
devScriptsForA2A = await createDevScriptRegistry();
|
|
877
|
+
}
|
|
878
|
+
catch { }
|
|
879
|
+
// Auto-discover template action files and register as shell-based tools.
|
|
880
|
+
// This ensures templates without a custom agent-chat plugin (e.g., analytics)
|
|
881
|
+
// still have their domain actions available as tools.
|
|
882
|
+
try {
|
|
883
|
+
const fs = await import("fs");
|
|
884
|
+
const pathMod = await import("path");
|
|
885
|
+
const cwd = process.cwd();
|
|
886
|
+
const skipFiles = new Set([
|
|
887
|
+
"helpers",
|
|
888
|
+
"run",
|
|
889
|
+
"registry",
|
|
890
|
+
"_utils",
|
|
891
|
+
"db-connect",
|
|
892
|
+
"db-status",
|
|
893
|
+
]);
|
|
894
|
+
for (const dir of ["actions", "scripts"]) {
|
|
895
|
+
const actionsDir = pathMod.join(cwd, dir);
|
|
896
|
+
const _fs = await lazyFs();
|
|
897
|
+
if (!_fs.existsSync(actionsDir))
|
|
898
|
+
continue;
|
|
899
|
+
const files = _fs
|
|
900
|
+
.readdirSync(actionsDir)
|
|
901
|
+
.filter((f) => f.endsWith(".ts") &&
|
|
902
|
+
!f.startsWith("_") &&
|
|
903
|
+
!skipFiles.has(f.replace(/\.ts$/, "")));
|
|
904
|
+
for (const file of files) {
|
|
905
|
+
const name = file.replace(/\.ts$/, "");
|
|
906
|
+
if (templateScripts[name] || devScriptsForA2A[name])
|
|
907
|
+
continue;
|
|
908
|
+
// Try to load the action module directly so we get the real
|
|
909
|
+
// run function (not a shell wrapper). This makes HTTP endpoints
|
|
910
|
+
// work correctly. Only fall back to shell wrapper if the import
|
|
911
|
+
// fails (e.g., CLI-style scripts that throw at top level).
|
|
912
|
+
const filePath = pathMod.join(actionsDir, file);
|
|
913
|
+
try {
|
|
914
|
+
const mod = await import(/* @vite-ignore */ filePath);
|
|
915
|
+
const def = mod.default && typeof mod.default === "object"
|
|
916
|
+
? mod.default
|
|
917
|
+
: mod;
|
|
918
|
+
if (def?.tool && typeof def.run === "function") {
|
|
919
|
+
discoveredActions[name] = {
|
|
920
|
+
tool: def.tool,
|
|
921
|
+
run: def.run,
|
|
922
|
+
...(def.http !== undefined ? { http: def.http } : {}),
|
|
923
|
+
};
|
|
924
|
+
continue;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
catch {
|
|
928
|
+
// Fall through to shell wrapper for CLI-style scripts
|
|
929
|
+
// (and .ts files Node can't parse natively).
|
|
930
|
+
}
|
|
931
|
+
// Static-parse the source for `http: false` or
|
|
932
|
+
// `http: { method: "GET" }` so the shell-wrapper fallback still
|
|
933
|
+
// mounts HTTP routes with the correct method. We can't load the
|
|
934
|
+
// .ts module to read the real defineAction object in this Node
|
|
935
|
+
// context, so this regex sniff is the best we can do until the
|
|
936
|
+
// discovery is moved into a Vite-aware codepath.
|
|
937
|
+
let httpConfig;
|
|
938
|
+
try {
|
|
939
|
+
const src = _fs.readFileSync(filePath, "utf-8");
|
|
940
|
+
if (/\bhttp\s*:\s*false\b/.test(src)) {
|
|
941
|
+
httpConfig = false;
|
|
942
|
+
}
|
|
943
|
+
else {
|
|
944
|
+
const httpStart = src.search(/\bhttp\s*:\s*\{/);
|
|
945
|
+
if (httpStart >= 0) {
|
|
946
|
+
const window = src.slice(httpStart, httpStart + 200);
|
|
947
|
+
const m = window.match(/method\s*:\s*['"`](GET|POST|PUT|DELETE)['"`]/);
|
|
948
|
+
const p = window.match(/path\s*:\s*['"`]([^'"`]+)['"`]/);
|
|
949
|
+
if (m || p) {
|
|
950
|
+
httpConfig = {
|
|
951
|
+
...(m
|
|
952
|
+
? {
|
|
953
|
+
method: m[1],
|
|
954
|
+
}
|
|
955
|
+
: {}),
|
|
956
|
+
...(p ? { path: p[1] } : {}),
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
catch {
|
|
963
|
+
// File read failed — leave httpConfig undefined (default POST)
|
|
964
|
+
}
|
|
965
|
+
// Fallback: shell-based wrapper for CLI-style scripts
|
|
966
|
+
discoveredActions[name] = {
|
|
967
|
+
tool: {
|
|
968
|
+
description: `Run the ${name} action. Use: pnpm action ${name} --arg=value`,
|
|
969
|
+
parameters: {
|
|
970
|
+
type: "object",
|
|
971
|
+
properties: {
|
|
972
|
+
args: {
|
|
973
|
+
type: "string",
|
|
974
|
+
description: "CLI arguments as a string (e.g., --metrics=sessions --days=7)",
|
|
975
|
+
},
|
|
976
|
+
},
|
|
977
|
+
},
|
|
978
|
+
},
|
|
979
|
+
run: async (input) => {
|
|
980
|
+
const shellEntry = devScriptsForA2A["shell"];
|
|
981
|
+
if (!shellEntry)
|
|
982
|
+
return "Error: shell not available";
|
|
983
|
+
return shellEntry.run({
|
|
984
|
+
command: `pnpm action ${name} ${input.args || ""}`.trim(),
|
|
985
|
+
});
|
|
986
|
+
},
|
|
987
|
+
...(httpConfig !== undefined ? { http: httpConfig } : {}),
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
if (Object.keys(discoveredActions).length > 0 && process.env.DEBUG)
|
|
992
|
+
console.log(`[agent-chat] Auto-discovered ${Object.keys(discoveredActions).length} action(s): ${Object.keys(discoveredActions).join(", ")}`);
|
|
993
|
+
}
|
|
994
|
+
catch { }
|
|
52
995
|
}
|
|
53
|
-
//
|
|
54
|
-
|
|
996
|
+
// In dev mode, template actions (templateScripts and discoveredActions) are
|
|
997
|
+
// NOT registered as native tools — the agent invokes them via shell instead.
|
|
998
|
+
// This avoids degenerate empty-object tool calls that Anthropic models
|
|
999
|
+
// sometimes emit for actions with complex schemas. Production keeps the
|
|
1000
|
+
// native registration since it has no shell access.
|
|
1001
|
+
const allScripts = canToggle
|
|
1002
|
+
? {
|
|
1003
|
+
...resourceScripts,
|
|
1004
|
+
...chatScripts,
|
|
1005
|
+
...callAgentScript,
|
|
1006
|
+
...devScriptsForA2A,
|
|
1007
|
+
}
|
|
1008
|
+
: {
|
|
1009
|
+
...discoveredActions,
|
|
1010
|
+
...templateScripts,
|
|
1011
|
+
...resourceScripts,
|
|
1012
|
+
...chatScripts,
|
|
1013
|
+
...callAgentScript,
|
|
1014
|
+
...devScriptsForA2A,
|
|
1015
|
+
};
|
|
1016
|
+
const { mountA2A } = await import("../a2a/server.js");
|
|
1017
|
+
mountA2A(nitroApp, {
|
|
1018
|
+
name: options?.appId
|
|
1019
|
+
? options.appId.charAt(0).toUpperCase() + options.appId.slice(1)
|
|
1020
|
+
: "Agent",
|
|
1021
|
+
description: `Agent-native ${options?.appId ?? "app"} agent`,
|
|
1022
|
+
skills: Object.entries(allScripts).map(([name, entry]) => ({
|
|
1023
|
+
id: name,
|
|
1024
|
+
name,
|
|
1025
|
+
description: entry.tool.description,
|
|
1026
|
+
})),
|
|
1027
|
+
streaming: true,
|
|
1028
|
+
handler: async function* (message, context) {
|
|
1029
|
+
// Resolve the caller's identity for user-scoped data access.
|
|
1030
|
+
const isDev = process.env.NODE_ENV !== "production";
|
|
1031
|
+
let userEmail;
|
|
1032
|
+
if (isDev) {
|
|
1033
|
+
userEmail = context.metadata?.userEmail || undefined;
|
|
1034
|
+
if (!userEmail) {
|
|
1035
|
+
try {
|
|
1036
|
+
const { getDbExec } = await import("../db/client.js");
|
|
1037
|
+
const db = getDbExec();
|
|
1038
|
+
const { rows } = await db.execute({
|
|
1039
|
+
sql: "SELECT email FROM sessions ORDER BY created_at DESC LIMIT 1",
|
|
1040
|
+
args: [],
|
|
1041
|
+
});
|
|
1042
|
+
if (rows[0])
|
|
1043
|
+
userEmail = rows[0].email;
|
|
1044
|
+
}
|
|
1045
|
+
catch { }
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
else {
|
|
1049
|
+
const googleToken = context.metadata?.googleToken;
|
|
1050
|
+
if (googleToken) {
|
|
1051
|
+
try {
|
|
1052
|
+
const res = await fetch(`https://oauth2.googleapis.com/tokeninfo?access_token=${encodeURIComponent(googleToken)}`);
|
|
1053
|
+
if (res.ok) {
|
|
1054
|
+
const info = (await res.json());
|
|
1055
|
+
if (info.email && info.email_verified === "true") {
|
|
1056
|
+
userEmail = info.email;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
catch { }
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
if (userEmail) {
|
|
1064
|
+
process.env.AGENT_USER_EMAIL = userEmail;
|
|
1065
|
+
}
|
|
1066
|
+
const text = message.parts
|
|
1067
|
+
.filter((p) => p.type === "text")
|
|
1068
|
+
.map((p) => p.text)
|
|
1069
|
+
.join("\n");
|
|
1070
|
+
if (!text) {
|
|
1071
|
+
yield {
|
|
1072
|
+
role: "agent",
|
|
1073
|
+
parts: [
|
|
1074
|
+
{ type: "text", text: "No text content in message" },
|
|
1075
|
+
],
|
|
1076
|
+
};
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
// Use the SAME agent setup as the interactive chat — identical tools,
|
|
1080
|
+
// prompt, and capabilities. The A2A agent IS the app's agent.
|
|
1081
|
+
const a2aEngine = await resolveEngine({
|
|
1082
|
+
engineOption: options?.engine,
|
|
1083
|
+
apiKey: options?.apiKey,
|
|
1084
|
+
});
|
|
1085
|
+
// Use the same handler (dev or prod) that the interactive chat uses
|
|
1086
|
+
const handler = canToggle && devHandler ? devHandler : prodHandler;
|
|
1087
|
+
// Build the same system prompt the interactive agent uses
|
|
1088
|
+
const owner = userEmail || "local@localhost";
|
|
1089
|
+
const resources = await loadResourcesForPrompt(owner);
|
|
1090
|
+
const schemaBlock = await buildSchemaBlock(owner, canToggle);
|
|
1091
|
+
const systemPrompt = canToggle
|
|
1092
|
+
? devPrompt + resources + schemaBlock
|
|
1093
|
+
: basePrompt + resources + schemaBlock;
|
|
1094
|
+
const model = options?.model ??
|
|
1095
|
+
(canToggle ? "claude-sonnet-4-6" : "claude-haiku-4-5-20251001");
|
|
1096
|
+
// Build tools — same as interactive handler but WITHOUT call-agent
|
|
1097
|
+
// to prevent infinite recursive A2A loops (agent calling itself).
|
|
1098
|
+
// In dev mode, template actions are invoked via shell (not native tools),
|
|
1099
|
+
// so they're omitted from the tool registry — see allScripts comment.
|
|
1100
|
+
const a2aActions = canToggle
|
|
1101
|
+
? {
|
|
1102
|
+
...resourceScripts,
|
|
1103
|
+
...chatScripts,
|
|
1104
|
+
...devScriptsForA2A,
|
|
1105
|
+
}
|
|
1106
|
+
: {
|
|
1107
|
+
...templateScripts,
|
|
1108
|
+
...resourceScripts,
|
|
1109
|
+
...chatScripts,
|
|
1110
|
+
};
|
|
1111
|
+
const a2aTools = actionsToEngineTools(a2aActions);
|
|
1112
|
+
const a2aMessages = [
|
|
1113
|
+
{ role: "user", content: [{ type: "text", text }] },
|
|
1114
|
+
];
|
|
1115
|
+
// Run the SAME agent loop, collect text events, yield as A2A messages
|
|
1116
|
+
let accumulatedText = "";
|
|
1117
|
+
const controller = new AbortController();
|
|
1118
|
+
console.log(`[A2A] Starting agent loop: ${a2aTools.length} tools, prompt ${systemPrompt.length} chars`);
|
|
1119
|
+
await runAgentLoop({
|
|
1120
|
+
engine: a2aEngine,
|
|
1121
|
+
model,
|
|
1122
|
+
systemPrompt,
|
|
1123
|
+
tools: a2aTools,
|
|
1124
|
+
messages: a2aMessages,
|
|
1125
|
+
actions: a2aActions,
|
|
1126
|
+
send: (event) => {
|
|
1127
|
+
if (event.type === "text") {
|
|
1128
|
+
accumulatedText += event.text;
|
|
1129
|
+
}
|
|
1130
|
+
else if (event.type === "tool_start") {
|
|
1131
|
+
console.log(`[A2A] Tool call: ${event.tool}`);
|
|
1132
|
+
}
|
|
1133
|
+
else if (event.type === "error") {
|
|
1134
|
+
console.error(`[A2A] Error: ${event.error}`);
|
|
1135
|
+
}
|
|
1136
|
+
else if (event.type === "done") {
|
|
1137
|
+
console.log(`[A2A] Done. Response: ${accumulatedText.length} chars`);
|
|
1138
|
+
}
|
|
1139
|
+
},
|
|
1140
|
+
signal: controller.signal,
|
|
1141
|
+
});
|
|
1142
|
+
console.log(`[A2A] Loop complete. Text: ${accumulatedText.slice(0, 100)}...`);
|
|
1143
|
+
// Yield the final accumulated text
|
|
1144
|
+
yield {
|
|
1145
|
+
role: "agent",
|
|
1146
|
+
parts: [
|
|
1147
|
+
{
|
|
1148
|
+
type: "text",
|
|
1149
|
+
text: accumulatedText || "(no response)",
|
|
1150
|
+
},
|
|
1151
|
+
],
|
|
1152
|
+
};
|
|
1153
|
+
},
|
|
1154
|
+
});
|
|
1155
|
+
// Generate an "Available Actions" section from template-specific actions
|
|
1156
|
+
// so the agent knows to use them instead of raw SQL.
|
|
1157
|
+
//
|
|
1158
|
+
// Production: actions are native tools — emit `name(arg*: type) — desc`
|
|
1159
|
+
// Dev: actions are invoked via shell — emit `pnpm action name --arg <type>`
|
|
1160
|
+
// and include discoveredActions too, since those are also missing
|
|
1161
|
+
// from the dev tool registry.
|
|
1162
|
+
const prodActionsPrompt = generateActionsPrompt(templateScripts, "tool");
|
|
1163
|
+
const devActionsPrompt = generateActionsPrompt({ ...discoveredActions, ...templateScripts }, "cli");
|
|
1164
|
+
// Build system prompts — dynamic functions that pre-load resources per-request.
|
|
1165
|
+
// Production gets PROD_FRAMEWORK_PROMPT, dev gets DEV_FRAMEWORK_PROMPT.
|
|
1166
|
+
// Custom systemPrompt from options overrides the framework default entirely.
|
|
1167
|
+
const prodPrompt = (options?.systemPrompt ?? PROD_FRAMEWORK_PROMPT) + prodActionsPrompt;
|
|
1168
|
+
const devPrompt = (options?.devSystemPrompt
|
|
1169
|
+
? options.devSystemPrompt +
|
|
1170
|
+
(options?.systemPrompt ?? PROD_FRAMEWORK_PROMPT)
|
|
1171
|
+
: DEV_FRAMEWORK_PROMPT) + devActionsPrompt;
|
|
1172
|
+
// Keep legacy names for the composition below
|
|
1173
|
+
const basePrompt = prodPrompt;
|
|
55
1174
|
const devPrefix = options?.devSystemPrompt ?? DEFAULT_DEV_PROMPT;
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
1175
|
+
// Mount MCP remote server — same action registry as A2A + agent chat
|
|
1176
|
+
const { mountMCP } = await import("../mcp/server.js");
|
|
1177
|
+
mountMCP(nitroApp, {
|
|
1178
|
+
name: options?.appId
|
|
1179
|
+
? options.appId.charAt(0).toUpperCase() + options.appId.slice(1)
|
|
1180
|
+
: "Agent",
|
|
1181
|
+
description: `Agent-native ${options?.appId ?? "app"} agent`,
|
|
1182
|
+
actions: allScripts,
|
|
1183
|
+
askAgent: async (message) => {
|
|
1184
|
+
const mcpEngine = await resolveEngine({
|
|
1185
|
+
engineOption: options?.engine,
|
|
1186
|
+
apiKey: options?.apiKey,
|
|
1187
|
+
});
|
|
1188
|
+
const model = options?.model ??
|
|
1189
|
+
(canToggle ? "claude-sonnet-4-6" : "claude-haiku-4-5-20251001");
|
|
1190
|
+
// Same actions as A2A — without call-agent to prevent loops.
|
|
1191
|
+
// In dev mode, template actions go through shell, not native tools.
|
|
1192
|
+
const mcpActions = canToggle
|
|
1193
|
+
? {
|
|
1194
|
+
...resourceScripts,
|
|
1195
|
+
...chatScripts,
|
|
1196
|
+
...devScriptsForA2A,
|
|
1197
|
+
}
|
|
1198
|
+
: {
|
|
1199
|
+
...templateScripts,
|
|
1200
|
+
...resourceScripts,
|
|
1201
|
+
...chatScripts,
|
|
1202
|
+
};
|
|
1203
|
+
const mcpTools = actionsToEngineTools(mcpActions);
|
|
1204
|
+
const resources = await loadResourcesForPrompt("local@localhost");
|
|
1205
|
+
const schemaBlock = await buildSchemaBlock("local@localhost", canToggle);
|
|
1206
|
+
const systemPrompt = canToggle
|
|
1207
|
+
? devPrompt + resources + schemaBlock
|
|
1208
|
+
: basePrompt + resources + schemaBlock;
|
|
1209
|
+
let accumulatedText = "";
|
|
1210
|
+
const controller = new AbortController();
|
|
1211
|
+
await runAgentLoop({
|
|
1212
|
+
engine: mcpEngine,
|
|
1213
|
+
model,
|
|
1214
|
+
systemPrompt,
|
|
1215
|
+
tools: mcpTools,
|
|
1216
|
+
messages: [
|
|
1217
|
+
{ role: "user", content: [{ type: "text", text: message }] },
|
|
1218
|
+
],
|
|
1219
|
+
actions: mcpActions,
|
|
1220
|
+
send: (event) => {
|
|
1221
|
+
if (event.type === "text")
|
|
1222
|
+
accumulatedText += event.text;
|
|
1223
|
+
},
|
|
1224
|
+
signal: controller.signal,
|
|
1225
|
+
});
|
|
1226
|
+
return accumulatedText || "(no response)";
|
|
1227
|
+
},
|
|
1228
|
+
});
|
|
1229
|
+
// Resolve owner from the H3 event's session — matches how resources are created
|
|
1230
|
+
const getOwnerFromEvent = async (event) => {
|
|
1231
|
+
try {
|
|
1232
|
+
const session = await getSession(event);
|
|
1233
|
+
return session?.email || "local@localhost";
|
|
1234
|
+
}
|
|
1235
|
+
catch {
|
|
1236
|
+
return "local@localhost";
|
|
1237
|
+
}
|
|
1238
|
+
};
|
|
1239
|
+
// Auto-mount template actions as HTTP endpoints under /_agent-native/actions/
|
|
1240
|
+
// Include engine management scripts so the UI can call list/set/test-agent-engine.
|
|
1241
|
+
const httpActions = {
|
|
1242
|
+
...discoveredActions,
|
|
1243
|
+
...templateScripts,
|
|
1244
|
+
...engineScripts,
|
|
1245
|
+
};
|
|
1246
|
+
if (Object.keys(httpActions).length > 0) {
|
|
1247
|
+
const { mountActionRoutes } = await import("./action-routes.js");
|
|
1248
|
+
mountActionRoutes(nitroApp, httpActions, {
|
|
1249
|
+
getOwnerFromEvent,
|
|
1250
|
+
resolveOrgId: options?.resolveOrgId,
|
|
1251
|
+
});
|
|
1252
|
+
}
|
|
1253
|
+
// Callback to persist agent response when run finishes (even if client disconnected).
|
|
1254
|
+
// Reconstructs the assistant message from buffered events and appends to thread_data.
|
|
1255
|
+
const onRunComplete = async (run, threadId) => {
|
|
1256
|
+
if (!threadId)
|
|
1257
|
+
return;
|
|
1258
|
+
try {
|
|
1259
|
+
const thread = await getThread(threadId);
|
|
1260
|
+
if (!thread)
|
|
1261
|
+
return;
|
|
1262
|
+
const assistantMsg = buildAssistantMessage(run.events ?? [], run.runId);
|
|
1263
|
+
if (!assistantMsg) {
|
|
1264
|
+
// No content produced — just bump timestamp
|
|
1265
|
+
await updateThreadData(threadId, thread.threadData, thread.title, thread.preview, thread.messageCount);
|
|
1266
|
+
return;
|
|
1267
|
+
}
|
|
1268
|
+
// Parse existing thread_data, append assistant message only if
|
|
1269
|
+
// the frontend hasn't already saved it (avoids duplicates when
|
|
1270
|
+
// the client is still connected during a normal flow).
|
|
1271
|
+
let repo;
|
|
1272
|
+
try {
|
|
1273
|
+
repo = JSON.parse(thread.threadData || "{}");
|
|
1274
|
+
}
|
|
1275
|
+
catch {
|
|
1276
|
+
repo = {};
|
|
1277
|
+
}
|
|
1278
|
+
if (!Array.isArray(repo.messages))
|
|
1279
|
+
repo.messages = [];
|
|
1280
|
+
const lastMsg = repo.messages[repo.messages.length - 1];
|
|
1281
|
+
// Check both wrapped ({ message: { role } }) and unwrapped ({ role }) formats
|
|
1282
|
+
const lastRole = lastMsg?.message?.role ?? lastMsg?.role;
|
|
1283
|
+
if (lastRole === "assistant") {
|
|
1284
|
+
// Frontend already saved the assistant response — just bump timestamp
|
|
1285
|
+
await updateThreadData(threadId, thread.threadData, thread.title, thread.preview, thread.messageCount);
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
1288
|
+
// Determine if repo uses wrapped format ({ message, parentId }) or flat format
|
|
1289
|
+
const isWrapped = lastMsg && "message" in lastMsg;
|
|
1290
|
+
if (isWrapped) {
|
|
1291
|
+
const parentId = repo.messages.length > 0
|
|
1292
|
+
? (repo.messages[repo.messages.length - 1].message?.id ?? null)
|
|
1293
|
+
: null;
|
|
1294
|
+
repo.messages.push({ message: assistantMsg, parentId });
|
|
1295
|
+
}
|
|
1296
|
+
else {
|
|
1297
|
+
repo.messages.push(assistantMsg);
|
|
1298
|
+
}
|
|
1299
|
+
const meta = extractThreadMeta(repo);
|
|
1300
|
+
await updateThreadData(threadId, JSON.stringify(repo), meta.title || thread.title, meta.preview || thread.preview, repo.messages.length);
|
|
1301
|
+
}
|
|
1302
|
+
catch {
|
|
1303
|
+
// Best-effort — don't break cleanup
|
|
1304
|
+
}
|
|
1305
|
+
};
|
|
1306
|
+
// ─── Agent Teams: per-run send reference ─────────────────────────
|
|
1307
|
+
// Team tools need to emit events to the parent chat's SSE stream.
|
|
1308
|
+
// Each run gets its own send function, keyed by threadId so concurrent
|
|
1309
|
+
// requests for different threads don't clobber each other.
|
|
1310
|
+
const _runSendByThread = new Map();
|
|
1311
|
+
let _currentRunOwner = "local@localhost";
|
|
1312
|
+
let _currentRunThreadId = "";
|
|
1313
|
+
let _currentRunSystemPrompt = basePrompt;
|
|
1314
|
+
// Default to Haiku in production mode to manage costs for hosted apps
|
|
1315
|
+
const resolvedModel = options?.model ??
|
|
1316
|
+
(canToggle ? "claude-sonnet-4-6" : "claude-haiku-4-5-20251001");
|
|
1317
|
+
const teamTools = createTeamTools({
|
|
1318
|
+
getOwner: () => _currentRunOwner,
|
|
1319
|
+
getSystemPrompt: () => _currentRunSystemPrompt,
|
|
1320
|
+
getActions: () => canToggle
|
|
1321
|
+
? {
|
|
1322
|
+
// Sub-agents spawned in dev mode also invoke template actions
|
|
1323
|
+
// via shell, so omit them from the native tool registry.
|
|
1324
|
+
...resourceScripts,
|
|
1325
|
+
...chatScripts,
|
|
1326
|
+
...devScriptsForA2A,
|
|
1327
|
+
}
|
|
1328
|
+
: {
|
|
1329
|
+
...templateScripts,
|
|
1330
|
+
...resourceScripts,
|
|
1331
|
+
...chatScripts,
|
|
1332
|
+
},
|
|
1333
|
+
getEngine: () => createAnthropicEngine({
|
|
1334
|
+
apiKey: options?.apiKey ?? process.env.ANTHROPIC_API_KEY,
|
|
1335
|
+
}),
|
|
1336
|
+
getModel: () => resolvedModel,
|
|
1337
|
+
getParentThreadId: () => _currentRunThreadId,
|
|
1338
|
+
getSend: () => {
|
|
1339
|
+
// Return the send for the current run's thread
|
|
1340
|
+
const send = _runSendByThread.get(_currentRunThreadId);
|
|
1341
|
+
return send ?? null;
|
|
1342
|
+
},
|
|
1343
|
+
});
|
|
1344
|
+
// Hook into the run lifecycle to set/clear the send reference.
|
|
1345
|
+
// Job management tools (create-job, list-jobs, update-job)
|
|
1346
|
+
let jobTools = {};
|
|
1347
|
+
try {
|
|
1348
|
+
const { createJobTools } = await import("../jobs/tools.js");
|
|
1349
|
+
jobTools = createJobTools();
|
|
1350
|
+
}
|
|
1351
|
+
catch { }
|
|
1352
|
+
const prodActions = {
|
|
1353
|
+
...templateScripts,
|
|
1354
|
+
...resourceScripts,
|
|
1355
|
+
...chatScripts,
|
|
1356
|
+
...callAgentScript,
|
|
1357
|
+
...teamTools,
|
|
1358
|
+
...jobTools,
|
|
1359
|
+
};
|
|
1360
|
+
// Always build the production handler (includes resource tools + call-agent + team tools)
|
|
1361
|
+
// In production mode (!canToggle), enable usage tracking and limits
|
|
1362
|
+
const isHostedProd = !canToggle;
|
|
1363
|
+
const prodHandler = createProductionAgentHandler({
|
|
1364
|
+
actions: prodActions,
|
|
1365
|
+
systemPrompt: async (event) => {
|
|
1366
|
+
const owner = await getOwnerFromEvent(event);
|
|
1367
|
+
_currentRunOwner = owner;
|
|
1368
|
+
const resources = await loadResourcesForPrompt(owner);
|
|
1369
|
+
const schemaBlock = await buildSchemaBlock(owner, false);
|
|
1370
|
+
_currentRunSystemPrompt = basePrompt + resources + schemaBlock;
|
|
1371
|
+
return _currentRunSystemPrompt;
|
|
1372
|
+
},
|
|
1373
|
+
model: options?.model ??
|
|
1374
|
+
(isHostedProd ? "claude-haiku-4-5-20251001" : undefined),
|
|
61
1375
|
apiKey: options?.apiKey,
|
|
1376
|
+
onRunStart: (send, threadId) => {
|
|
1377
|
+
_runSendByThread.set(threadId, send);
|
|
1378
|
+
_currentRunThreadId = threadId;
|
|
1379
|
+
},
|
|
1380
|
+
onRunComplete: async (run, threadId) => {
|
|
1381
|
+
if (threadId)
|
|
1382
|
+
_runSendByThread.delete(threadId);
|
|
1383
|
+
await onRunComplete(run, threadId);
|
|
1384
|
+
},
|
|
1385
|
+
// Usage tracking for hosted production deployments
|
|
1386
|
+
trackUsage: isHostedProd,
|
|
1387
|
+
resolveOwnerEmail: isHostedProd ? getOwnerFromEvent : undefined,
|
|
62
1388
|
});
|
|
63
|
-
//
|
|
64
|
-
|
|
1389
|
+
// Build the dev handler (with filesystem/shell/db tools) if environment allows toggling
|
|
1390
|
+
let devHandler = null;
|
|
1391
|
+
if (canToggle) {
|
|
1392
|
+
const { createDevScriptRegistry } = await import("../scripts/dev/index.js");
|
|
1393
|
+
// Dev mode: template actions (templateScripts and discoveredActions) are
|
|
1394
|
+
// intentionally OMITTED from the native tool registry. The agent invokes
|
|
1395
|
+
// them via `shell(command="pnpm action <name> ...")` instead. This mirrors
|
|
1396
|
+
// how Claude Code works locally and dramatically reduces the rate of
|
|
1397
|
+
// degenerate empty-object tool calls. The CLI syntax for each action is
|
|
1398
|
+
// listed in the dev system prompt's "Available Actions" section.
|
|
1399
|
+
const devActions = {
|
|
1400
|
+
...resourceScripts,
|
|
1401
|
+
...chatScripts,
|
|
1402
|
+
...callAgentScript,
|
|
1403
|
+
...teamTools,
|
|
1404
|
+
...jobTools,
|
|
1405
|
+
...(await createDevScriptRegistry()),
|
|
1406
|
+
};
|
|
1407
|
+
devHandler = createProductionAgentHandler({
|
|
1408
|
+
actions: devActions,
|
|
1409
|
+
systemPrompt: async (event) => {
|
|
1410
|
+
const owner = await getOwnerFromEvent(event);
|
|
1411
|
+
_currentRunOwner = owner;
|
|
1412
|
+
const resources = await loadResourcesForPrompt(owner);
|
|
1413
|
+
const schemaBlock = await buildSchemaBlock(owner, true);
|
|
1414
|
+
_currentRunSystemPrompt = devPrompt + resources + schemaBlock;
|
|
1415
|
+
return _currentRunSystemPrompt;
|
|
1416
|
+
},
|
|
1417
|
+
model: options?.model,
|
|
1418
|
+
apiKey: options?.apiKey,
|
|
1419
|
+
onRunStart: (send, threadId) => {
|
|
1420
|
+
_runSendByThread.set(threadId, send);
|
|
1421
|
+
_currentRunThreadId = threadId;
|
|
1422
|
+
},
|
|
1423
|
+
onRunComplete: async (run, threadId) => {
|
|
1424
|
+
if (threadId)
|
|
1425
|
+
_runSendByThread.delete(threadId);
|
|
1426
|
+
await onRunComplete(run, threadId);
|
|
1427
|
+
},
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1430
|
+
// Resolve mention providers
|
|
1431
|
+
const rawProviders = options?.mentionProviders;
|
|
1432
|
+
const mentionProviders = typeof rawProviders === "function"
|
|
1433
|
+
? await rawProviders()
|
|
1434
|
+
: (rawProviders ?? {});
|
|
1435
|
+
// Mutable mode flag — starts in dev if environment allows
|
|
1436
|
+
let currentDevMode = canToggle;
|
|
1437
|
+
// Mount mode endpoint — GET returns current mode, POST toggles it (localhost only)
|
|
1438
|
+
getH3App(nitroApp).use(`${routePath}/mode`, defineEventHandler(async (event) => {
|
|
1439
|
+
if (getMethod(event) === "POST") {
|
|
1440
|
+
if (!canToggle) {
|
|
1441
|
+
setResponseStatus(event, 403);
|
|
1442
|
+
return { error: "Mode switching not available in production" };
|
|
1443
|
+
}
|
|
1444
|
+
if (!isLocalhost(event)) {
|
|
1445
|
+
setResponseStatus(event, 403);
|
|
1446
|
+
return { error: "Mode switching only available on localhost" };
|
|
1447
|
+
}
|
|
1448
|
+
const body = await readBody(event);
|
|
1449
|
+
if (typeof body?.devMode === "boolean") {
|
|
1450
|
+
currentDevMode = body.devMode;
|
|
1451
|
+
}
|
|
1452
|
+
else {
|
|
1453
|
+
currentDevMode = !currentDevMode;
|
|
1454
|
+
}
|
|
1455
|
+
return { devMode: currentDevMode, canToggle };
|
|
1456
|
+
}
|
|
1457
|
+
return { devMode: currentDevMode, canToggle };
|
|
1458
|
+
}));
|
|
65
1459
|
// Mount save-key BEFORE the prefix handler so it isn't shadowed
|
|
66
1460
|
// Only functional in Node.js environments (writes to .env file)
|
|
67
|
-
nitroApp.
|
|
1461
|
+
getH3App(nitroApp).use(`${routePath}/save-key`, defineEventHandler(async (event) => {
|
|
68
1462
|
if (getMethod(event) !== "POST") {
|
|
69
1463
|
setResponseStatus(event, 405);
|
|
70
1464
|
return { error: "Method not allowed" };
|
|
@@ -80,7 +1474,7 @@ export function createAgentChatPlugin(options) {
|
|
|
80
1474
|
const path = await import("path");
|
|
81
1475
|
const { upsertEnvFile } = await import("./create-server.js");
|
|
82
1476
|
const envPath = path.join(process.cwd(), ".env");
|
|
83
|
-
upsertEnvFile(envPath, [
|
|
1477
|
+
await upsertEnvFile(envPath, [
|
|
84
1478
|
{ key: "ANTHROPIC_API_KEY", value: trimmedKey },
|
|
85
1479
|
]);
|
|
86
1480
|
}
|
|
@@ -91,12 +1485,562 @@ export function createAgentChatPlugin(options) {
|
|
|
91
1485
|
process.env.ANTHROPIC_API_KEY = trimmedKey;
|
|
92
1486
|
return { ok: true };
|
|
93
1487
|
}));
|
|
94
|
-
// Mount
|
|
95
|
-
nitroApp.
|
|
1488
|
+
// Mount file search endpoint
|
|
1489
|
+
getH3App(nitroApp).use(`${routePath}/files`, defineEventHandler(async (event) => {
|
|
1490
|
+
if (getMethod(event) !== "GET") {
|
|
1491
|
+
setResponseStatus(event, 405);
|
|
1492
|
+
return { error: "Method not allowed" };
|
|
1493
|
+
}
|
|
1494
|
+
const query = getQuery(event);
|
|
1495
|
+
const q = typeof query.q === "string" ? query.q.toLowerCase() : "";
|
|
1496
|
+
const files = [];
|
|
1497
|
+
const seen = new Set();
|
|
1498
|
+
// In dev mode, walk the filesystem
|
|
1499
|
+
if (currentDevMode) {
|
|
1500
|
+
const codebaseFiles = [];
|
|
1501
|
+
try {
|
|
1502
|
+
await collectFiles(process.cwd(), "", 0, codebaseFiles);
|
|
1503
|
+
}
|
|
1504
|
+
catch {
|
|
1505
|
+
// Filesystem access failed — skip
|
|
1506
|
+
}
|
|
1507
|
+
for (const f of codebaseFiles) {
|
|
1508
|
+
if (!seen.has(f.path)) {
|
|
1509
|
+
seen.add(f.path);
|
|
1510
|
+
files.push({
|
|
1511
|
+
path: f.path,
|
|
1512
|
+
name: f.name,
|
|
1513
|
+
source: "codebase",
|
|
1514
|
+
type: f.type,
|
|
1515
|
+
});
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
// Query resources
|
|
1520
|
+
try {
|
|
1521
|
+
const resources = currentDevMode
|
|
1522
|
+
? await resourceListAccessible("local@localhost")
|
|
1523
|
+
: await resourceList(SHARED_OWNER);
|
|
1524
|
+
for (const r of resources) {
|
|
1525
|
+
if (!seen.has(r.path)) {
|
|
1526
|
+
seen.add(r.path);
|
|
1527
|
+
files.push({
|
|
1528
|
+
path: r.path,
|
|
1529
|
+
name: r.path.split("/").pop() || r.path,
|
|
1530
|
+
source: "resource",
|
|
1531
|
+
type: "file",
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
catch {
|
|
1537
|
+
// Resources not available — skip
|
|
1538
|
+
}
|
|
1539
|
+
// Filter by query and limit
|
|
1540
|
+
const filtered = q
|
|
1541
|
+
? files.filter((f) => f.path.toLowerCase().includes(q))
|
|
1542
|
+
: files;
|
|
1543
|
+
return { files: filtered.slice(0, 30) };
|
|
1544
|
+
}));
|
|
1545
|
+
// Mount skills listing endpoint
|
|
1546
|
+
getH3App(nitroApp).use(`${routePath}/skills`, defineEventHandler(async (event) => {
|
|
1547
|
+
if (getMethod(event) !== "GET") {
|
|
1548
|
+
setResponseStatus(event, 405);
|
|
1549
|
+
return { error: "Method not allowed" };
|
|
1550
|
+
}
|
|
1551
|
+
const skills = [];
|
|
1552
|
+
const seenNames = new Set();
|
|
1553
|
+
// In dev mode, scan .agents/skills/ directory
|
|
1554
|
+
if (currentDevMode) {
|
|
1555
|
+
try {
|
|
1556
|
+
const _fs = await lazyFs();
|
|
1557
|
+
const skillsDir = nodePath.join(process.cwd(), ".agents", "skills");
|
|
1558
|
+
const entries = _fs.readdirSync(skillsDir, {
|
|
1559
|
+
withFileTypes: true,
|
|
1560
|
+
});
|
|
1561
|
+
for (const entry of entries) {
|
|
1562
|
+
// Support both flat .md files and subdirectory-based skills (dir/SKILL.md)
|
|
1563
|
+
let skillFilePath;
|
|
1564
|
+
let skillRelPath;
|
|
1565
|
+
if (entry.isDirectory()) {
|
|
1566
|
+
// Subdirectory layout: .agents/skills/<name>/SKILL.md
|
|
1567
|
+
const candidate = nodePath.join(skillsDir, entry.name, "SKILL.md");
|
|
1568
|
+
if (!_fs.existsSync(candidate))
|
|
1569
|
+
continue;
|
|
1570
|
+
skillFilePath = candidate;
|
|
1571
|
+
skillRelPath = `.agents/skills/${entry.name}/SKILL.md`;
|
|
1572
|
+
}
|
|
1573
|
+
else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
1574
|
+
// Flat layout: .agents/skills/<name>.md
|
|
1575
|
+
skillFilePath = nodePath.join(skillsDir, entry.name);
|
|
1576
|
+
skillRelPath = `.agents/skills/${entry.name}`;
|
|
1577
|
+
}
|
|
1578
|
+
else {
|
|
1579
|
+
continue;
|
|
1580
|
+
}
|
|
1581
|
+
try {
|
|
1582
|
+
const content = _fs.readFileSync(skillFilePath, "utf-8");
|
|
1583
|
+
const fm = parseSkillFrontmatter(content);
|
|
1584
|
+
const skillName = fm.name || entry.name.replace(/\.md$/, "");
|
|
1585
|
+
if (!seenNames.has(skillName)) {
|
|
1586
|
+
seenNames.add(skillName);
|
|
1587
|
+
skills.push({
|
|
1588
|
+
name: skillName,
|
|
1589
|
+
description: fm.description,
|
|
1590
|
+
path: skillRelPath,
|
|
1591
|
+
source: "codebase",
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
catch {
|
|
1596
|
+
// Could not read individual skill file — skip
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
catch {
|
|
1601
|
+
// .agents/skills/ directory doesn't exist or not readable — skip
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
// Query resources with skills/ prefix
|
|
1605
|
+
try {
|
|
1606
|
+
const resourceSkills = currentDevMode
|
|
1607
|
+
? await resourceListAccessible("local@localhost", "skills/")
|
|
1608
|
+
: await resourceList(SHARED_OWNER, "skills/");
|
|
1609
|
+
for (const r of resourceSkills) {
|
|
1610
|
+
// Try to get content to parse frontmatter
|
|
1611
|
+
let skillName = r.path.split("/").pop()?.replace(/\.md$/, "") || r.path;
|
|
1612
|
+
let description;
|
|
1613
|
+
try {
|
|
1614
|
+
const full = await resourceGet(r.id);
|
|
1615
|
+
if (full) {
|
|
1616
|
+
const fm = parseSkillFrontmatter(full.content);
|
|
1617
|
+
if (fm.name)
|
|
1618
|
+
skillName = fm.name;
|
|
1619
|
+
description = fm.description;
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
catch {
|
|
1623
|
+
// Could not read resource content — use path-based name
|
|
1624
|
+
}
|
|
1625
|
+
if (!seenNames.has(skillName)) {
|
|
1626
|
+
seenNames.add(skillName);
|
|
1627
|
+
skills.push({
|
|
1628
|
+
name: skillName,
|
|
1629
|
+
description,
|
|
1630
|
+
path: r.path,
|
|
1631
|
+
source: "resource",
|
|
1632
|
+
});
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
catch {
|
|
1637
|
+
// Resources not available — skip
|
|
1638
|
+
}
|
|
1639
|
+
const result = { skills };
|
|
1640
|
+
if (skills.length === 0) {
|
|
1641
|
+
result.hint =
|
|
1642
|
+
"No skills found. Add skill files under skills/ in Resources. Learn more: https://agent-native.com/docs/resources#skills";
|
|
1643
|
+
}
|
|
1644
|
+
return result;
|
|
1645
|
+
}));
|
|
1646
|
+
// Mount unified mentions endpoint (files + resources + custom providers)
|
|
1647
|
+
getH3App(nitroApp).use(`${routePath}/mentions`, defineEventHandler(async (event) => {
|
|
1648
|
+
if (getMethod(event) !== "GET") {
|
|
1649
|
+
setResponseStatus(event, 405);
|
|
1650
|
+
return { error: "Method not allowed" };
|
|
1651
|
+
}
|
|
1652
|
+
const query = getQuery(event);
|
|
1653
|
+
const q = typeof query.q === "string" ? query.q.toLowerCase() : "";
|
|
1654
|
+
const matchesQuery = (item) => !q ||
|
|
1655
|
+
item.label.toLowerCase().includes(q) ||
|
|
1656
|
+
(item.description?.toLowerCase().includes(q) ?? false);
|
|
1657
|
+
const enc = new TextEncoder();
|
|
1658
|
+
// Stream NDJSON — each source flushes its batch as soon as it's ready.
|
|
1659
|
+
setResponseHeader(event, "Content-Type", "application/x-ndjson");
|
|
1660
|
+
setResponseHeader(event, "Cache-Control", "no-cache");
|
|
1661
|
+
const stream = new ReadableStream({
|
|
1662
|
+
async start(controller) {
|
|
1663
|
+
const MAX_RESULTS = 50;
|
|
1664
|
+
let totalSent = 0;
|
|
1665
|
+
let cancelled = false;
|
|
1666
|
+
const flush = (batch) => {
|
|
1667
|
+
if (cancelled)
|
|
1668
|
+
return;
|
|
1669
|
+
const filtered = batch.filter(matchesQuery);
|
|
1670
|
+
if (filtered.length === 0)
|
|
1671
|
+
return;
|
|
1672
|
+
const remaining = MAX_RESULTS - totalSent;
|
|
1673
|
+
const toSend = filtered.slice(0, remaining);
|
|
1674
|
+
if (toSend.length > 0) {
|
|
1675
|
+
totalSent += toSend.length;
|
|
1676
|
+
try {
|
|
1677
|
+
controller.enqueue(enc.encode(JSON.stringify({ items: toSend }) + "\n"));
|
|
1678
|
+
}
|
|
1679
|
+
catch {
|
|
1680
|
+
// Stream was closed by client
|
|
1681
|
+
cancelled = true;
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
};
|
|
1685
|
+
// All sources run in parallel; each flushes independently.
|
|
1686
|
+
const sources = [];
|
|
1687
|
+
// 1. Resources from SQL (fast — flush first)
|
|
1688
|
+
sources.push((async () => {
|
|
1689
|
+
try {
|
|
1690
|
+
const resources = currentDevMode
|
|
1691
|
+
? await resourceListAccessible("local@localhost")
|
|
1692
|
+
: await resourceList(SHARED_OWNER);
|
|
1693
|
+
flush(resources.map((r) => {
|
|
1694
|
+
const isShared = r.owner === SHARED_OWNER;
|
|
1695
|
+
return {
|
|
1696
|
+
id: `resource:${r.path}`,
|
|
1697
|
+
label: r.path.split("/").pop() || r.path,
|
|
1698
|
+
description: r.path,
|
|
1699
|
+
icon: "file",
|
|
1700
|
+
source: isShared
|
|
1701
|
+
? "resource:shared"
|
|
1702
|
+
: "resource:private",
|
|
1703
|
+
refType: "file",
|
|
1704
|
+
refPath: r.path,
|
|
1705
|
+
section: "Files",
|
|
1706
|
+
};
|
|
1707
|
+
}));
|
|
1708
|
+
}
|
|
1709
|
+
catch { }
|
|
1710
|
+
})());
|
|
1711
|
+
// 2. Codebase files (dev mode only — can be slow on large repos)
|
|
1712
|
+
if (currentDevMode) {
|
|
1713
|
+
sources.push((async () => {
|
|
1714
|
+
const codebaseFiles = [];
|
|
1715
|
+
try {
|
|
1716
|
+
await collectFiles(process.cwd(), "", 0, codebaseFiles);
|
|
1717
|
+
}
|
|
1718
|
+
catch { }
|
|
1719
|
+
flush(codebaseFiles.map((f) => ({
|
|
1720
|
+
id: `codebase:${f.path}`,
|
|
1721
|
+
label: f.name,
|
|
1722
|
+
description: f.path !== f.name ? f.path : undefined,
|
|
1723
|
+
icon: f.type,
|
|
1724
|
+
source: "codebase",
|
|
1725
|
+
refType: "file",
|
|
1726
|
+
refPath: f.path,
|
|
1727
|
+
section: "Files",
|
|
1728
|
+
})));
|
|
1729
|
+
})());
|
|
1730
|
+
}
|
|
1731
|
+
// 3. Custom mention providers (each flushes independently)
|
|
1732
|
+
for (const [key, provider] of Object.entries(mentionProviders)) {
|
|
1733
|
+
sources.push((async () => {
|
|
1734
|
+
try {
|
|
1735
|
+
const providerItems = await provider.search(q, event);
|
|
1736
|
+
flush(providerItems.map((item) => ({
|
|
1737
|
+
id: item.id,
|
|
1738
|
+
label: item.label,
|
|
1739
|
+
description: item.description,
|
|
1740
|
+
icon: item.icon || provider.icon || "file",
|
|
1741
|
+
source: key,
|
|
1742
|
+
refType: item.refType,
|
|
1743
|
+
refPath: item.refPath,
|
|
1744
|
+
refId: item.refId,
|
|
1745
|
+
section: provider.label,
|
|
1746
|
+
})));
|
|
1747
|
+
}
|
|
1748
|
+
catch (e) {
|
|
1749
|
+
console.error(`[agent-native] Mention provider "${key}" failed:`, e);
|
|
1750
|
+
}
|
|
1751
|
+
})());
|
|
1752
|
+
}
|
|
1753
|
+
// 4. Peer agent discovery (network call — often slowest)
|
|
1754
|
+
sources.push((async () => {
|
|
1755
|
+
try {
|
|
1756
|
+
const agents = await discoverAgents(options?.appId);
|
|
1757
|
+
flush(agents.map((agent) => ({
|
|
1758
|
+
id: `agent:${agent.id}`,
|
|
1759
|
+
label: agent.name,
|
|
1760
|
+
description: agent.description,
|
|
1761
|
+
icon: "agent",
|
|
1762
|
+
source: "agent",
|
|
1763
|
+
refType: "agent",
|
|
1764
|
+
refPath: agent.url,
|
|
1765
|
+
refId: agent.id,
|
|
1766
|
+
section: "Agents",
|
|
1767
|
+
})));
|
|
1768
|
+
}
|
|
1769
|
+
catch (e) {
|
|
1770
|
+
console.error("[agent-native] Agent discovery failed:", e);
|
|
1771
|
+
}
|
|
1772
|
+
})());
|
|
1773
|
+
await Promise.all(sources);
|
|
1774
|
+
if (!cancelled)
|
|
1775
|
+
controller.close();
|
|
1776
|
+
},
|
|
1777
|
+
cancel() {
|
|
1778
|
+
// Client disconnected — stop enqueuing
|
|
1779
|
+
},
|
|
1780
|
+
});
|
|
1781
|
+
return stream;
|
|
1782
|
+
}));
|
|
1783
|
+
// ─── Generate thread title ──────────────────────────────────────────
|
|
1784
|
+
getH3App(nitroApp).use(`${routePath}/generate-title`, defineEventHandler(async (event) => {
|
|
1785
|
+
if (getMethod(event) !== "POST") {
|
|
1786
|
+
setResponseStatus(event, 405);
|
|
1787
|
+
return { error: "Method not allowed" };
|
|
1788
|
+
}
|
|
1789
|
+
await getOwnerFromEvent(event);
|
|
1790
|
+
const body = await readBody(event);
|
|
1791
|
+
const message = body?.message;
|
|
1792
|
+
if (!message || typeof message !== "string") {
|
|
1793
|
+
setResponseStatus(event, 400);
|
|
1794
|
+
return { error: "message is required" };
|
|
1795
|
+
}
|
|
1796
|
+
// Strip mention markup: @[Name|type] → @Name
|
|
1797
|
+
const cleanMessage = message.replace(/@\[([^\]|]+)\|[^\]]*\]/g, "@$1");
|
|
1798
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
1799
|
+
if (!apiKey) {
|
|
1800
|
+
// Fallback: truncate the message
|
|
1801
|
+
return { title: cleanMessage.trim().slice(0, 60) };
|
|
1802
|
+
}
|
|
1803
|
+
try {
|
|
1804
|
+
const res = await fetch("https://api.anthropic.com/v1/messages", {
|
|
1805
|
+
method: "POST",
|
|
1806
|
+
headers: {
|
|
1807
|
+
"Content-Type": "application/json",
|
|
1808
|
+
"x-api-key": apiKey,
|
|
1809
|
+
"anthropic-version": "2023-06-01",
|
|
1810
|
+
},
|
|
1811
|
+
body: JSON.stringify({
|
|
1812
|
+
model: "claude-haiku-4-5-20251001",
|
|
1813
|
+
max_tokens: 30,
|
|
1814
|
+
messages: [
|
|
1815
|
+
{
|
|
1816
|
+
role: "user",
|
|
1817
|
+
content: `Generate a very short title (3-6 words, no quotes) for a chat that starts with this message:\n\n${cleanMessage.slice(0, 500)}`,
|
|
1818
|
+
},
|
|
1819
|
+
],
|
|
1820
|
+
}),
|
|
1821
|
+
});
|
|
1822
|
+
if (!res.ok) {
|
|
1823
|
+
return { title: cleanMessage.trim().slice(0, 60) };
|
|
1824
|
+
}
|
|
1825
|
+
const data = (await res.json());
|
|
1826
|
+
const text = data.content?.[0]?.text?.trim();
|
|
1827
|
+
return { title: text || cleanMessage.trim().slice(0, 60) };
|
|
1828
|
+
}
|
|
1829
|
+
catch {
|
|
1830
|
+
return { title: cleanMessage.trim().slice(0, 60) };
|
|
1831
|
+
}
|
|
1832
|
+
}));
|
|
1833
|
+
// ─── Run management endpoints (for hot-reload resilience) ─────────────
|
|
1834
|
+
// GET /runs/active?threadId=X — check if there's an active run for a thread
|
|
1835
|
+
getH3App(nitroApp).use(`${routePath}/runs`, defineEventHandler(async (event) => {
|
|
1836
|
+
// Auth check — ensure the user is authenticated
|
|
1837
|
+
await getOwnerFromEvent(event);
|
|
1838
|
+
const method = getMethod(event);
|
|
1839
|
+
const url = event.node?.req?.url || event.path || "";
|
|
1840
|
+
// Route: POST /runs/:id/abort
|
|
1841
|
+
// Match both full URL (/runs/{id}/abort) and h3 prefix-stripped (/{id}/abort)
|
|
1842
|
+
const abortMatch = url.match(/\/runs\/([^/?]+)\/abort/) ||
|
|
1843
|
+
url.match(/^\/([^/?]+)\/abort/);
|
|
1844
|
+
if (abortMatch && method === "POST") {
|
|
1845
|
+
const runId = decodeURIComponent(abortMatch[1]);
|
|
1846
|
+
abortRun(runId); // Aborts in-memory + marks aborted in SQL
|
|
1847
|
+
return { ok: true };
|
|
1848
|
+
}
|
|
1849
|
+
// Route: GET /runs/:id/events?after=N
|
|
1850
|
+
// Match both full URL (/runs/{id}/events) and h3 prefix-stripped (/{id}/events)
|
|
1851
|
+
const eventsMatch = url.match(/\/runs\/([^/?]+)\/events/) ||
|
|
1852
|
+
url.match(/^\/([^/?]+)\/events/);
|
|
1853
|
+
if (eventsMatch && method === "GET") {
|
|
1854
|
+
const runId = decodeURIComponent(eventsMatch[1]);
|
|
1855
|
+
const query = getQuery(event);
|
|
1856
|
+
const after = parseInt(String(query.after ?? "0"), 10) || 0;
|
|
1857
|
+
const stream = subscribeToRun(runId, after);
|
|
1858
|
+
if (!stream) {
|
|
1859
|
+
setResponseStatus(event, 404);
|
|
1860
|
+
return { error: "Run not found" };
|
|
1861
|
+
}
|
|
1862
|
+
setResponseHeader(event, "Content-Type", "text/event-stream");
|
|
1863
|
+
setResponseHeader(event, "Cache-Control", "no-cache");
|
|
1864
|
+
setResponseHeader(event, "Connection", "keep-alive");
|
|
1865
|
+
return stream;
|
|
1866
|
+
}
|
|
1867
|
+
// Route: GET /runs/active?threadId=X
|
|
1868
|
+
if (method === "GET") {
|
|
1869
|
+
const query = getQuery(event);
|
|
1870
|
+
const threadId = query.threadId ? String(query.threadId) : null;
|
|
1871
|
+
if (!threadId) {
|
|
1872
|
+
setResponseStatus(event, 400);
|
|
1873
|
+
return { error: "threadId query parameter is required" };
|
|
1874
|
+
}
|
|
1875
|
+
// Check in-memory first, then SQL (cross-isolate on Workers)
|
|
1876
|
+
const run = await getActiveRunForThreadAsync(threadId);
|
|
1877
|
+
if (!run) {
|
|
1878
|
+
setResponseStatus(event, 404);
|
|
1879
|
+
return { error: "No active run for this thread" };
|
|
1880
|
+
}
|
|
1881
|
+
return {
|
|
1882
|
+
runId: run.runId,
|
|
1883
|
+
threadId: run.threadId,
|
|
1884
|
+
status: run.status,
|
|
1885
|
+
};
|
|
1886
|
+
}
|
|
1887
|
+
setResponseStatus(event, 405);
|
|
1888
|
+
return { error: "Method not allowed" };
|
|
1889
|
+
}));
|
|
1890
|
+
// ─── Thread management endpoints ──────────────────────────────────────
|
|
1891
|
+
// Single handler for /threads and /threads/:id — h3's use() does prefix
|
|
1892
|
+
// matching so we can't reliably split them into separate handlers.
|
|
1893
|
+
getH3App(nitroApp).use(`${routePath}/threads`, defineEventHandler(async (event) => {
|
|
1894
|
+
const owner = await getOwnerFromEvent(event);
|
|
1895
|
+
const method = getMethod(event);
|
|
1896
|
+
// Determine if this is a specific-thread request.
|
|
1897
|
+
// h3's use() strips the mount prefix, so event.path contains
|
|
1898
|
+
// only the remainder after /threads — e.g., "/thread-abc" or "/".
|
|
1899
|
+
// We also check the original URL as a fallback.
|
|
1900
|
+
const remainder = (event.path || "").replace(/^\/+/, "");
|
|
1901
|
+
const fromUrl = (event.node?.req?.url || "").match(/\/threads\/([^/?]+)/);
|
|
1902
|
+
const threadId = remainder
|
|
1903
|
+
? decodeURIComponent(remainder.split("?")[0].split("/")[0])
|
|
1904
|
+
: fromUrl
|
|
1905
|
+
? decodeURIComponent(fromUrl[1])
|
|
1906
|
+
: null;
|
|
1907
|
+
// ── Specific thread: GET/PUT/DELETE /threads/:id ──
|
|
1908
|
+
if (threadId) {
|
|
1909
|
+
if (method === "GET") {
|
|
1910
|
+
const thread = await getThread(threadId);
|
|
1911
|
+
if (!thread || thread.ownerEmail !== owner) {
|
|
1912
|
+
setResponseStatus(event, 404);
|
|
1913
|
+
return { error: "Thread not found" };
|
|
1914
|
+
}
|
|
1915
|
+
return thread;
|
|
1916
|
+
}
|
|
1917
|
+
if (method === "PUT") {
|
|
1918
|
+
const thread = await getThread(threadId);
|
|
1919
|
+
if (!thread || thread.ownerEmail !== owner) {
|
|
1920
|
+
setResponseStatus(event, 404);
|
|
1921
|
+
return { error: "Thread not found" };
|
|
1922
|
+
}
|
|
1923
|
+
const body = await readBody(event);
|
|
1924
|
+
await updateThreadData(threadId, body.threadData || thread.threadData, body.title ?? thread.title, body.preview ?? thread.preview, body.messageCount || thread.messageCount);
|
|
1925
|
+
return { ok: true };
|
|
1926
|
+
}
|
|
1927
|
+
if (method === "DELETE") {
|
|
1928
|
+
const thread = await getThread(threadId);
|
|
1929
|
+
if (!thread || thread.ownerEmail !== owner) {
|
|
1930
|
+
setResponseStatus(event, 404);
|
|
1931
|
+
return { error: "Thread not found" };
|
|
1932
|
+
}
|
|
1933
|
+
await deleteThread(threadId);
|
|
1934
|
+
return { ok: true };
|
|
1935
|
+
}
|
|
1936
|
+
setResponseStatus(event, 405);
|
|
1937
|
+
return { error: "Method not allowed" };
|
|
1938
|
+
}
|
|
1939
|
+
// ── Thread list: GET/POST /threads ──
|
|
1940
|
+
if (method === "GET") {
|
|
1941
|
+
const query = getQuery(event);
|
|
1942
|
+
const limit = Math.min(parseInt(String(query.limit ?? "50"), 10) || 50, 200);
|
|
1943
|
+
const q = query.q ? String(query.q).trim() : "";
|
|
1944
|
+
if (q) {
|
|
1945
|
+
const threads = await searchThreads(owner, q, limit);
|
|
1946
|
+
return { threads };
|
|
1947
|
+
}
|
|
1948
|
+
const offset = parseInt(String(query.offset ?? "0"), 10) || 0;
|
|
1949
|
+
const threads = await listThreads(owner, limit, offset);
|
|
1950
|
+
return { threads };
|
|
1951
|
+
}
|
|
1952
|
+
if (method === "POST") {
|
|
1953
|
+
const body = await readBody(event);
|
|
1954
|
+
const thread = await createThread(owner, {
|
|
1955
|
+
id: body?.id,
|
|
1956
|
+
title: body?.title ?? "",
|
|
1957
|
+
});
|
|
1958
|
+
return thread;
|
|
1959
|
+
}
|
|
1960
|
+
setResponseStatus(event, 405);
|
|
1961
|
+
return { error: "Method not allowed" };
|
|
1962
|
+
}));
|
|
1963
|
+
// Mount the main chat handler — delegates to dev or prod handler based on current mode.
|
|
1964
|
+
// This is mounted last because h3's use() is prefix-based, meaning /_agent-native/agent-chat
|
|
1965
|
+
// also matches /_agent-native/agent-chat/threads/... — we skip sub-path requests here so the
|
|
1966
|
+
// earlier-mounted handlers (mode, save-key, files, skills, mentions, threads) handle them.
|
|
1967
|
+
getH3App(nitroApp).use(routePath, defineEventHandler(async (event) => {
|
|
1968
|
+
// Skip sub-path requests — they're handled by earlier-mounted handlers
|
|
1969
|
+
const url = event.node?.req?.url || event.path || "";
|
|
1970
|
+
const afterBase = url.slice(url.indexOf(routePath) + routePath.length);
|
|
1971
|
+
if (afterBase && afterBase !== "/" && !afterBase.startsWith("?")) {
|
|
1972
|
+
// Not for us — return 404 so h3 doesn't swallow the request
|
|
1973
|
+
setResponseStatus(event, 404);
|
|
1974
|
+
return { error: "Not found" };
|
|
1975
|
+
}
|
|
1976
|
+
// Set AGENT_USER_EMAIL so scripts resolve the same owner as the session.
|
|
1977
|
+
// Without this, scripts default to "local@localhost" and miss resources
|
|
1978
|
+
// created by users who authenticated via OAuth (e.g., Gmail).
|
|
1979
|
+
const owner = await getOwnerFromEvent(event);
|
|
1980
|
+
process.env.AGENT_USER_EMAIL = owner;
|
|
1981
|
+
// Set AGENT_ORG_ID so db-query/db-exec scope by org_id when applicable.
|
|
1982
|
+
// Priority: explicit resolveOrgId callback > session.orgId from Better Auth
|
|
1983
|
+
let resolvedOrgId = null;
|
|
1984
|
+
if (options?.resolveOrgId) {
|
|
1985
|
+
resolvedOrgId = await options.resolveOrgId(event);
|
|
1986
|
+
}
|
|
1987
|
+
else {
|
|
1988
|
+
try {
|
|
1989
|
+
const session = await getSession(event);
|
|
1990
|
+
resolvedOrgId = session?.orgId ?? null;
|
|
1991
|
+
}
|
|
1992
|
+
catch {
|
|
1993
|
+
// Session not available
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
if (resolvedOrgId) {
|
|
1997
|
+
process.env.AGENT_ORG_ID = resolvedOrgId;
|
|
1998
|
+
}
|
|
1999
|
+
else {
|
|
2000
|
+
delete process.env.AGENT_ORG_ID;
|
|
2001
|
+
}
|
|
2002
|
+
const handler = currentDevMode && devHandler ? devHandler : prodHandler;
|
|
2003
|
+
return handler(event);
|
|
2004
|
+
}));
|
|
2005
|
+
// ─── Recurring Jobs Scheduler ──────────────────────────────────────
|
|
2006
|
+
// Poll every 60 seconds for due recurring jobs and execute them.
|
|
2007
|
+
// Uses setInterval so it works in all deployment environments without
|
|
2008
|
+
// requiring Nitro experimental tasks configuration.
|
|
2009
|
+
try {
|
|
2010
|
+
const { processRecurringJobs } = await import("../jobs/scheduler.js");
|
|
2011
|
+
const schedulerDeps = {
|
|
2012
|
+
getActions: () => ({
|
|
2013
|
+
...templateScripts,
|
|
2014
|
+
...resourceScripts,
|
|
2015
|
+
...chatScripts,
|
|
2016
|
+
...jobTools,
|
|
2017
|
+
}),
|
|
2018
|
+
getSystemPrompt: async (owner) => {
|
|
2019
|
+
const resources = await loadResourcesForPrompt(owner);
|
|
2020
|
+
const schemaBlock = await buildSchemaBlock(owner, false);
|
|
2021
|
+
return basePrompt + resources + schemaBlock;
|
|
2022
|
+
},
|
|
2023
|
+
apiKey: options?.apiKey ?? process.env.ANTHROPIC_API_KEY,
|
|
2024
|
+
model: resolvedModel,
|
|
2025
|
+
};
|
|
2026
|
+
// Start after a 10-second delay to let the server fully initialize
|
|
2027
|
+
setTimeout(() => {
|
|
2028
|
+
setInterval(() => {
|
|
2029
|
+
processRecurringJobs(schedulerDeps).catch((err) => {
|
|
2030
|
+
console.error("[recurring-jobs] Scheduler error:", err?.message);
|
|
2031
|
+
});
|
|
2032
|
+
}, 60_000);
|
|
2033
|
+
if (process.env.DEBUG)
|
|
2034
|
+
console.log("[recurring-jobs] Scheduler started (60s interval)");
|
|
2035
|
+
}, 10_000);
|
|
2036
|
+
}
|
|
2037
|
+
catch (err) {
|
|
2038
|
+
// Jobs module not available — skip silently
|
|
2039
|
+
}
|
|
96
2040
|
};
|
|
97
2041
|
}
|
|
98
2042
|
/**
|
|
99
|
-
* Default agent chat plugin with no template-specific
|
|
2043
|
+
* Default agent chat plugin with no template-specific actions.
|
|
100
2044
|
* In dev mode, provides file system, shell, and database tools.
|
|
101
2045
|
* In production, provides only the default system prompt.
|
|
102
2046
|
*/
|