denchclaw 3.1.1 → 3.1.3
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/apps/web/.next/standalone/apps/web/.next/BUILD_ID +1 -1
- package/apps/web/.next/standalone/apps/web/.next/app-build-manifest.json +163 -163
- package/apps/web/.next/standalone/apps/web/.next/app-path-routes-manifest.json +45 -45
- package/apps/web/.next/standalone/apps/web/.next/build-manifest.json +2 -2
- package/apps/web/.next/standalone/apps/web/.next/cache/config.json +3 -3
- package/apps/web/.next/standalone/apps/web/.next/prerender-manifest.json +3 -3
- package/apps/web/.next/standalone/apps/web/.next/required-server-files.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/routes-manifest.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/_not-found/page.js +2 -2
- package/apps/web/.next/standalone/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/cron/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/proxy/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/serve/[...path]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/store/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/webhooks/[...path]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/active/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/runs/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/stop/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/stop/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/stream/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/subagents/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/composio/callback/route.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/composio/callback/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/composio/connect/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/composio/connections/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/composio/disconnect/route.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/composio/disconnect/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/composio/status/route.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/composio/status/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/composio/toolkits/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/crm/calendar/[id]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/crm/calendar/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/crm/companies/[id]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/crm/enrich/[type]/[id]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/crm/inbox/[threadId]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/crm/inbox/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/crm/people/[id]/activity/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/crm/people/[id]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/crm/people/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/crm/photos/proxy/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/crm/photos/sync/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/cron/heartbeat/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/cron/jobs/[jobId]/runs/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/cron/jobs/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/cron/runs/[sessionId]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/cron/runs/search-transcript/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/feedback/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/feedback/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/gateway/channels/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/gateway/chat/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/gateway/chat/stream/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/gateway/sessions/[id]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/gateway/sessions/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/integrations/[id]/toggle/route.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/integrations/[id]/toggle/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/integrations/repair/route.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/integrations/repair/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/integrations/route.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/integrations/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/memories/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/onboarding/connections/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/onboarding/connections/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/onboarding/dench-cloud/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/onboarding/dench-cloud/route.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/onboarding/dench-cloud/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/onboarding/identity/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/onboarding/identity/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/onboarding/skill-template/consume/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/onboarding/state/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/onboarding/state/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/onboarding/sync/progress/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/onboarding/sync/start/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/onboarding/sync/start/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/profiles/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/profiles/switch/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/sessions/[sessionId]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/sessions/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/settings/cloud/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/settings/cloud/route.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/settings/cloud/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/settings/mcp/connect/callback/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/settings/mcp/connect/start/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/settings/mcp/connect/token/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/settings/mcp/probe/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/settings/mcp/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/skills/[slug]/content/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/skills/[slug]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/skills/browse/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/skills/install/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/sync/poll-tick/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/sync/refresh/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/sync/status/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/terminal/port/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/voice/speech/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/voice/speech/route.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/voice/speech/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/voice/transcribe/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/voice/transcribe/route.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/voice/transcribe/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/voice/voices/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/voice/voices/route.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/voice/voices/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/[id]/messages/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/[id]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/assets/[...path]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/browse/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/browse-file/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/context/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/copy/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/db/introspect/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/db/query/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/delete/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/delete/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/enrichment-status/route.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/enrichment-status/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/execute/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/file/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/init/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/init/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/link-preview/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/list/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/mkdir/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/move/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/actions/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/actions/runs/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/display-field/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/enrich/route.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/enrich/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/[id]/content/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/[id]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/bulk-delete/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/options/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/fields/[fieldId]/enum-rename/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/fields/[fieldId]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/fields/reorder/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/fields/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/icon/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/views/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/open-file/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/path-info/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/query/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/raw-file/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/rename/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/reports/execute/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/reports/execute/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/search-index/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/suggest-files/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/switch/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/switch/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/thumbnail/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/tree/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/upload/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/upload/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/virtual-file/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/watch/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/write-binary/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/onboarding/page.js +2 -2
- package/apps/web/.next/standalone/apps/web/.next/server/app/onboarding/page.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/page.js +4 -4
- package/apps/web/.next/standalone/apps/web/.next/server/app/page.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/workspace/page.js +2 -2
- package/apps/web/.next/standalone/apps/web/.next/server/app/workspace/page.js.nft.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/workspace/page_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app-paths-manifest.json +45 -45
- package/apps/web/.next/standalone/apps/web/.next/server/chunks/17048.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/chunks/27221.js +15 -0
- package/apps/web/.next/standalone/apps/web/.next/server/chunks/27488.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/chunks/40192.js +1 -0
- package/apps/web/.next/standalone/apps/web/.next/server/chunks/44877.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/chunks/77515.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/chunks/80687.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/functions-config-manifest.json +12 -12
- package/apps/web/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/server-reference-manifest.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/static/chunks/29545-9f80428394c70d80.js +1 -0
- package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/{layout-c2e78eacc6f11614.js → layout-41989054c7ad7dc0.js} +1 -1
- package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/{page-f4dc14a9a2e7e80f.js → page-8ba18ea2dbbf6362.js} +1 -1
- package/apps/web/.next/standalone/apps/web/.next/static/css/df1d749df85dc392.css +1 -0
- package/apps/web/.next/standalone/apps/web/server.js +1 -1
- package/apps/web/.next/standalone/extensions/apollo-enrichment/index.mjs +294 -0
- package/apps/web/.next/standalone/extensions/apollo-enrichment/package.json +1 -1
- package/apps/web/.next/standalone/extensions/dench-ai-gateway/composio-bridge.ts +4 -1
- package/apps/web/.next/standalone/extensions/dench-ai-gateway/config-patch.ts +32 -0
- package/apps/web/.next/standalone/extensions/dench-ai-gateway/index.mjs +1128 -0
- package/apps/web/.next/standalone/extensions/dench-ai-gateway/index.ts +17 -5
- package/apps/web/.next/standalone/extensions/dench-ai-gateway/openclaw.plugin.json +10 -0
- package/apps/web/.next/standalone/extensions/dench-ai-gateway/package.json +1 -1
- package/apps/web/.next/standalone/extensions/dench-ai-gateway/sync-refresh-tools.ts +2 -2
- package/apps/web/.next/standalone/extensions/dench-identity/index.mjs +750 -0
- package/apps/web/.next/standalone/extensions/dench-identity/index.test.ts +11 -3
- package/apps/web/.next/standalone/extensions/dench-identity/index.ts +128 -8
- package/apps/web/.next/standalone/extensions/dench-identity/openclaw.plugin.json +8 -0
- package/apps/web/.next/standalone/extensions/dench-identity/package.json +1 -1
- package/apps/web/.next/standalone/extensions/exa-search/index.mjs +333 -0
- package/apps/web/.next/standalone/extensions/exa-search/package.json +1 -1
- package/apps/web/.next/standalone/extensions/posthog-analytics/index.mjs +786 -0
- package/apps/web/.next/standalone/extensions/posthog-analytics/lib/build-env.js +1 -1
- package/apps/web/.next/standalone/extensions/posthog-analytics/package.json +1 -1
- package/apps/web/.next/standalone/package.json +4 -2
- package/apps/web/.next/static/chunks/29545-9f80428394c70d80.js +1 -0
- package/apps/web/.next/static/chunks/app/{layout-c2e78eacc6f11614.js → layout-41989054c7ad7dc0.js} +1 -1
- package/apps/web/.next/static/chunks/app/{page-f4dc14a9a2e7e80f.js → page-8ba18ea2dbbf6362.js} +1 -1
- package/apps/web/.next/static/css/df1d749df85dc392.css +1 -0
- package/assets/seed/workspace.duckdb +0 -0
- package/dist/entry.js +1 -1
- package/dist/{program-JflTwsUD.js → program-BzTUdX93.js} +91 -2
- package/dist/{run-main-Db7zNm4h.js → run-main-DWpG1QJ-.js} +1 -1
- package/extensions/apollo-enrichment/index.mjs +294 -0
- package/extensions/apollo-enrichment/package.json +1 -1
- package/extensions/dench-ai-gateway/composio-bridge.ts +4 -1
- package/extensions/dench-ai-gateway/config-patch.ts +32 -0
- package/extensions/dench-ai-gateway/index.mjs +1128 -0
- package/extensions/dench-ai-gateway/index.ts +17 -5
- package/extensions/dench-ai-gateway/openclaw.plugin.json +10 -0
- package/extensions/dench-ai-gateway/package.json +1 -1
- package/extensions/dench-ai-gateway/sync-refresh-tools.ts +2 -2
- package/extensions/dench-identity/index.mjs +750 -0
- package/extensions/dench-identity/index.test.ts +11 -3
- package/extensions/dench-identity/index.ts +128 -8
- package/extensions/dench-identity/openclaw.plugin.json +8 -0
- package/extensions/dench-identity/package.json +1 -1
- package/extensions/exa-search/index.mjs +333 -0
- package/extensions/exa-search/package.json +1 -1
- package/extensions/posthog-analytics/index.mjs +786 -0
- package/extensions/posthog-analytics/lib/build-env.js +1 -1
- package/extensions/posthog-analytics/package.json +1 -1
- package/package.json +4 -2
- package/skills/dench-integrations/SKILL.md +2 -0
- package/apps/web/.next/standalone/apps/web/.next/server/chunks/6787.js +0 -15
- package/apps/web/.next/standalone/apps/web/.next/static/chunks/29545-3370e8cf127fa226.js +0 -1
- package/apps/web/.next/standalone/apps/web/.next/static/css/dd3ce8da3e14c080.css +0 -1
- package/apps/web/.next/static/chunks/29545-3370e8cf127fa226.js +0 -1
- package/apps/web/.next/static/css/dd3ce8da3e14c080.css +0 -1
- /package/apps/web/.next/standalone/apps/web/.next/static/{ZWGvHj5AzsMzgNHbpBmxN → exKPS0SMCb4AlH7q2vwOy}/_buildManifest.js +0 -0
- /package/apps/web/.next/standalone/apps/web/.next/static/{ZWGvHj5AzsMzgNHbpBmxN → exKPS0SMCb4AlH7q2vwOy}/_ssgManifest.js +0 -0
- /package/apps/web/.next/static/{ZWGvHj5AzsMzgNHbpBmxN → exKPS0SMCb4AlH7q2vwOy}/_buildManifest.js +0 -0
- /package/apps/web/.next/static/{ZWGvHj5AzsMzgNHbpBmxN → exKPS0SMCb4AlH7q2vwOy}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,1128 @@
|
|
|
1
|
+
// extensions/shared/dench-auth.ts
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
var AUTH_PROFILES_REL = path.join("agents", "main", "agent", "auth-profiles.json");
|
|
5
|
+
function readDenchAuthProfileKey() {
|
|
6
|
+
const stateDir = process.env.OPENCLAW_STATE_DIR;
|
|
7
|
+
if (stateDir) {
|
|
8
|
+
const key = readKeyFromAuthProfiles(path.join(stateDir, AUTH_PROFILES_REL));
|
|
9
|
+
if (key) return key;
|
|
10
|
+
}
|
|
11
|
+
return envFallback();
|
|
12
|
+
}
|
|
13
|
+
function readKeyFromAuthProfiles(authPath) {
|
|
14
|
+
try {
|
|
15
|
+
if (!existsSync(authPath)) return void 0;
|
|
16
|
+
const raw = JSON.parse(readFileSync(authPath, "utf-8"));
|
|
17
|
+
const key = raw?.profiles?.["dench-cloud:default"]?.key;
|
|
18
|
+
return typeof key === "string" && key.trim() ? key.trim() : void 0;
|
|
19
|
+
} catch {
|
|
20
|
+
return void 0;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function envFallback() {
|
|
24
|
+
return process.env.DENCH_CLOUD_API_KEY?.trim() || process.env.DENCH_API_KEY?.trim() || void 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// extensions/dench-ai-gateway/composio-bridge.ts
|
|
28
|
+
var DENCH_EXECUTE_INTEGRATIONS_NAME = "dench_execute_integrations";
|
|
29
|
+
var DENCH_INTEGRATIONS_DISPLAY_NAME = "Dench Integrations";
|
|
30
|
+
var DENCH_EXECUTE_INTEGRATIONS_PARAMETERS = {
|
|
31
|
+
type: "object",
|
|
32
|
+
additionalProperties: false,
|
|
33
|
+
properties: {
|
|
34
|
+
tool_slug: {
|
|
35
|
+
type: "string",
|
|
36
|
+
description: "Exact tool slug returned by dench_search_integrations, for example GMAIL_FETCH_EMAILS or YOUTUBE_LIST_USER_SUBSCRIPTIONS."
|
|
37
|
+
},
|
|
38
|
+
arguments: {
|
|
39
|
+
type: "object",
|
|
40
|
+
additionalProperties: true,
|
|
41
|
+
description: "JSON arguments object matching the tool's input_schema from the search results.",
|
|
42
|
+
properties: {}
|
|
43
|
+
},
|
|
44
|
+
connected_account_id: {
|
|
45
|
+
type: "string",
|
|
46
|
+
description: "Optional connected account id. Required only when multiple accounts are connected for the same toolkit. The gateway auto-selects when only one account exists."
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
required: ["tool_slug"]
|
|
50
|
+
};
|
|
51
|
+
function asRecord(value) {
|
|
52
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
53
|
+
}
|
|
54
|
+
function readString(value) {
|
|
55
|
+
return typeof value === "string" ? value : void 0;
|
|
56
|
+
}
|
|
57
|
+
function jsonResult(payload, details) {
|
|
58
|
+
return {
|
|
59
|
+
content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
|
|
60
|
+
details: details ?? payload
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function resolveGatewayBaseUrl(api, fallbackGatewayUrl) {
|
|
64
|
+
const plugins = asRecord(asRecord(api?.config)?.plugins)?.entries;
|
|
65
|
+
const denchGateway = asRecord(asRecord(plugins)?.["dench-ai-gateway"]);
|
|
66
|
+
const gwConfig = asRecord(denchGateway?.config);
|
|
67
|
+
const configuredUrl = readString(gwConfig?.gatewayUrl);
|
|
68
|
+
return (configuredUrl ?? fallbackGatewayUrl).replace(/\/$/, "");
|
|
69
|
+
}
|
|
70
|
+
function resolveApiKey() {
|
|
71
|
+
return readDenchAuthProfileKey() ?? void 0;
|
|
72
|
+
}
|
|
73
|
+
function createDenchExecuteIntegrationsTool(params) {
|
|
74
|
+
return {
|
|
75
|
+
name: DENCH_EXECUTE_INTEGRATIONS_NAME,
|
|
76
|
+
label: `${DENCH_INTEGRATIONS_DISPLAY_NAME} Execute`,
|
|
77
|
+
description: `Execute a ${DENCH_INTEGRATIONS_DISPLAY_NAME.toLowerCase()} tool by its slug. Pass the tool_slug from dench_search_integrations and the arguments matching its input_schema. The gateway handles authentication and account selection.`,
|
|
78
|
+
parameters: DENCH_EXECUTE_INTEGRATIONS_PARAMETERS,
|
|
79
|
+
async execute(_toolCallId, input) {
|
|
80
|
+
const payload = asRecord(input) ?? {};
|
|
81
|
+
const toolSlug = readString(payload.tool_slug)?.trim();
|
|
82
|
+
const connectedAccountId = readString(payload.connected_account_id)?.trim();
|
|
83
|
+
const toolArgs = asRecord(payload.arguments) ?? {};
|
|
84
|
+
if (!toolSlug) {
|
|
85
|
+
return jsonResult({
|
|
86
|
+
error: "The `tool_slug` field is required. Use dench_search_integrations to find available tools first."
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
const res = await fetch(`${params.gatewayBaseUrl}/v1/composio/tools/execute`, {
|
|
91
|
+
method: "POST",
|
|
92
|
+
headers: {
|
|
93
|
+
"content-type": "application/json",
|
|
94
|
+
accept: "application/json",
|
|
95
|
+
...params.authorization ? { authorization: params.authorization } : {}
|
|
96
|
+
},
|
|
97
|
+
body: JSON.stringify({
|
|
98
|
+
tool_slug: toolSlug,
|
|
99
|
+
arguments: toolArgs,
|
|
100
|
+
...connectedAccountId ? { connected_account_id: connectedAccountId } : {}
|
|
101
|
+
})
|
|
102
|
+
});
|
|
103
|
+
const text = await res.text();
|
|
104
|
+
let parsed;
|
|
105
|
+
try {
|
|
106
|
+
parsed = JSON.parse(text);
|
|
107
|
+
} catch {
|
|
108
|
+
parsed = void 0;
|
|
109
|
+
}
|
|
110
|
+
if (!res.ok) {
|
|
111
|
+
const errorCode = readString(asRecord(parsed?.error)?.code) ?? readString(parsed?.code);
|
|
112
|
+
const errorMessage = readString(asRecord(parsed?.error)?.message) ?? readString(parsed?.error) ?? text;
|
|
113
|
+
if (errorCode === "composio_account_selection_required") {
|
|
114
|
+
return jsonResult(
|
|
115
|
+
{
|
|
116
|
+
error: errorMessage,
|
|
117
|
+
account_selection_required: true,
|
|
118
|
+
instruction: "Ask the user which connected account to use and pass its connected_account_id."
|
|
119
|
+
},
|
|
120
|
+
{ status: "error", errorCode, tool_slug: toolSlug }
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
if (errorCode === "composio_not_connected") {
|
|
124
|
+
return jsonResult(
|
|
125
|
+
{ error: errorMessage, not_connected: true },
|
|
126
|
+
{ status: "error", errorCode, tool_slug: toolSlug }
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
return jsonResult(
|
|
130
|
+
{
|
|
131
|
+
error: `${DENCH_INTEGRATIONS_DISPLAY_NAME} tool ${toolSlug} failed (HTTP ${res.status}).`,
|
|
132
|
+
detail: parsed ?? (text || void 0)
|
|
133
|
+
},
|
|
134
|
+
{ status: "error", tool_slug: toolSlug }
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
const data = parsed?.data;
|
|
138
|
+
const error = readString(parsed?.error);
|
|
139
|
+
const contentPayload = error ? { error, data } : data ?? parsed ?? {};
|
|
140
|
+
return {
|
|
141
|
+
content: [
|
|
142
|
+
{
|
|
143
|
+
type: "text",
|
|
144
|
+
text: JSON.stringify(contentPayload, null, 2)
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
details: {
|
|
148
|
+
denchIntegrations: true,
|
|
149
|
+
tool_slug: toolSlug,
|
|
150
|
+
...parsed?.log_id ? { logId: parsed.log_id } : {},
|
|
151
|
+
...data !== void 0 ? { structuredContent: data } : {},
|
|
152
|
+
...error ? { status: "error", error } : {},
|
|
153
|
+
...connectedAccountId ? { connectedAccountId } : {}
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
} catch (error) {
|
|
157
|
+
return jsonResult(
|
|
158
|
+
{
|
|
159
|
+
error: `${DENCH_INTEGRATIONS_DISPLAY_NAME} tool ${toolSlug} failed.`,
|
|
160
|
+
detail: error instanceof Error ? error.message : String(error)
|
|
161
|
+
},
|
|
162
|
+
{ status: "error", tool_slug: toolSlug }
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function stripRuntimeComposioServer(api) {
|
|
169
|
+
const rootConfig = asRecord(api?.config);
|
|
170
|
+
const mcp = asRecord(rootConfig?.mcp);
|
|
171
|
+
const servers = asRecord(mcp?.servers);
|
|
172
|
+
if (!rootConfig || !mcp || !servers) return;
|
|
173
|
+
if (servers.composio) {
|
|
174
|
+
delete servers.composio;
|
|
175
|
+
if (Object.keys(servers).length === 0) delete mcp.servers;
|
|
176
|
+
if (Object.keys(mcp).length === 0) delete rootConfig.mcp;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function registerDenchIntegrationsBridge(api, fallbackGatewayUrl) {
|
|
180
|
+
stripRuntimeComposioServer(api);
|
|
181
|
+
const gatewayBaseUrl = resolveGatewayBaseUrl(api, fallbackGatewayUrl);
|
|
182
|
+
const apiKey = resolveApiKey();
|
|
183
|
+
if (!apiKey) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const tool = createDenchExecuteIntegrationsTool({
|
|
187
|
+
gatewayBaseUrl,
|
|
188
|
+
authorization: `Bearer ${apiKey}`
|
|
189
|
+
});
|
|
190
|
+
api.registerTool(tool, {
|
|
191
|
+
name: DENCH_EXECUTE_INTEGRATIONS_NAME,
|
|
192
|
+
optional: true
|
|
193
|
+
});
|
|
194
|
+
api.logger?.info?.(
|
|
195
|
+
`[dench-ai-gateway] registered ${DENCH_EXECUTE_INTEGRATIONS_NAME} bridge tool`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// extensions/dench-ai-gateway/models.ts
|
|
200
|
+
var DEFAULT_DENCH_CLOUD_GATEWAY_URL = "https://gateway.merseoriginals.com";
|
|
201
|
+
function asRecord2(value) {
|
|
202
|
+
return value && typeof value === "object" ? value : void 0;
|
|
203
|
+
}
|
|
204
|
+
function readString2(input, ...keys) {
|
|
205
|
+
for (const key of keys) {
|
|
206
|
+
const value = input[key];
|
|
207
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
208
|
+
return value.trim();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return void 0;
|
|
212
|
+
}
|
|
213
|
+
function readNumber(input, ...keys) {
|
|
214
|
+
for (const key of keys) {
|
|
215
|
+
const value = input[key];
|
|
216
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
217
|
+
return value;
|
|
218
|
+
}
|
|
219
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
220
|
+
const parsed = Number(value);
|
|
221
|
+
if (Number.isFinite(parsed)) {
|
|
222
|
+
return parsed;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return void 0;
|
|
227
|
+
}
|
|
228
|
+
function readBoolean(input, ...keys) {
|
|
229
|
+
for (const key of keys) {
|
|
230
|
+
const value = input[key];
|
|
231
|
+
if (typeof value === "boolean") {
|
|
232
|
+
return value;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return void 0;
|
|
236
|
+
}
|
|
237
|
+
function isNonEmptyString(value) {
|
|
238
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
239
|
+
}
|
|
240
|
+
function normalizeInputKinds(input, supportsImages) {
|
|
241
|
+
if (!Array.isArray(input)) {
|
|
242
|
+
return supportsImages ? ["text", "image"] : ["text"];
|
|
243
|
+
}
|
|
244
|
+
const kinds = /* @__PURE__ */ new Set();
|
|
245
|
+
for (const value of input) {
|
|
246
|
+
if (value === "text" || value === "image") {
|
|
247
|
+
kinds.add(value);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (!kinds.has("text")) {
|
|
251
|
+
kinds.add("text");
|
|
252
|
+
}
|
|
253
|
+
if (supportsImages) {
|
|
254
|
+
kinds.add("image");
|
|
255
|
+
}
|
|
256
|
+
return [...kinds];
|
|
257
|
+
}
|
|
258
|
+
function stripTrailingSlashes(url) {
|
|
259
|
+
let end = url.length;
|
|
260
|
+
while (end > 0 && url.charCodeAt(end - 1) === 47) {
|
|
261
|
+
end -= 1;
|
|
262
|
+
}
|
|
263
|
+
return end === url.length ? url : url.slice(0, end);
|
|
264
|
+
}
|
|
265
|
+
function normalizeDenchGatewayUrl(value) {
|
|
266
|
+
const raw = (value || DEFAULT_DENCH_CLOUD_GATEWAY_URL).trim();
|
|
267
|
+
const withProtocol = raw.startsWith("http://") || raw.startsWith("https://") ? raw : `https://${raw}`;
|
|
268
|
+
let base = stripTrailingSlashes(withProtocol);
|
|
269
|
+
if (base.endsWith("/v1")) {
|
|
270
|
+
base = stripTrailingSlashes(base.slice(0, -3));
|
|
271
|
+
}
|
|
272
|
+
return base;
|
|
273
|
+
}
|
|
274
|
+
function buildDenchGatewayApiBaseUrl(gatewayUrl) {
|
|
275
|
+
return `${normalizeDenchGatewayUrl(gatewayUrl)}/v1`;
|
|
276
|
+
}
|
|
277
|
+
function buildDenchGatewayCatalogUrl(gatewayUrl) {
|
|
278
|
+
return `${normalizeDenchGatewayUrl(gatewayUrl)}/v1/public/models`;
|
|
279
|
+
}
|
|
280
|
+
var RECOMMENDED_DENCH_CLOUD_MODEL_ID = "claude-sonnet-4.6";
|
|
281
|
+
var FALLBACK_DENCH_CLOUD_MODELS = [
|
|
282
|
+
{
|
|
283
|
+
id: "kimi-k2.5",
|
|
284
|
+
stableId: "moonshotai.kimi-k2.5",
|
|
285
|
+
displayName: "Kimi K2.5",
|
|
286
|
+
provider: "moonshot",
|
|
287
|
+
transportProvider: "bedrock",
|
|
288
|
+
api: "openai-responses",
|
|
289
|
+
input: ["text", "image"],
|
|
290
|
+
reasoning: true,
|
|
291
|
+
contextWindow: 262e3,
|
|
292
|
+
maxTokens: 64e3,
|
|
293
|
+
supportsStreaming: true,
|
|
294
|
+
supportsImages: true,
|
|
295
|
+
supportsResponses: true,
|
|
296
|
+
supportsReasoning: true,
|
|
297
|
+
cost: {
|
|
298
|
+
input: 0.81,
|
|
299
|
+
output: 4.05,
|
|
300
|
+
cacheRead: 0,
|
|
301
|
+
cacheWrite: 0
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
id: "claude-opus-4.6",
|
|
306
|
+
stableId: "anthropic.claude-opus-4-6-v1",
|
|
307
|
+
displayName: "Claude Opus 4.6",
|
|
308
|
+
provider: "anthropic",
|
|
309
|
+
transportProvider: "bedrock",
|
|
310
|
+
api: "openai-responses",
|
|
311
|
+
input: ["text", "image"],
|
|
312
|
+
reasoning: true,
|
|
313
|
+
contextWindow: 971e3,
|
|
314
|
+
maxTokens: 128e3,
|
|
315
|
+
supportsStreaming: true,
|
|
316
|
+
supportsImages: true,
|
|
317
|
+
supportsResponses: true,
|
|
318
|
+
supportsReasoning: true,
|
|
319
|
+
cost: {
|
|
320
|
+
input: 6.75,
|
|
321
|
+
output: 33.75,
|
|
322
|
+
cacheRead: 0.675,
|
|
323
|
+
cacheWrite: 8.4375
|
|
324
|
+
}
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
id: "gpt-5.4",
|
|
328
|
+
stableId: "gpt-5.4",
|
|
329
|
+
displayName: "GPT-5.4",
|
|
330
|
+
provider: "openai",
|
|
331
|
+
transportProvider: "openai",
|
|
332
|
+
api: "openai-responses",
|
|
333
|
+
input: ["text", "image"],
|
|
334
|
+
reasoning: true,
|
|
335
|
+
contextWindow: 971e3,
|
|
336
|
+
maxTokens: 128e3,
|
|
337
|
+
supportsStreaming: true,
|
|
338
|
+
supportsImages: true,
|
|
339
|
+
supportsResponses: true,
|
|
340
|
+
supportsReasoning: true,
|
|
341
|
+
cost: {
|
|
342
|
+
input: 3.375,
|
|
343
|
+
output: 20.25,
|
|
344
|
+
cacheRead: 0.3375,
|
|
345
|
+
cacheWrite: 0
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
id: "claude-sonnet-4.6",
|
|
350
|
+
stableId: "anthropic.claude-sonnet-4-6-v1",
|
|
351
|
+
displayName: "Claude Sonnet 4.6",
|
|
352
|
+
provider: "anthropic",
|
|
353
|
+
transportProvider: "bedrock",
|
|
354
|
+
api: "openai-responses",
|
|
355
|
+
input: ["text", "image"],
|
|
356
|
+
reasoning: true,
|
|
357
|
+
contextWindow: 971e3,
|
|
358
|
+
maxTokens: 64e3,
|
|
359
|
+
supportsStreaming: true,
|
|
360
|
+
supportsImages: true,
|
|
361
|
+
supportsResponses: true,
|
|
362
|
+
supportsReasoning: true,
|
|
363
|
+
cost: {
|
|
364
|
+
input: 4.05,
|
|
365
|
+
output: 20.25,
|
|
366
|
+
cacheRead: 0.405,
|
|
367
|
+
cacheWrite: 5.0625
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
];
|
|
371
|
+
function cloneFallbackDenchCloudModels() {
|
|
372
|
+
return FALLBACK_DENCH_CLOUD_MODELS.map((model) => ({
|
|
373
|
+
...model,
|
|
374
|
+
input: [...model.input],
|
|
375
|
+
cost: { ...model.cost }
|
|
376
|
+
}));
|
|
377
|
+
}
|
|
378
|
+
function normalizeDenchCloudCatalogModel(input) {
|
|
379
|
+
const record = asRecord2(input);
|
|
380
|
+
if (!record) {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
const publicId = readString2(record, "id", "publicId", "public_id");
|
|
384
|
+
const stableId = readString2(record, "stableId", "stable_id") || publicId;
|
|
385
|
+
const displayName = readString2(record, "name", "displayName", "display_name");
|
|
386
|
+
const provider = readString2(record, "provider");
|
|
387
|
+
const transportProvider = readString2(record, "transportProvider", "transport_provider");
|
|
388
|
+
if (!publicId || !stableId || !displayName || !isNonEmptyString(provider) || !isNonEmptyString(transportProvider)) {
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
const supportsImages = readBoolean(record, "supportsImages", "supports_images") ?? false;
|
|
392
|
+
const supportsStreaming = readBoolean(record, "supportsStreaming", "supports_streaming") ?? true;
|
|
393
|
+
const supportsResponses = readBoolean(record, "supportsResponses", "supports_responses") ?? true;
|
|
394
|
+
const supportsReasoning = readBoolean(record, "supportsReasoning", "supports_reasoning") ?? readBoolean(record, "reasoning") ?? false;
|
|
395
|
+
const contextWindow = readNumber(record, "contextWindow", "context_window") ?? 2e5;
|
|
396
|
+
const maxTokens = readNumber(record, "maxTokens", "max_tokens", "maxOutputTokens", "max_output_tokens") ?? 64e3;
|
|
397
|
+
const costRecord = asRecord2(record.cost) ?? {};
|
|
398
|
+
const inputCost = readNumber(costRecord, "input") ?? 0;
|
|
399
|
+
const outputCost = readNumber(costRecord, "output") ?? 0;
|
|
400
|
+
const cacheRead = readNumber(costRecord, "cacheRead", "cache_read") ?? 0;
|
|
401
|
+
const cacheWrite = readNumber(costRecord, "cacheWrite", "cache_write") ?? 0;
|
|
402
|
+
return {
|
|
403
|
+
id: publicId,
|
|
404
|
+
stableId,
|
|
405
|
+
displayName,
|
|
406
|
+
provider,
|
|
407
|
+
transportProvider,
|
|
408
|
+
api: record.api === "openai-completions" ? "openai-completions" : "openai-responses",
|
|
409
|
+
input: normalizeInputKinds(record.input, supportsImages),
|
|
410
|
+
reasoning: supportsReasoning,
|
|
411
|
+
contextWindow,
|
|
412
|
+
maxTokens,
|
|
413
|
+
supportsStreaming,
|
|
414
|
+
supportsImages,
|
|
415
|
+
supportsResponses,
|
|
416
|
+
supportsReasoning,
|
|
417
|
+
cost: {
|
|
418
|
+
input: inputCost,
|
|
419
|
+
output: outputCost,
|
|
420
|
+
cacheRead,
|
|
421
|
+
cacheWrite
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
function normalizeDenchCloudCatalogResponse(payload) {
|
|
426
|
+
const root = asRecord2(payload);
|
|
427
|
+
const data = root?.data;
|
|
428
|
+
if (!Array.isArray(data)) {
|
|
429
|
+
return [];
|
|
430
|
+
}
|
|
431
|
+
const models = [];
|
|
432
|
+
const seen = /* @__PURE__ */ new Set();
|
|
433
|
+
for (const entry of data) {
|
|
434
|
+
const normalized = normalizeDenchCloudCatalogModel(entry);
|
|
435
|
+
if (!normalized || seen.has(normalized.stableId)) {
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
seen.add(normalized.stableId);
|
|
439
|
+
models.push(normalized);
|
|
440
|
+
}
|
|
441
|
+
return models;
|
|
442
|
+
}
|
|
443
|
+
function buildDenchCloudProviderModels(models) {
|
|
444
|
+
return models.map((model) => ({
|
|
445
|
+
id: model.stableId,
|
|
446
|
+
name: `${model.displayName} (Dench Cloud)`,
|
|
447
|
+
reasoning: model.reasoning,
|
|
448
|
+
input: [...model.input],
|
|
449
|
+
cost: {
|
|
450
|
+
input: model.cost.input,
|
|
451
|
+
output: model.cost.output,
|
|
452
|
+
cacheRead: model.cost.cacheRead,
|
|
453
|
+
cacheWrite: model.cost.cacheWrite
|
|
454
|
+
},
|
|
455
|
+
contextWindow: model.contextWindow,
|
|
456
|
+
maxTokens: model.maxTokens
|
|
457
|
+
}));
|
|
458
|
+
}
|
|
459
|
+
function buildDenchCloudAgentModelEntries(models) {
|
|
460
|
+
return Object.fromEntries(
|
|
461
|
+
models.map((model) => [
|
|
462
|
+
`dench-cloud/${model.stableId}`,
|
|
463
|
+
{ alias: `${model.displayName} (Dench Cloud)` }
|
|
464
|
+
])
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
function resolveDenchCloudModel(models, requestedId) {
|
|
468
|
+
const normalized = requestedId?.trim();
|
|
469
|
+
if (!normalized) {
|
|
470
|
+
return models.find((model) => model.id === RECOMMENDED_DENCH_CLOUD_MODEL_ID) || models[0];
|
|
471
|
+
}
|
|
472
|
+
return models.find((model) => model.id === normalized || model.stableId === normalized);
|
|
473
|
+
}
|
|
474
|
+
function formatDenchCloudModelHint(model) {
|
|
475
|
+
const parts = [model.provider];
|
|
476
|
+
if (model.reasoning) parts.push("reasoning");
|
|
477
|
+
if (model.id === RECOMMENDED_DENCH_CLOUD_MODEL_ID) parts.push("recommended");
|
|
478
|
+
return parts.join(" \xB7 ");
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// extensions/dench-ai-gateway/config-patch.ts
|
|
482
|
+
var DENCH_COMPOSIO_WRAPPER_TOOLS = [
|
|
483
|
+
"dench_search_integrations",
|
|
484
|
+
"dench_execute_integrations"
|
|
485
|
+
];
|
|
486
|
+
var DENCH_CLOUD_TOOL_ALLOWLIST = [
|
|
487
|
+
"read",
|
|
488
|
+
"write",
|
|
489
|
+
"edit",
|
|
490
|
+
"apply_patch",
|
|
491
|
+
"exec",
|
|
492
|
+
"process",
|
|
493
|
+
"code_execution",
|
|
494
|
+
"web_fetch",
|
|
495
|
+
"x_search",
|
|
496
|
+
"memory_search",
|
|
497
|
+
"memory_get",
|
|
498
|
+
"sessions_list",
|
|
499
|
+
"sessions_history",
|
|
500
|
+
"sessions_send",
|
|
501
|
+
"sessions_spawn",
|
|
502
|
+
"sessions_yield",
|
|
503
|
+
"subagents",
|
|
504
|
+
"session_status",
|
|
505
|
+
"cron",
|
|
506
|
+
"update_plan",
|
|
507
|
+
"image",
|
|
508
|
+
"image_generate",
|
|
509
|
+
"music_generate",
|
|
510
|
+
"video_generate",
|
|
511
|
+
...DENCH_COMPOSIO_WRAPPER_TOOLS
|
|
512
|
+
];
|
|
513
|
+
function buildDenchCloudProviderConfig(params) {
|
|
514
|
+
return {
|
|
515
|
+
baseUrl: buildDenchGatewayApiBaseUrl(params.gatewayUrl),
|
|
516
|
+
apiKey: params.apiKey,
|
|
517
|
+
api: "openai-responses",
|
|
518
|
+
models: buildDenchCloudProviderModels(params.models)
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
function buildDenchCloudConfigPatch(params) {
|
|
522
|
+
return {
|
|
523
|
+
models: {
|
|
524
|
+
mode: "merge",
|
|
525
|
+
providers: {
|
|
526
|
+
"dench-cloud": buildDenchCloudProviderConfig(params)
|
|
527
|
+
}
|
|
528
|
+
},
|
|
529
|
+
agents: {
|
|
530
|
+
defaults: {
|
|
531
|
+
models: buildDenchCloudAgentModelEntries(params.models)
|
|
532
|
+
}
|
|
533
|
+
},
|
|
534
|
+
messages: {
|
|
535
|
+
tts: {
|
|
536
|
+
provider: "elevenlabs",
|
|
537
|
+
providers: {
|
|
538
|
+
elevenlabs: {
|
|
539
|
+
baseUrl: params.gatewayUrl,
|
|
540
|
+
apiKey: params.apiKey
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
tools: {
|
|
546
|
+
alsoAllow: [...DENCH_COMPOSIO_WRAPPER_TOOLS],
|
|
547
|
+
byProvider: {
|
|
548
|
+
"dench-cloud": {
|
|
549
|
+
allow: [...DENCH_CLOUD_TOOL_ALLOWLIST]
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// extensions/dench-ai-gateway/sync-trigger.ts
|
|
557
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
558
|
+
import { homedir } from "node:os";
|
|
559
|
+
import path2 from "node:path";
|
|
560
|
+
var DEFAULT_INTERVAL_MS = 5 * 60 * 1e3;
|
|
561
|
+
var DEFAULT_WEB_PORT = 3100;
|
|
562
|
+
var PROCESS_JSON_REL = path2.join("web-runtime", "process.json");
|
|
563
|
+
var FETCH_TIMEOUT_MS = 6e4;
|
|
564
|
+
function asRecord3(value) {
|
|
565
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
566
|
+
}
|
|
567
|
+
function readString3(value) {
|
|
568
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
569
|
+
}
|
|
570
|
+
function readNumber2(value) {
|
|
571
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
572
|
+
}
|
|
573
|
+
function resolveSyncTriggerConfig(api) {
|
|
574
|
+
const pluginConfig = asRecord3(asRecord3(asRecord3(api?.config)?.plugins)?.entries)?.["dench-ai-gateway"];
|
|
575
|
+
return asRecord3(asRecord3(pluginConfig)?.config?.["syncTrigger"]);
|
|
576
|
+
}
|
|
577
|
+
function resolveStateDir() {
|
|
578
|
+
const fromEnv = process.env.OPENCLAW_STATE_DIR?.trim();
|
|
579
|
+
if (fromEnv) {
|
|
580
|
+
return fromEnv;
|
|
581
|
+
}
|
|
582
|
+
const home = process.env.OPENCLAW_HOME?.trim() || homedir();
|
|
583
|
+
return path2.join(home, ".openclaw-dench");
|
|
584
|
+
}
|
|
585
|
+
function resolveWebPortFromProcessFile(stateDir) {
|
|
586
|
+
const processPath = path2.join(stateDir, PROCESS_JSON_REL);
|
|
587
|
+
if (!existsSync2(processPath)) {
|
|
588
|
+
return void 0;
|
|
589
|
+
}
|
|
590
|
+
try {
|
|
591
|
+
const parsed = JSON.parse(readFileSync2(processPath, "utf-8"));
|
|
592
|
+
return readNumber2(parsed?.port);
|
|
593
|
+
} catch {
|
|
594
|
+
return void 0;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
function resolveWebBaseUrl(api, syncTriggerConfig) {
|
|
598
|
+
const fromConfig = readString3(syncTriggerConfig?.webBaseUrl);
|
|
599
|
+
if (fromConfig) {
|
|
600
|
+
return fromConfig.replace(/\/$/, "");
|
|
601
|
+
}
|
|
602
|
+
const fromEnv = readString3(process.env.DENCHCLAW_WEB_BASE_URL);
|
|
603
|
+
if (fromEnv) {
|
|
604
|
+
return fromEnv.replace(/\/$/, "");
|
|
605
|
+
}
|
|
606
|
+
const port = resolveWebPortFromProcessFile(resolveStateDir()) ?? DEFAULT_WEB_PORT;
|
|
607
|
+
return `http://127.0.0.1:${port}`;
|
|
608
|
+
}
|
|
609
|
+
function outcomeKey(outcome) {
|
|
610
|
+
switch (outcome.kind) {
|
|
611
|
+
case "ok":
|
|
612
|
+
return "ok";
|
|
613
|
+
case "http":
|
|
614
|
+
return `http:${outcome.statusBucket}`;
|
|
615
|
+
case "timeout":
|
|
616
|
+
return "timeout";
|
|
617
|
+
case "network":
|
|
618
|
+
return `network:${outcome.message}`;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
function describeOutcome(outcome) {
|
|
622
|
+
switch (outcome.kind) {
|
|
623
|
+
case "ok":
|
|
624
|
+
return "ok";
|
|
625
|
+
case "http":
|
|
626
|
+
return `HTTP ${outcome.status}`;
|
|
627
|
+
case "timeout":
|
|
628
|
+
return `timed out after ${FETCH_TIMEOUT_MS}ms`;
|
|
629
|
+
case "network":
|
|
630
|
+
return outcome.message;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
function bucketFor(status) {
|
|
634
|
+
if (status >= 400 && status < 500) {
|
|
635
|
+
return "4xx";
|
|
636
|
+
}
|
|
637
|
+
if (status >= 500 && status < 600) {
|
|
638
|
+
return "5xx";
|
|
639
|
+
}
|
|
640
|
+
return "other";
|
|
641
|
+
}
|
|
642
|
+
var _armed = false;
|
|
643
|
+
function armSyncTrigger(api) {
|
|
644
|
+
if (_armed) {
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
const config = resolveSyncTriggerConfig(api);
|
|
648
|
+
if (config?.enabled === false) {
|
|
649
|
+
api?.logger?.info?.("[dench-ai-gateway] sync-trigger disabled via syncTrigger.enabled=false");
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
const apiKey = readDenchAuthProfileKey();
|
|
653
|
+
if (!apiKey) {
|
|
654
|
+
api?.logger?.info?.("[dench-ai-gateway] No Dench Cloud API key; sync trigger not armed.");
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
const intervalMs = readNumber2(config?.intervalMs) ?? DEFAULT_INTERVAL_MS;
|
|
658
|
+
if (intervalMs < 1e3) {
|
|
659
|
+
api?.logger?.info?.(
|
|
660
|
+
`[dench-ai-gateway] sync-trigger intervalMs=${intervalMs} below safety floor; not arming.`
|
|
661
|
+
);
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
const webBaseUrl = resolveWebBaseUrl(api, config);
|
|
665
|
+
const tickUrl = `${webBaseUrl}/api/sync/poll-tick`;
|
|
666
|
+
let lastOutcomeKey = "ok";
|
|
667
|
+
async function tick() {
|
|
668
|
+
const controller = new AbortController();
|
|
669
|
+
const timeoutHandle = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
670
|
+
let outcome;
|
|
671
|
+
try {
|
|
672
|
+
const response = await fetch(tickUrl, {
|
|
673
|
+
method: "POST",
|
|
674
|
+
headers: {
|
|
675
|
+
authorization: `Bearer ${apiKey}`,
|
|
676
|
+
"content-type": "application/json"
|
|
677
|
+
},
|
|
678
|
+
body: "{}",
|
|
679
|
+
signal: controller.signal
|
|
680
|
+
});
|
|
681
|
+
outcome = response.ok ? { kind: "ok" } : { kind: "http", statusBucket: bucketFor(response.status), status: response.status };
|
|
682
|
+
} catch (err) {
|
|
683
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
684
|
+
const aborted = err instanceof Error && (err.name === "AbortError" || /aborted/i.test(message));
|
|
685
|
+
outcome = aborted ? { kind: "timeout" } : { kind: "network", message };
|
|
686
|
+
} finally {
|
|
687
|
+
clearTimeout(timeoutHandle);
|
|
688
|
+
}
|
|
689
|
+
const key = outcomeKey(outcome);
|
|
690
|
+
const wasFailing = lastOutcomeKey !== "ok";
|
|
691
|
+
if (outcome.kind === "ok") {
|
|
692
|
+
if (wasFailing) {
|
|
693
|
+
api?.logger?.info?.(`[dench-ai-gateway] sync-trigger recovered (was: ${lastOutcomeKey})`);
|
|
694
|
+
}
|
|
695
|
+
} else if (key !== lastOutcomeKey) {
|
|
696
|
+
api?.logger?.info?.(
|
|
697
|
+
`[dench-ai-gateway] sync-trigger tick ${describeOutcome(outcome)} from ${tickUrl}`
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
lastOutcomeKey = key;
|
|
701
|
+
}
|
|
702
|
+
setInterval(() => {
|
|
703
|
+
void tick();
|
|
704
|
+
}, intervalMs);
|
|
705
|
+
_armed = true;
|
|
706
|
+
api?.logger?.info?.(`[dench-ai-gateway] sync-trigger armed (every ${intervalMs}ms \u2192 ${tickUrl})`);
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// extensions/dench-ai-gateway/sync-refresh-tools.ts
|
|
710
|
+
var REFRESH_TOOL_NAME = "denchclaw_refresh_sync";
|
|
711
|
+
var RESYNC_TOOL_NAME = "denchclaw_resync_full";
|
|
712
|
+
var REFRESH_TIMEOUT_MS = 3e4;
|
|
713
|
+
var RESYNC_TIMEOUT_MS = 6e4;
|
|
714
|
+
var REFRESH_PARAMETERS = {
|
|
715
|
+
type: "object",
|
|
716
|
+
additionalProperties: false,
|
|
717
|
+
properties: {}
|
|
718
|
+
};
|
|
719
|
+
function jsonResult2(payload, details) {
|
|
720
|
+
return {
|
|
721
|
+
content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
|
|
722
|
+
details: details ?? payload
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
function summarize(mode, body) {
|
|
726
|
+
if (body.ok === false) {
|
|
727
|
+
return `Sync ${mode} failed: ${body.error ?? "unknown error"}`;
|
|
728
|
+
}
|
|
729
|
+
if (body.alreadyRunning) {
|
|
730
|
+
return `A ${mode} sync is already running \u2014 no new tick started.`;
|
|
731
|
+
}
|
|
732
|
+
if (body.skipped === "backfill-in-progress") {
|
|
733
|
+
return "Skipped incremental tick because a full backfill is currently in progress.";
|
|
734
|
+
}
|
|
735
|
+
const evt = body.lastEvent;
|
|
736
|
+
if (evt?.phase === "error") {
|
|
737
|
+
return `Sync ${mode} reported an error: ${evt.error ?? evt.message ?? "unknown"}`;
|
|
738
|
+
}
|
|
739
|
+
if (mode === "incremental") {
|
|
740
|
+
const newMessages = evt?.messagesProcessed ?? 0;
|
|
741
|
+
const newEvents = evt?.eventsProcessed ?? 0;
|
|
742
|
+
if (newMessages === 0 && newEvents === 0) {
|
|
743
|
+
return "Incremental sync ran \u2014 no new emails or calendar events since the last tick.";
|
|
744
|
+
}
|
|
745
|
+
const parts = [];
|
|
746
|
+
if (newMessages > 0) {
|
|
747
|
+
parts.push(`${newMessages} new email${newMessages === 1 ? "" : "s"}`);
|
|
748
|
+
}
|
|
749
|
+
if (newEvents > 0) {
|
|
750
|
+
parts.push(`${newEvents} new event${newEvents === 1 ? "" : "s"}`);
|
|
751
|
+
}
|
|
752
|
+
return `Synced ${parts.join(" and ")}.`;
|
|
753
|
+
}
|
|
754
|
+
if (body.started) {
|
|
755
|
+
return "Full backfill started \u2014 Gmail and Calendar are re-importing in the background.";
|
|
756
|
+
}
|
|
757
|
+
return "Full backfill request acknowledged.";
|
|
758
|
+
}
|
|
759
|
+
async function callRefreshRoute(webBaseUrl, mode, timeoutMs) {
|
|
760
|
+
const controller = new AbortController();
|
|
761
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
762
|
+
try {
|
|
763
|
+
const res = await fetch(`${webBaseUrl}/api/sync/refresh`, {
|
|
764
|
+
method: "POST",
|
|
765
|
+
headers: { "content-type": "application/json", accept: "application/json" },
|
|
766
|
+
body: JSON.stringify({ mode }),
|
|
767
|
+
signal: controller.signal
|
|
768
|
+
});
|
|
769
|
+
const text = await res.text();
|
|
770
|
+
let body = {};
|
|
771
|
+
if (text.trim()) {
|
|
772
|
+
try {
|
|
773
|
+
body = JSON.parse(text);
|
|
774
|
+
} catch {
|
|
775
|
+
body = { error: text.slice(0, 240) };
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
return { status: res.status, body };
|
|
779
|
+
} finally {
|
|
780
|
+
clearTimeout(timer);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
function createRefreshSyncTool(api) {
|
|
784
|
+
const webBaseUrl = resolveWebBaseUrl(api, resolveSyncTriggerConfig(api));
|
|
785
|
+
return {
|
|
786
|
+
name: REFRESH_TOOL_NAME,
|
|
787
|
+
label: "Refresh Gmail/Calendar sync",
|
|
788
|
+
description: "Trigger an incremental Gmail and Calendar sync tick right now. Use this when the user asks to refresh, sync now, pull new emails, or check whether anything new has arrived. Cheap and fast (1-2 seconds). For a full re-import use denchclaw_resync_full instead.",
|
|
789
|
+
parameters: REFRESH_PARAMETERS,
|
|
790
|
+
async execute(_toolCallId, _input) {
|
|
791
|
+
try {
|
|
792
|
+
const { status, body } = await callRefreshRoute(
|
|
793
|
+
webBaseUrl,
|
|
794
|
+
"incremental",
|
|
795
|
+
REFRESH_TIMEOUT_MS
|
|
796
|
+
);
|
|
797
|
+
if (status >= 400) {
|
|
798
|
+
return jsonResult2(
|
|
799
|
+
{
|
|
800
|
+
error: body.error ?? `Refresh failed (HTTP ${status}).`,
|
|
801
|
+
mode: "incremental"
|
|
802
|
+
},
|
|
803
|
+
{ status: "error", httpStatus: status }
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
return {
|
|
807
|
+
content: [{ type: "text", text: summarize("incremental", body) }],
|
|
808
|
+
details: { mode: "incremental", response: body }
|
|
809
|
+
};
|
|
810
|
+
} catch (err) {
|
|
811
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
812
|
+
return jsonResult2(
|
|
813
|
+
{ error: `Refresh request failed: ${message}`, mode: "incremental" },
|
|
814
|
+
{ status: "error" }
|
|
815
|
+
);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
function createResyncFullTool(api) {
|
|
821
|
+
const webBaseUrl = resolveWebBaseUrl(api, resolveSyncTriggerConfig(api));
|
|
822
|
+
return {
|
|
823
|
+
name: RESYNC_TOOL_NAME,
|
|
824
|
+
label: "Full Gmail/Calendar resync",
|
|
825
|
+
description: "Trigger a full Gmail and Calendar backfill \u2014 re-imports messages and events from scratch. Use this only when the user explicitly asks for a full resync, after they have reconnected an account, or when the incremental refresh (denchclaw_refresh_sync) repeatedly fails to surface messages they expect to see. Heavier than incremental sync; runs in the background.",
|
|
826
|
+
parameters: REFRESH_PARAMETERS,
|
|
827
|
+
async execute(_toolCallId, _input) {
|
|
828
|
+
try {
|
|
829
|
+
const { status, body } = await callRefreshRoute(webBaseUrl, "backfill", RESYNC_TIMEOUT_MS);
|
|
830
|
+
if (status >= 400) {
|
|
831
|
+
return jsonResult2(
|
|
832
|
+
{
|
|
833
|
+
error: body.error ?? `Resync failed (HTTP ${status}).`,
|
|
834
|
+
mode: "backfill"
|
|
835
|
+
},
|
|
836
|
+
{ status: "error", httpStatus: status }
|
|
837
|
+
);
|
|
838
|
+
}
|
|
839
|
+
return {
|
|
840
|
+
content: [{ type: "text", text: summarize("backfill", body) }],
|
|
841
|
+
details: { mode: "backfill", response: body }
|
|
842
|
+
};
|
|
843
|
+
} catch (err) {
|
|
844
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
845
|
+
return jsonResult2(
|
|
846
|
+
{ error: `Resync request failed: ${message}`, mode: "backfill" },
|
|
847
|
+
{ status: "error" }
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
function registerSyncRefreshTools(api) {
|
|
854
|
+
const refresh = createRefreshSyncTool(api);
|
|
855
|
+
const resync = createResyncFullTool(api);
|
|
856
|
+
api.registerTool(refresh, { name: REFRESH_TOOL_NAME, optional: true });
|
|
857
|
+
api.registerTool(resync, { name: RESYNC_TOOL_NAME, optional: true });
|
|
858
|
+
return [refresh.name, resync.name];
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// extensions/dench-ai-gateway/index.ts
|
|
862
|
+
var id = "dench-ai-gateway";
|
|
863
|
+
var PROVIDER_ID = "dench-cloud";
|
|
864
|
+
var PROVIDER_LABEL = "Dench Cloud";
|
|
865
|
+
var API_KEY_ENV_VARS = ["DENCH_CLOUD_API_KEY", "DENCH_API_KEY"];
|
|
866
|
+
function asRecord4(value) {
|
|
867
|
+
return value && typeof value === "object" ? value : void 0;
|
|
868
|
+
}
|
|
869
|
+
function resolvePluginConfig(api) {
|
|
870
|
+
const pluginConfig = api?.config?.plugins?.entries?.["dench-ai-gateway"]?.config;
|
|
871
|
+
return asRecord4(pluginConfig);
|
|
872
|
+
}
|
|
873
|
+
function resolveGatewayUrl(api) {
|
|
874
|
+
const pluginConfig = resolvePluginConfig(api);
|
|
875
|
+
const configured = typeof pluginConfig?.gatewayUrl === "string" ? pluginConfig.gatewayUrl : void 0;
|
|
876
|
+
return normalizeDenchGatewayUrl(
|
|
877
|
+
configured || process.env.DENCH_GATEWAY_URL || DEFAULT_DENCH_CLOUD_GATEWAY_URL
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
function resolveEnvApiKey() {
|
|
881
|
+
for (const envVar of API_KEY_ENV_VARS) {
|
|
882
|
+
const value = process.env[envVar]?.trim();
|
|
883
|
+
if (value) {
|
|
884
|
+
return value;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return void 0;
|
|
888
|
+
}
|
|
889
|
+
async function promptForApiKey(prompter) {
|
|
890
|
+
if (typeof prompter?.secret === "function") {
|
|
891
|
+
return String(
|
|
892
|
+
await prompter.secret(
|
|
893
|
+
"Enter your Dench Cloud API key (sign up at dench.com and get it at dench.com/settings)"
|
|
894
|
+
)
|
|
895
|
+
).trim();
|
|
896
|
+
}
|
|
897
|
+
return String(
|
|
898
|
+
await prompter.text({
|
|
899
|
+
message: "Enter your Dench Cloud API key (sign up at dench.com and get it at dench.com/settings)"
|
|
900
|
+
})
|
|
901
|
+
).trim();
|
|
902
|
+
}
|
|
903
|
+
async function fetchDenchCloudCatalog(gatewayUrl) {
|
|
904
|
+
try {
|
|
905
|
+
const response = await fetch(buildDenchGatewayCatalogUrl(gatewayUrl));
|
|
906
|
+
if (!response.ok) {
|
|
907
|
+
throw new Error(`HTTP ${response.status}`);
|
|
908
|
+
}
|
|
909
|
+
const payload = await response.json().catch(() => null);
|
|
910
|
+
const models = normalizeDenchCloudCatalogResponse(payload);
|
|
911
|
+
if (!models.length) {
|
|
912
|
+
throw new Error("response did not contain any usable models");
|
|
913
|
+
}
|
|
914
|
+
return { models, source: "live" };
|
|
915
|
+
} catch (error) {
|
|
916
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
917
|
+
return {
|
|
918
|
+
models: cloneFallbackDenchCloudModels(),
|
|
919
|
+
source: "fallback",
|
|
920
|
+
detail
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
var DENCH_CLOUD_API_KEY_VALIDATION_TIMEOUT_MS = 15e3;
|
|
925
|
+
async function validateDenchCloudApiKey(gatewayUrl, apiKey) {
|
|
926
|
+
const apiBaseUrl = buildDenchGatewayApiBaseUrl(gatewayUrl);
|
|
927
|
+
let response;
|
|
928
|
+
try {
|
|
929
|
+
response = await fetch(`${apiBaseUrl}/models`, {
|
|
930
|
+
headers: {
|
|
931
|
+
Authorization: `Bearer ${apiKey}`
|
|
932
|
+
},
|
|
933
|
+
signal: AbortSignal.timeout(DENCH_CLOUD_API_KEY_VALIDATION_TIMEOUT_MS)
|
|
934
|
+
});
|
|
935
|
+
} catch (err) {
|
|
936
|
+
const cause = err instanceof Error ? err.message : String(err);
|
|
937
|
+
throw new Error(
|
|
938
|
+
`Could not reach Dench Cloud gateway at ${apiBaseUrl} (${cause}). Check your network connection and gateway URL, then try again.`
|
|
939
|
+
);
|
|
940
|
+
}
|
|
941
|
+
if (response.ok) {
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
const message = response.status === 401 || response.status === 403 ? "Invalid Dench Cloud API key." : `Dench Cloud validation failed with HTTP ${response.status}.`;
|
|
945
|
+
throw new Error(`${message} Check your key at dench.com/settings.`);
|
|
946
|
+
}
|
|
947
|
+
async function promptForModelSelection(params) {
|
|
948
|
+
const selectedStableId = String(
|
|
949
|
+
await params.prompter.select({
|
|
950
|
+
message: "Choose your default Dench Cloud model",
|
|
951
|
+
options: params.models.map((model) => ({
|
|
952
|
+
value: model.stableId,
|
|
953
|
+
label: model.displayName,
|
|
954
|
+
hint: formatDenchCloudModelHint(model)
|
|
955
|
+
})),
|
|
956
|
+
...params.initialStableId ? { initialValue: params.initialStableId } : {}
|
|
957
|
+
})
|
|
958
|
+
);
|
|
959
|
+
const selected = resolveDenchCloudModel(params.models, selectedStableId);
|
|
960
|
+
if (!selected) {
|
|
961
|
+
throw new Error(`Unknown Dench Cloud model "${selectedStableId}".`);
|
|
962
|
+
}
|
|
963
|
+
return selected;
|
|
964
|
+
}
|
|
965
|
+
function buildAuthNotes(params) {
|
|
966
|
+
const notes = [
|
|
967
|
+
`Dench Cloud uses ${buildDenchGatewayApiBaseUrl(params.gatewayUrl)} for model traffic.`
|
|
968
|
+
];
|
|
969
|
+
if (params.catalog.source === "fallback") {
|
|
970
|
+
notes.push(
|
|
971
|
+
`Model catalog fell back to DenchClaw's bundled list (${params.catalog.detail ?? "public catalog unavailable"}).`
|
|
972
|
+
);
|
|
973
|
+
}
|
|
974
|
+
return notes;
|
|
975
|
+
}
|
|
976
|
+
function buildProviderAuthResult(params) {
|
|
977
|
+
return {
|
|
978
|
+
profiles: [
|
|
979
|
+
{
|
|
980
|
+
profileId: `${PROVIDER_ID}:default`,
|
|
981
|
+
credential: {
|
|
982
|
+
type: "api_key",
|
|
983
|
+
provider: PROVIDER_ID,
|
|
984
|
+
key: params.apiKey
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
],
|
|
988
|
+
defaultModel: `${PROVIDER_ID}/${params.selected.stableId}`,
|
|
989
|
+
configPatch: buildDenchCloudConfigPatch({
|
|
990
|
+
gatewayUrl: params.gatewayUrl,
|
|
991
|
+
apiKey: params.apiKey,
|
|
992
|
+
models: params.catalog.models
|
|
993
|
+
}),
|
|
994
|
+
notes: buildAuthNotes({
|
|
995
|
+
gatewayUrl: params.gatewayUrl,
|
|
996
|
+
catalog: params.catalog
|
|
997
|
+
})
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
async function runInteractiveAuth(ctx, gatewayUrl) {
|
|
1001
|
+
const apiKey = await promptForApiKey(ctx.prompter);
|
|
1002
|
+
if (!apiKey) {
|
|
1003
|
+
throw new Error("A Dench Cloud API key is required.");
|
|
1004
|
+
}
|
|
1005
|
+
await validateDenchCloudApiKey(gatewayUrl, apiKey);
|
|
1006
|
+
const catalog = await fetchDenchCloudCatalog(gatewayUrl);
|
|
1007
|
+
const selected = await promptForModelSelection({
|
|
1008
|
+
prompter: ctx.prompter,
|
|
1009
|
+
models: catalog.models
|
|
1010
|
+
});
|
|
1011
|
+
return buildProviderAuthResult({
|
|
1012
|
+
gatewayUrl,
|
|
1013
|
+
apiKey,
|
|
1014
|
+
catalog,
|
|
1015
|
+
selected
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
async function runNonInteractiveAuth(ctx, gatewayUrl) {
|
|
1019
|
+
const apiKey = String(
|
|
1020
|
+
ctx?.opts?.denchCloudApiKey || ctx?.opts?.denchCloudKey || resolveEnvApiKey() || ""
|
|
1021
|
+
).trim();
|
|
1022
|
+
if (!apiKey) {
|
|
1023
|
+
throw new Error(
|
|
1024
|
+
"Dench Cloud non-interactive auth requires DENCH_CLOUD_API_KEY or --dench-cloud-api-key."
|
|
1025
|
+
);
|
|
1026
|
+
}
|
|
1027
|
+
await validateDenchCloudApiKey(gatewayUrl, apiKey);
|
|
1028
|
+
const catalog = await fetchDenchCloudCatalog(gatewayUrl);
|
|
1029
|
+
const selected = resolveDenchCloudModel(
|
|
1030
|
+
catalog.models,
|
|
1031
|
+
String(ctx?.opts?.denchCloudModel || process.env.DENCH_CLOUD_MODEL || "").trim()
|
|
1032
|
+
);
|
|
1033
|
+
if (!selected) {
|
|
1034
|
+
throw new Error("Configured Dench Cloud model is not available.");
|
|
1035
|
+
}
|
|
1036
|
+
return buildProviderAuthResult({
|
|
1037
|
+
gatewayUrl,
|
|
1038
|
+
apiKey,
|
|
1039
|
+
catalog,
|
|
1040
|
+
selected
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1043
|
+
function buildDiscoveryProvider(api, gatewayUrl) {
|
|
1044
|
+
const configured = api?.config?.models?.providers?.[PROVIDER_ID];
|
|
1045
|
+
if (configured && typeof configured === "object") {
|
|
1046
|
+
return configured;
|
|
1047
|
+
}
|
|
1048
|
+
const apiKey = resolveEnvApiKey();
|
|
1049
|
+
if (!apiKey) {
|
|
1050
|
+
return null;
|
|
1051
|
+
}
|
|
1052
|
+
const models = cloneFallbackDenchCloudModels();
|
|
1053
|
+
return buildDenchCloudProviderConfig({ gatewayUrl, apiKey, models });
|
|
1054
|
+
}
|
|
1055
|
+
function register(api) {
|
|
1056
|
+
const pluginConfig = resolvePluginConfig(api);
|
|
1057
|
+
if (pluginConfig?.enabled === false) {
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
const gatewayUrl = resolveGatewayUrl(api);
|
|
1061
|
+
api.registerProvider({
|
|
1062
|
+
id: PROVIDER_ID,
|
|
1063
|
+
label: PROVIDER_LABEL,
|
|
1064
|
+
docsPath: "/providers/models",
|
|
1065
|
+
aliases: ["dench", "dench-cloud", "dench-ai-gateway"],
|
|
1066
|
+
envVars: [...API_KEY_ENV_VARS],
|
|
1067
|
+
auth: [
|
|
1068
|
+
{
|
|
1069
|
+
id: "api-key",
|
|
1070
|
+
label: "Dench Cloud API Key",
|
|
1071
|
+
hint: "Use your Dench Cloud key from dench.com/settings",
|
|
1072
|
+
kind: "api_key",
|
|
1073
|
+
run: async (ctx) => await runInteractiveAuth(ctx, gatewayUrl),
|
|
1074
|
+
// Newer OpenClaw builds can call this hook during headless onboarding.
|
|
1075
|
+
runNonInteractive: async (ctx) => await runNonInteractiveAuth(ctx, gatewayUrl)
|
|
1076
|
+
}
|
|
1077
|
+
],
|
|
1078
|
+
// Newer OpenClaw builds can surface provider-specific wizard entries.
|
|
1079
|
+
wizard: {
|
|
1080
|
+
onboarding: {
|
|
1081
|
+
choiceId: PROVIDER_ID,
|
|
1082
|
+
choiceLabel: PROVIDER_LABEL,
|
|
1083
|
+
choiceHint: "Use Dench's managed AI gateway",
|
|
1084
|
+
groupId: "dench",
|
|
1085
|
+
groupLabel: "Dench",
|
|
1086
|
+
groupHint: "Managed Dench Cloud models",
|
|
1087
|
+
methodId: "api-key"
|
|
1088
|
+
},
|
|
1089
|
+
modelPicker: {
|
|
1090
|
+
label: PROVIDER_LABEL,
|
|
1091
|
+
hint: "Connect Dench Cloud with your API key",
|
|
1092
|
+
methodId: "api-key"
|
|
1093
|
+
}
|
|
1094
|
+
},
|
|
1095
|
+
// Best-effort discovery so newer OpenClaw builds can rehydrate provider config.
|
|
1096
|
+
discovery: {
|
|
1097
|
+
order: "profile",
|
|
1098
|
+
run: async () => {
|
|
1099
|
+
const provider = buildDiscoveryProvider(api, gatewayUrl);
|
|
1100
|
+
return provider ? { provider } : null;
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1104
|
+
registerDenchIntegrationsBridge(api, gatewayUrl);
|
|
1105
|
+
armSyncTrigger(api);
|
|
1106
|
+
if (typeof api?.registerTool === "function" && readDenchAuthProfileKey()) {
|
|
1107
|
+
const registered = registerSyncRefreshTools(api);
|
|
1108
|
+
api.logger?.info?.(
|
|
1109
|
+
`[dench-ai-gateway] registered sync refresh tools: ${registered.join(", ")}`
|
|
1110
|
+
);
|
|
1111
|
+
}
|
|
1112
|
+
api.registerService({
|
|
1113
|
+
id: "dench-ai-gateway",
|
|
1114
|
+
start: () => {
|
|
1115
|
+
api.logger?.info?.(`[dench-ai-gateway] active (gateway: ${gatewayUrl})`);
|
|
1116
|
+
},
|
|
1117
|
+
stop: () => {
|
|
1118
|
+
api.logger?.info?.("[dench-ai-gateway] stopped");
|
|
1119
|
+
}
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
export {
|
|
1123
|
+
buildDenchCloudConfigPatch,
|
|
1124
|
+
register as default,
|
|
1125
|
+
fetchDenchCloudCatalog,
|
|
1126
|
+
id,
|
|
1127
|
+
validateDenchCloudApiKey
|
|
1128
|
+
};
|