@inneranimalmedia/agentsam-sdk 2.6.1 → 2.6.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/AGENTSAM.md +45 -1
- package/README.md +80 -0
- package/apps/README.md +34 -0
- package/apps/cad-creator/README.md +728 -0
- package/apps/cad-creator/shared/cad/package.json +19 -0
- package/apps/cad-creator/shared/cad/src/domain/operations.ts +7 -0
- package/apps/cad-creator/shared/cad/src/domain/project-contract.d.ts +3 -0
- package/apps/cad-creator/shared/cad/src/domain/project-contract.js +75 -0
- package/apps/cad-creator/shared/cad/src/domain/project-tools.d.ts +1 -0
- package/apps/cad-creator/shared/cad/src/domain/project-tools.js +24 -0
- package/apps/cad-creator/shared/cad/src/domain/validation.ts +191 -0
- package/apps/cad-creator/shared/cad/src/index.ts +4 -0
- package/apps/cad-creator/shared/cad/src/robotics/types.ts +232 -0
- package/apps/cad-creator/shared/cad/src/types.ts +507 -0
- package/apps/cad-creator/shared/cad/tsconfig.json +14 -0
- package/docs/AUTH_IDENTITY_CONTRACT.md +25 -27
- package/docs/AUTORAG.md +58 -0
- package/docs/BRAND_INTELLIGENCE.md +30 -0
- package/docs/CLI_SHELL.md +4 -2
- package/docs/CMS_CONTEXTUAL_COMPOSER.md +38 -0
- package/docs/MERKLE.md +4 -0
- package/docs/PROJECT_CONFIG.md +3 -0
- package/docs/REPOSITORY_KNOWLEDGE.md +2 -0
- package/docs/SDK_WORKER.md +4 -3
- package/docs/THEME_REFINERY.md +120 -0
- package/docs/architecture/PROVIDER-TOOLS-AND-COMPACTION.md +60 -0
- package/docs/architecture/STORAGE.md +87 -0
- package/docs/cad-project-tools.md +69 -0
- package/docs/cms-scaffolding-pattern-reference.md +73 -0
- package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS-codex-tui-20260919.md +113 -0
- package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS.md +85 -0
- package/docs/plans/AGENTSAM-MCP-CLIENT-2026-09-19.md +181 -0
- package/docs/plans/ASBD-PORTABLE-WORKGRAPH-UI-DEFERRED.md +34 -0
- package/docs/plans/ASTRA-BRIEF-2026-09-18.md +258 -0
- package/docs/plans/MULTI-AGENT-SPRINTS-2026-09-19.md +373 -0
- package/docs/plans/NEXT-AGENT-HANDOFF.md +167 -0
- package/docs/plans/RECONCILIATION-2026-09-19.md +178 -0
- package/docs/plugins.md +43 -0
- package/docs/tools/README.md +57 -0
- package/docs/tools/agent-and-orchestration.md +49 -0
- package/docs/tools/browser-and-research.md +46 -0
- package/docs/tools/cloudflare-platform.md +32 -0
- package/docs/tools/cms.md +25 -0
- package/docs/tools/communications.md +41 -0
- package/docs/tools/database-and-storage.md +62 -0
- package/docs/tools/design-and-media.md +64 -0
- package/docs/tools/filesystem-and-code.md +55 -0
- package/docs/tools/github.md +56 -0
- package/docs/tools/integrations-and-misc.md +16 -0
- package/docs/tools/memory.md +21 -0
- package/docs/tools/terminal-and-execution.md +29 -0
- package/docs/tools/tickets-and-platform.md +30 -0
- package/migrations/d1/0001_agentsam_plugin_runtime.sql +177 -0
- package/migrations/d1/0002_agentsam_ticket_ownership.sql +8 -0
- package/migrations/d1/0002_dynamic_model_policies.sql +23 -0
- package/migrations/d1/0003_expand_tool_handler_families.sql +18 -0
- package/migrations/d1/0004_project_aware_retrieval_lanes.sql +24 -0
- package/migrations/d1/0005_portable_knowledge_identity.sql +104 -0
- package/migrations/d1/0006_repair_ops_trail_account_scope.sql +14 -0
- package/migrations/d1/0007_repair_ops_trail_agent_run_account.sql +13 -0
- package/migrations/d1/0008_backfill_knowledge_run_legacy_tenant.sql +14 -0
- package/migrations/d1/0009_normalize_cloudflare_plugin_installations.sql +137 -0
- package/migrations/runtime/0001_cli_runtime.sql +67 -0
- package/migrations/runtime/0002_project_sessions.sql +15 -0
- package/migrations/runtime/0003_provider_continuations.sql +8 -0
- package/package.json +92 -12
- package/packages/agentsam-brand/README.md +21 -0
- package/packages/agentsam-brand/package.json +22 -0
- package/packages/agentsam-brand/src/contract.js +59 -0
- package/packages/agentsam-brand/src/extract.js +126 -0
- package/packages/agentsam-brand/src/goap-actions.js +73 -0
- package/packages/agentsam-brand/src/index.js +48 -0
- package/packages/agentsam-brand/src/plan.js +115 -0
- package/packages/agentsam-brand/src/resolve.js +139 -0
- package/packages/agentsam-brand/src/scan.js +250 -0
- package/packages/agentsam-brand/test/brand-scan.test.mjs +106 -0
- package/packages/agentsam-contracts/README.md +23 -0
- package/packages/agentsam-contracts/package.json +32 -0
- package/packages/agentsam-contracts/src/adapter.ts +25 -0
- package/packages/agentsam-contracts/src/agent.ts +35 -0
- package/packages/agentsam-contracts/src/artifacts.ts +33 -0
- package/packages/agentsam-contracts/src/authority.ts +29 -0
- package/packages/agentsam-contracts/src/context.ts +16 -0
- package/packages/agentsam-contracts/src/errors.ts +46 -0
- package/packages/agentsam-contracts/src/events.ts +47 -0
- package/packages/agentsam-contracts/src/execution.ts +50 -0
- package/packages/agentsam-contracts/src/hooks.ts +40 -0
- package/packages/agentsam-contracts/src/identity.ts +16 -0
- package/packages/agentsam-contracts/src/index.ts +14 -0
- package/packages/agentsam-contracts/src/models.ts +9 -0
- package/packages/agentsam-contracts/src/providers.ts +33 -0
- package/packages/agentsam-contracts/src/repository.ts +64 -0
- package/packages/agentsam-contracts/src/tools.ts +98 -0
- package/packages/agentsam-contracts/test/contracts.test.mjs +16 -0
- package/packages/agentsam-contracts/test/errors-catalog.test.mjs +25 -0
- package/packages/agentsam-contracts/test/repository.test.mjs +18 -0
- package/packages/agentsam-contracts/tsconfig.json +12 -0
- package/packages/agentsam-errors/package.json +17 -0
- package/packages/agentsam-errors/src/adapters/anthropic.js +15 -0
- package/packages/agentsam-errors/src/adapters/cad.js +109 -0
- package/packages/agentsam-errors/src/adapters/cloudflare.js +21 -0
- package/packages/agentsam-errors/src/adapters/cursor.js +4 -0
- package/packages/agentsam-errors/src/adapters/device.js +38 -0
- package/packages/agentsam-errors/src/adapters/docker.js +28 -0
- package/packages/agentsam-errors/src/adapters/gcp.js +14 -0
- package/packages/agentsam-errors/src/adapters/github.js +22 -0
- package/packages/agentsam-errors/src/adapters/google.js +17 -0
- package/packages/agentsam-errors/src/adapters/index.js +55 -0
- package/packages/agentsam-errors/src/adapters/internal.js +40 -0
- package/packages/agentsam-errors/src/adapters/oauth.js +24 -0
- package/packages/agentsam-errors/src/adapters/openai.js +17 -0
- package/packages/agentsam-errors/src/adapters/process.js +35 -0
- package/packages/agentsam-errors/src/adapters/provider.js +114 -0
- package/packages/agentsam-errors/src/envelope.js +186 -0
- package/packages/agentsam-errors/src/error.js +24 -0
- package/packages/agentsam-errors/src/fingerprint.js +35 -0
- package/packages/agentsam-errors/src/index.js +10 -0
- package/packages/agentsam-errors/src/normalize.js +30 -0
- package/packages/agentsam-errors/src/redaction.js +52 -0
- package/packages/agentsam-errors/src/render.js +16 -0
- package/packages/agentsam-errors/src/retry.js +10 -0
- package/packages/agentsam-errors/src/transport.js +52 -0
- package/packages/agentsam-errors/src/vocabulary.js +320 -0
- package/packages/agentsam-errors/test/envelope.test.mjs +70 -0
- package/packages/agentsam-errors/test/providers.test.mjs +99 -0
- package/packages/agentsam-errors/test/redaction.test.mjs +21 -0
- package/packages/agentsam-errors/test/runtime-cad-device.test.mjs +76 -0
- package/packages/agentsam-errors/test/transport.test.mjs +46 -0
- package/packages/agentsam-knowledge/package.json +15 -0
- package/packages/agentsam-knowledge/src/autorag/index.js +64 -0
- package/packages/agentsam-knowledge/src/backends/index.js +26 -0
- package/packages/agentsam-knowledge/src/index.js +3 -0
- package/packages/agentsam-knowledge/src/providers/index.js +95 -0
- package/packages/agentsam-knowledge/test/autorag.test.mjs +42 -0
- package/packages/agentsam-nav/README.md +40 -0
- package/packages/agentsam-nav/dist/Nav.d.ts +43 -0
- package/packages/agentsam-nav/dist/NavCollapsible.d.ts +10 -0
- package/packages/agentsam-nav/dist/NavContent.d.ts +2 -0
- package/packages/agentsam-nav/dist/NavFooter.d.ts +2 -0
- package/packages/agentsam-nav/dist/NavGroup.d.ts +3 -0
- package/packages/agentsam-nav/dist/NavHeader.d.ts +2 -0
- package/packages/agentsam-nav/dist/NavMenu.d.ts +22 -0
- package/packages/agentsam-nav/dist/NavProvider.d.ts +35 -0
- package/packages/agentsam-nav/dist/NavTrigger.d.ts +2 -0
- package/packages/agentsam-nav/dist/Surfaces.d.ts +41 -0
- package/packages/agentsam-nav/dist/browser.d.ts +11 -0
- package/packages/agentsam-nav/dist/browser.global.js +132 -0
- package/packages/agentsam-nav/dist/browser.js +613 -0
- package/packages/agentsam-nav/dist/contracts.d.ts +76 -0
- package/packages/agentsam-nav/dist/index.d.ts +11 -0
- package/packages/agentsam-nav/dist/index.js +614 -0
- package/packages/agentsam-nav/dist/legacy.css +83 -0
- package/packages/agentsam-nav/dist/shell.css +113 -0
- package/packages/agentsam-nav/dist/theme.css +113 -0
- package/packages/agentsam-nav/dist/utils.d.ts +1 -0
- package/packages/agentsam-nav/package.json +43 -0
- package/packages/agentsam-queue-control/README.md +107 -0
- package/packages/agentsam-queue-control/package.json +31 -0
- package/packages/agentsam-queue-control/schemas/job-envelope.schema.json +56 -0
- package/packages/agentsam-queue-control/src/adapters/cloudflare.js +152 -0
- package/packages/agentsam-queue-control/src/adapters/memory.js +38 -0
- package/packages/agentsam-queue-control/src/contracts.js +130 -0
- package/packages/agentsam-queue-control/src/control-plane.js +141 -0
- package/packages/agentsam-queue-control/src/dispatch.js +43 -0
- package/packages/agentsam-queue-control/src/index.js +7 -0
- package/packages/agentsam-queue-control/src/policy.js +88 -0
- package/packages/agentsam-queue-control/src/topology.js +66 -0
- package/packages/agentsam-queue-control/test/queue-control.test.mjs +100 -0
- package/packages/agentsam-repository/src/goap.js +718 -0
- package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +670 -0
- package/packages/agentsam-repository/src/index.js +5 -0
- package/packages/agentsam-repository/src/merkle/cloudflare-persistence.js +2 -2
- package/packages/agentsam-repository/src/tickets.js +184 -0
- package/packages/agentsam-repository/src/work-tracking.js +199 -0
- package/packages/agentsam-repository/src/workspace-state.js +176 -0
- package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +152 -0
- package/packages/connectors/cloudflare/src/index.js +297 -15
- package/packages/connectors/cloudflare/src/owner.js +43 -40
- package/packages/connectors/cloudflare/src/routes.js +167 -26
- package/packages/connectors/cloudflare/tests/connector.test.mjs +112 -2
- package/packages/heuristic-theme/README.md +11 -0
- package/packages/heuristic-theme/package.json +25 -0
- package/packages/heuristic-theme/src/index.js +2 -0
- package/packages/heuristic-theme/src/registry.js +36 -0
- package/packages/heuristic-theme/src/theme.js +41 -0
- package/packages/heuristic-theme/test/theme.test.mjs +26 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +64 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +96 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/resources.json +47 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +74 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/ui.json +35 -0
- package/packages/identity/package.json +4 -3
- package/packages/identity/src/adapters/cloudflare-d1/ids.js +4 -0
- package/packages/identity/src/adapters/cloudflare-d1/index.js +39 -1
- package/packages/identity/src/contracts/auth-config.js +23 -40
- package/packages/identity/src/contracts/provider.js +3 -2
- package/packages/identity/src/frontend/auth-portal/pages/login.html +7 -0
- package/packages/identity/src/index.js +2 -0
- package/packages/identity/src/oauth/credentials.js +13 -0
- package/packages/identity/src/oauth/iam-platform.js +5 -5
- package/packages/identity/src/providers/cloudflare/index.js +19 -0
- package/packages/identity/src/providers/cloudflare/mapper.js +21 -0
- package/packages/identity/src/providers/cloudflare/oauth.js +48 -0
- package/packages/identity/src/providers/cloudflare/profile.js +28 -0
- package/packages/identity/src/providers/index.js +18 -2
- package/packages/identity/src/server/identity-service.js +13 -3
- package/packages/identity/src/server/worker-router.js +63 -8
- package/packages/identity/tests/auth-config.test.mjs +14 -23
- package/packages/identity/tests/identity-service.test.mjs +15 -0
- package/packages/providers/completeful/README.md +38 -0
- package/packages/providers/completeful/package.json +29 -0
- package/packages/providers/completeful/src/client.js +162 -0
- package/packages/providers/completeful/src/events.js +49 -0
- package/packages/providers/completeful/src/index.js +22 -0
- package/packages/providers/completeful/src/tools.js +579 -0
- package/packages/providers/completeful/src/webhooks.js +55 -0
- package/packages/providers/completeful/test/provider.test.mjs +196 -0
- package/packages/theme-church-site/README.md +10 -0
- package/packages/theme-church-site/package.json +30 -0
- package/packages/theme-church-site/src/harvest.json +14 -0
- package/packages/theme-church-site/src/index.js +84 -0
- package/packages/theme-church-site/test/theme.test.mjs +19 -0
- package/packages/theme-companions-site/README.md +10 -0
- package/packages/theme-companions-site/package.json +30 -0
- package/packages/theme-companions-site/src/harvest.json +12 -0
- package/packages/theme-companions-site/src/index.js +82 -0
- package/packages/theme-companions-site/test/theme.test.mjs +19 -0
- package/packages/theme-floors-site/README.md +10 -0
- package/packages/theme-floors-site/package.json +30 -0
- package/packages/theme-floors-site/src/harvest.json +14 -0
- package/packages/theme-floors-site/src/index.js +82 -0
- package/packages/theme-floors-site/test/theme.test.mjs +19 -0
- package/packages/theme-fuelnfree-site/README.md +10 -0
- package/packages/theme-fuelnfree-site/package.json +30 -0
- package/packages/theme-fuelnfree-site/src/harvest.json +13 -0
- package/packages/theme-fuelnfree-site/src/index.js +81 -0
- package/packages/theme-fuelnfree-site/test/theme.test.mjs +19 -0
- package/packages/theme-handyman-site/README.md +10 -0
- package/packages/theme-handyman-site/package.json +30 -0
- package/packages/theme-handyman-site/src/harvest.json +10 -0
- package/packages/theme-handyman-site/src/index.js +83 -0
- package/packages/theme-handyman-site/test/theme.test.mjs +19 -0
- package/packages/theme-insurance-site/README.md +10 -0
- package/packages/theme-insurance-site/package.json +30 -0
- package/packages/theme-insurance-site/src/harvest.json +10 -0
- package/packages/theme-insurance-site/src/index.js +83 -0
- package/packages/theme-insurance-site/test/theme.test.mjs +19 -0
- package/packages/theme-shinshu-site/README.md +10 -0
- package/packages/theme-shinshu-site/package.json +30 -0
- package/packages/theme-shinshu-site/src/harvest.json +12 -0
- package/packages/theme-shinshu-site/src/index.js +83 -0
- package/packages/theme-shinshu-site/test/theme.test.mjs +19 -0
- package/packages/work-graph/README.md +49 -0
- package/packages/work-graph/package.json +19 -0
- package/packages/work-graph/prototype/README.md +32 -0
- package/packages/work-graph/prototype/data/demo-workgraph.js +47 -0
- package/packages/work-graph/prototype/renderers/timeline-model.js +21 -0
- package/packages/work-graph/prototype/renderers/workgraph-runtime.js +38 -0
- package/packages/work-graph/prototype-gnantt.html +655 -0
- package/packages/work-graph/src/adapters/business/projects.js +23 -0
- package/packages/work-graph/src/adapters/engineering/git.js +22 -0
- package/packages/work-graph/src/adapters/engineering/mcp.js +22 -0
- package/packages/work-graph/src/index.js +76 -0
- package/packages/work-graph/src/renderers/gantt-model.js +11 -0
- package/packages/work-graph/src/renderers/timeline.js +16 -0
- package/packages/work-graph/test/work-graph.test.mjs +37 -0
- package/protocol/README.md +12 -0
- package/protocol/capabilities/cloudflare-cpu-audit-input.schema.json +30 -6
- package/protocol/capabilities/cloudflare-cpu-profile-input.schema.json +18 -4
- package/protocol/capabilities/cloudflare-wrangler-native-input.schema.json +59 -10
- package/protocol/capabilities/knowledge-search-input.schema.json +35 -0
- package/protocol/capabilities/manifest.json +163 -1
- package/protocol/capabilities/repository-audit-input.schema.json +39 -6
- package/protocol/capabilities/repository-snapshot-input.schema.json +15 -3
- package/protocol/capabilities/terminal-exec-input.schema.json +55 -0
- package/protocol/commerce/catalog.v1.json +50 -0
- package/protocol/errors/error-catalog.json +164 -0
- package/protocol/errors/error-envelope.schema.json +544 -0
- package/protocol/features/README.md +57 -0
- package/protocol/features/agentsam.feature.v1.schema.json +290 -0
- package/protocol/features/catalog.json +65 -0
- package/protocol/features/examples/provider-resend.feature.json +17 -0
- package/protocol/go/agentsam-go-runtime.v1.json +17 -0
- package/protocol/knowledge/LIFECYCLE.md +140 -0
- package/protocol/knowledge/README.md +4 -0
- package/protocol/presets/catalog.json +128 -19
- package/protocol/rpc/v1/errors.proto +24 -0
- package/protocol/theme-refinery/d1-reconciliation.md +48 -0
- package/protocol/theme-refinery/product-metadata.schema.json +27 -0
- package/protocol/theme-refinery/receipts/products-registry-batch-20260924.json +318 -0
- package/protocol/theme-refinery/receipts/theme-harvest-20260924.json +472 -0
- package/protocol/theme-refinery/reconciliation-receipt.schema.json +83 -0
- package/services/cad/server.py +249 -2
- package/src/agent/capability-adapter.js +15 -5
- package/src/agent/index.js +2 -1
- package/src/agent/model-turn.js +51 -0
- package/src/agent/responses-runner.js +304 -38
- package/src/capabilities/index.js +1 -0
- package/src/capabilities/terminal-exec.js +78 -0
- package/src/cli.js +129 -31
- package/src/cloudflare/index.js +6 -0
- package/src/cloudflare/runtime-status.js +393 -0
- package/src/cloudflare/wrangler.js +17 -1
- package/src/commands/account-auth.js +1 -1
- package/src/commands/app.js +106 -0
- package/src/commands/autorag.js +77 -0
- package/src/commands/brand.js +293 -0
- package/src/commands/cad.js +1 -0
- package/src/commands/connections.js +126 -29
- package/src/commands/context-economics.js +8 -0
- package/src/commands/db.js +7 -0
- package/src/commands/deploy.js +2 -2
- package/src/commands/env.js +5 -4
- package/src/commands/eval.js +209 -14
- package/src/commands/go.js +365 -0
- package/src/commands/goap.js +176 -0
- package/src/commands/identity-init.js +27 -3
- package/src/commands/identity-protocol.js +195 -0
- package/src/commands/knowledge.js +64 -5
- package/src/commands/mcp.js +341 -0
- package/src/commands/merkle-persist.js +3 -1
- package/src/commands/merkle.js +18 -3
- package/src/commands/models.js +109 -23
- package/src/commands/plugins.js +175 -0
- package/src/commands/preferences.js +28 -8
- package/src/commands/product.js +53 -10
- package/src/commands/providers.js +389 -0
- package/src/commands/resume.js +9 -5
- package/src/commands/runtime-status.js +154 -0
- package/src/commands/shell.js +469 -54
- package/src/commands/status.js +82 -7
- package/src/commands/tunnel.js +228 -195
- package/src/commands/whoami.js +115 -22
- package/src/context/budget.js +6 -0
- package/src/context/index.js +2 -1
- package/src/context/project-card.js +75 -0
- package/src/errors/contract.js +34 -211
- package/src/errors/diagnostic.js +95 -50
- package/src/errors/index.js +6 -13
- package/src/eval/index.js +6 -0
- package/src/eval/live.js +439 -0
- package/src/features/resolve.js +242 -0
- package/src/go/build.js +108 -0
- package/src/go/cloudflare.js +207 -0
- package/src/go/contract.js +139 -0
- package/src/go/discover.js +96 -0
- package/src/go/index.js +13 -0
- package/src/go/receipts.js +77 -0
- package/src/go/registry.js +223 -0
- package/src/go/verify.js +31 -0
- package/src/index.js +100 -1
- package/src/knowledge/config.js +13 -5
- package/src/knowledge/engine.js +23 -8
- package/src/knowledge/index.js +1 -0
- package/src/knowledge/lane-registry.js +46 -0
- package/src/knowledge/providers/gemini.js +48 -8
- package/src/knowledge/service/client.js +13 -1
- package/src/knowledge/service/grpc-codec.js +156 -53
- package/src/knowledge/service/job-engine.js +133 -11
- package/src/knowledge/service/job-worker.js +34 -5
- package/src/knowledge/service/server.js +10 -1
- package/src/knowledge/store-discovery.js +77 -0
- package/src/lib/account-session.js +100 -25
- package/src/lib/agent-instructions.js +3 -0
- package/src/lib/auth.js +318 -51
- package/src/lib/cad/blender.js +42 -3
- package/src/lib/cad/d1-project-store.js +43 -0
- package/src/lib/cad/discovery.js +616 -0
- package/src/lib/cad/docker-executor.js +352 -0
- package/src/lib/cad/freecad.js +253 -0
- package/src/lib/cad/index.js +40 -0
- package/src/lib/cad/openscad.js +198 -0
- package/src/lib/cad/project-cli.d.ts +2 -0
- package/src/lib/cad/project-cli.js +21 -0
- package/src/lib/cad/project-contract.d.ts +3 -0
- package/src/lib/cad/project-contract.js +1 -0
- package/src/lib/cad/project-recipe.js +30 -0
- package/src/lib/cad/project-runtime.d.ts +2 -0
- package/src/lib/cad/project-runtime.js +53 -0
- package/src/lib/cad/project-store.js +25 -0
- package/src/lib/cad/project-workflows.js +31 -0
- package/src/lib/cad-docker.js +21 -2
- package/src/lib/cli-preferences.js +17 -2
- package/src/lib/core-client.js +97 -33
- package/src/lib/deploy/local-studio.js +6 -5
- package/src/lib/detect-context.js +14 -16
- package/src/lib/dockerize.js +3 -0
- package/src/lib/execution-approvals.js +1 -0
- package/src/lib/identity-scaffold.js +4 -1
- package/src/lib/knowledge-docker.js +9 -1
- package/src/lib/local-sessions.js +124 -34
- package/src/lib/local-status.js +35 -14
- package/src/lib/project-config.js +9 -0
- package/src/lib/provider-credentials.js +233 -55
- package/src/lib/scaffold/resolve-cloudflare-account.js +37 -0
- package/src/lib/scaffold/wizards/cms.js +2 -8
- package/src/lib/scaffold/wizards/worker-api.js +2 -8
- package/src/lib/slash-commands.js +10 -2
- package/src/local/migrations.js +109 -1
- package/src/local/runtime-store.js +31 -5
- package/src/local/sqlite.js +36 -1
- package/src/mcp/authority.js +348 -0
- package/src/mcp/client-adapters.js +431 -0
- package/src/mcp/client.js +172 -0
- package/src/mcp/index.js +47 -0
- package/src/mcp/telemetry.js +103 -0
- package/src/models/catalog.js +329 -51
- package/src/models/discovery.js +59 -4
- package/src/models/index.js +2 -0
- package/src/models/inventory-core.js +182 -0
- package/src/models/policy.js +20 -0
- package/src/plugins/cloudflare.js +103 -0
- package/src/plugins/completeful.js +69 -0
- package/src/plugins/contracts.js +86 -0
- package/src/plugins/index.js +11 -0
- package/src/plugins/registry.js +207 -0
- package/src/plugins/resource-scope.js +45 -0
- package/src/plugins/runtime.js +118 -0
- package/src/plugins/vectorize.js +31 -0
- package/src/progression/engine.js +171 -0
- package/src/progression/index.js +1 -0
- package/src/providers/cloudflare-chat.js +1 -1
- package/src/providers/gemini-generate-content.js +2 -1
- package/src/providers/openai-responses.js +45 -16
- package/src/providers/tool-schema.js +85 -0
- package/src/repository/index.js +29 -0
- package/src/rpc/generated/errors_pb.js +961 -1
- package/src/security/local-vault.js +415 -0
- package/src/security/process.js +20 -4
- package/src/status/actions.js +192 -0
- package/src/tools/hydrate.js +5 -1
- package/src/tools/index.js +7 -0
- package/src/tools/redact.js +64 -0
- package/src/tools/registry.js +83 -0
- package/src/tools/runtime.js +257 -0
- package/src/tools/search.js +21 -8
- package/src/ui/ansi.js +117 -3
- package/src/ui/cli/activity.js +76 -7
- package/src/ui/cli/footer.js +110 -9
- package/src/ui/cli/help.js +14 -5
- package/src/ui/wireframes.js +166 -0
- package/test/account-session.test.mjs +76 -11
- package/test/apps-scaffold-contract.test.mjs +58 -0
- package/test/capabilities.test.mjs +1 -1
- package/test/cli/eval-live.test.mjs +219 -0
- package/test/cli/go.test.mjs +71 -0
- package/test/cli/local-vault-and-provider-setup.test.mjs +268 -0
- package/test/cli/mcp-client.test.mjs +245 -0
- package/test/cli/runtime-ui.test.mjs +69 -2
- package/test/cli/status-actions.test.mjs +88 -0
- package/test/cli/wireframes-go-registry.test.mjs +54 -0
- package/test/cloudflare-connector.test.mjs +3 -6
- package/test/cloudflare-runtime.test.mjs +8 -1
- package/test/context.test.mjs +15 -0
- package/test/error-diagnostics.test.mjs +9 -0
- package/test/fixtures/cad/courtyard-house.json +208 -0
- package/test/go/cloudflare-probe.test.mjs +53 -0
- package/test/integration/app-command.test.mjs +55 -0
- package/test/integration/cad-discovery.test.mjs +158 -0
- package/test/integration/cad-docker-executor.test.mjs +249 -0
- package/test/integration/cad-execution.test.mjs +184 -0
- package/test/integration/cad-project-app.test.mjs +31 -0
- package/test/integration/cad-project-d1.test.mjs +25 -0
- package/test/integration/cad-project-native.test.mjs +24 -0
- package/test/integration/cad-project-workflow.test.mjs +9 -0
- package/test/integration/cad-project.test.mjs +82 -0
- package/test/integration/cli-help.test.mjs +4 -0
- package/test/integration/cms-site-tenancy-contract.test.mjs +256 -0
- package/test/integration/core-client.integration.test.mjs +55 -0
- package/test/integration/error-runtime-rpc.test.mjs +71 -0
- package/test/integration/features-resolve.test.mjs +128 -0
- package/test/integration/install-script.test.mjs +107 -0
- package/test/integration/inventory-core.test.mjs +53 -0
- package/test/integration/plugins-cloudflare.integration.test.mjs +28 -0
- package/test/integration/provider-env-cli.test.mjs +1 -1
- package/test/integration/runtime-migrations.test.mjs +6 -1
- package/test/integration/runtime-status.integration.test.mjs +211 -0
- package/test/integration/scaffold-cloudflare.test.mjs +46 -0
- package/test/integration/storage-architecture.test.mjs +154 -0
- package/test/integration/store-discovery.test.mjs +44 -0
- package/test/integration/terminal-exec.integration.test.mjs +86 -0
- package/test/integration/tool-runtime.test.mjs +124 -0
- package/test/integration/tool-schema.test.mjs +59 -0
- package/test/knowledge-service.test.mjs +4 -0
- package/test/local-sessions.test.mjs +11 -2
- package/test/local-studio-deploy.test.mjs +1 -1
- package/test/model-catalog.test.mjs +28 -1
- package/test/models.test.mjs +159 -5
- package/test/openai-responses.test.mjs +60 -0
- package/test/provider-credentials.test.mjs +15 -5
- package/test/responses-runner.test.mjs +321 -6
- package/test/sdk-worker-contract.test.mjs +5 -1
- package/test/shell.test.mjs +149 -4
- package/test/smoke.mjs +4 -3
- package/test/tools-search.test.mjs +33 -0
- package/test/unit/website-assets-bindings.test.mjs +60 -0
- package/test/whoami-resume.test.mjs +87 -7
- package/examples/gorilla-shell/README.md +0 -15
- package/src/lib/gorilla-template.js +0 -54
- package/src/lib/prompt-byok.js +0 -57
- package/src/lib/save-sdk-token.js +0 -19
- package/templates/gorilla-shell/App.tsx +0 -639
- package/templates/gorilla-shell/README.md +0 -34
- package/templates/gorilla-shell/index.html +0 -15
- package/templates/gorilla-shell/main.jsx +0 -9
- package/templates/gorilla-shell/package.json +0 -19
- package/templates/gorilla-shell/vite.config.js +0 -21
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
createAgentRunId,
|
|
6
|
+
createTicketId,
|
|
7
|
+
generateTicketCreateSql,
|
|
8
|
+
generateTicketActivationSql,
|
|
9
|
+
generateTicketCloseSql,
|
|
10
|
+
} from '../src/tickets.js';
|
|
11
|
+
import { generateWorkspaceStateUpsertSql } from '../src/workspace-state.js';
|
|
12
|
+
import {
|
|
13
|
+
renderGoapStatus,
|
|
14
|
+
renderGoapGoal,
|
|
15
|
+
renderGoapWhy,
|
|
16
|
+
renderGoapPlan,
|
|
17
|
+
} from '../src/goap.js';
|
|
18
|
+
|
|
19
|
+
test('createAgentRunId / createTicketId produce prefixed, collision-resistant ids', () => {
|
|
20
|
+
const run1 = createAgentRunId();
|
|
21
|
+
const run2 = createAgentRunId();
|
|
22
|
+
const tkt1 = createTicketId();
|
|
23
|
+
assert.match(run1, /^arun_[0-9a-f]{16}$/);
|
|
24
|
+
assert.match(tkt1, /^tkt_[0-9a-f]{16}$/);
|
|
25
|
+
assert.notEqual(run1, run2);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('generateTicketCreateSql requires account_id and title', () => {
|
|
29
|
+
assert.throws(() => generateTicketCreateSql({ title: 'x' }), /account_id_required/);
|
|
30
|
+
assert.throws(() => generateTicketCreateSql({ accountId: 'acc_1' }), /title_required/);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('generateTicketCreateSql with status=active mints an agent_run and links it on the ticket insert', () => {
|
|
34
|
+
const { sql, ticketId, agentRunId } = generateTicketCreateSql({
|
|
35
|
+
accountId: 'acc_1',
|
|
36
|
+
title: 'Wire GOAP planner',
|
|
37
|
+
status: 'active',
|
|
38
|
+
now: 1000,
|
|
39
|
+
});
|
|
40
|
+
assert.ok(ticketId.startsWith('tkt_'));
|
|
41
|
+
assert.ok(agentRunId && agentRunId.startsWith('arun_'));
|
|
42
|
+
assert.match(sql, /INSERT INTO agentsam_agent_run/);
|
|
43
|
+
assert.match(sql, /INSERT INTO agentsam_tickets/);
|
|
44
|
+
assert.match(sql, /INSERT INTO agentsam_ticket_events/);
|
|
45
|
+
const runOccurrences = sql.split(agentRunId).length - 1;
|
|
46
|
+
assert.ok(runOccurrences >= 2, 'agent_run id should appear in both the run insert and the ticket insert');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('generateTicketCreateSql with status=backlog does not mint an agent_run', () => {
|
|
50
|
+
const { sql, agentRunId } = generateTicketCreateSql({
|
|
51
|
+
accountId: 'acc_1',
|
|
52
|
+
title: 'Later work',
|
|
53
|
+
status: 'backlog',
|
|
54
|
+
});
|
|
55
|
+
assert.equal(agentRunId, null);
|
|
56
|
+
assert.doesNotMatch(sql, /INSERT INTO agentsam_agent_run/);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('generateTicketCreateSql escapes single quotes and truncates the title before escaping (past 240 chars)', () => {
|
|
60
|
+
const longTitle = 'x'.repeat(300) + "'drop";
|
|
61
|
+
const { sql } = generateTicketCreateSql({
|
|
62
|
+
accountId: 'acc_1',
|
|
63
|
+
title: longTitle,
|
|
64
|
+
status: 'backlog',
|
|
65
|
+
});
|
|
66
|
+
// title is sliced to 240 chars BEFORE sql-escaping, so the trailing quote at position 300 never reaches the output
|
|
67
|
+
assert.doesNotMatch(sql, /drop/);
|
|
68
|
+
assert.doesNotMatch(sql, new RegExp('x'.repeat(241)));
|
|
69
|
+
assert.match(sql, new RegExp('x'.repeat(240)));
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('generateTicketCreateSql escapes a single quote embedded inside the title itself', () => {
|
|
73
|
+
const { sql } = generateTicketCreateSql({
|
|
74
|
+
accountId: 'acc_1',
|
|
75
|
+
title: "Sam's ticket",
|
|
76
|
+
status: 'backlog',
|
|
77
|
+
});
|
|
78
|
+
assert.match(sql, /Sam''s ticket/);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('generateTicketActivationSql requires account and ticket id', () => {
|
|
82
|
+
assert.throws(() => generateTicketActivationSql({ ticketId: 't' }), /account_id_required/);
|
|
83
|
+
assert.throws(() => generateTicketActivationSql({ accountId: 'a' }), /ticket_id_required/);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('generateTicketActivationSql wires a fresh agent_run and clears closed_at', () => {
|
|
87
|
+
const { sql, agentRunId } = generateTicketActivationSql({
|
|
88
|
+
accountId: 'acc_1',
|
|
89
|
+
ticketId: 'tkt_abc',
|
|
90
|
+
now: 1000,
|
|
91
|
+
});
|
|
92
|
+
assert.ok(agentRunId.startsWith('arun_'));
|
|
93
|
+
assert.match(sql, /status = 'active'/);
|
|
94
|
+
assert.match(sql, /closed_at = NULL/);
|
|
95
|
+
assert.match(sql, /COALESCE\(agent_run_id,/);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test('generateTicketCloseSql maps shipped -> completed and abandoned/blocked -> failed run status', () => {
|
|
99
|
+
const shipped = generateTicketCloseSql({ ticketId: 'tkt_1', status: 'shipped', now: 1000 });
|
|
100
|
+
assert.match(shipped.sql, /status = 'completed'/);
|
|
101
|
+
assert.match(shipped.sql, /closed_at = 1000/);
|
|
102
|
+
|
|
103
|
+
const abandoned = generateTicketCloseSql({ ticketId: 'tkt_1', status: 'abandoned', now: 1000 });
|
|
104
|
+
assert.match(abandoned.sql, /status = 'failed'/);
|
|
105
|
+
|
|
106
|
+
const blocked = generateTicketCloseSql({ ticketId: 'tkt_1', status: 'blocked', now: 1000 });
|
|
107
|
+
assert.match(blocked.sql, /status = 'failed'/);
|
|
108
|
+
assert.match(blocked.sql, /closed_at = closed_at/);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test('generateTicketCloseSql requires a ticket id', () => {
|
|
112
|
+
assert.throws(() => generateTicketCloseSql({}), /ticket_id_required/);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('generateWorkspaceStateUpsertSql requires repository_id and derives a default workspace id (non-alnum chars become underscores)', () => {
|
|
116
|
+
assert.throws(() => generateWorkspaceStateUpsertSql({}), /repository_id_required/);
|
|
117
|
+
const sql = generateWorkspaceStateUpsertSql({ repositoryId: 'SamPrimeaux/agentsam-sdk' });
|
|
118
|
+
assert.match(sql, /INSERT INTO agentsam_workspace_state/);
|
|
119
|
+
assert.match(sql, /ON CONFLICT\(repository_id\) DO UPDATE SET/);
|
|
120
|
+
assert.match(sql, /ws_SamPrimeaux_agentsam_sdk/);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test('generateWorkspaceStateUpsertSql upsert preserves existing values via COALESCE when a field is omitted', () => {
|
|
124
|
+
const sql = generateWorkspaceStateUpsertSql({ repositoryId: 'repo_1', currentTaskId: 'tkt_9' });
|
|
125
|
+
assert.match(sql, /current_task_id = COALESCE\(excluded\.current_task_id, agentsam_workspace_state\.current_task_id\)/);
|
|
126
|
+
assert.match(sql, /'tkt_9'/);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('renderGoapStatus reflects ticket/workspace/run state and falls back gracefully on empty state', () => {
|
|
130
|
+
const out = renderGoapStatus({
|
|
131
|
+
repositoryId: 'SamPrimeaux/agentsam-sdk',
|
|
132
|
+
workspaceState: { locked_by: 'agentsam_cli', current_task_id: 'tkt_1' },
|
|
133
|
+
activeTicket: { id: 'tkt_1', title: 'Ship GOAP', status: 'active', priority: 'P1' },
|
|
134
|
+
agentRun: { id: 'arun_1', status: 'running' },
|
|
135
|
+
git: { branch: 'main', headSha: 'abcdef1234567890', dirty: false },
|
|
136
|
+
});
|
|
137
|
+
assert.match(out, /GOAP BLACKBOARD STATUS/);
|
|
138
|
+
assert.match(out, /Ship GOAP/);
|
|
139
|
+
assert.match(out, /CLEAN/);
|
|
140
|
+
|
|
141
|
+
const empty = renderGoapStatus();
|
|
142
|
+
assert.match(empty, /no active ticket/);
|
|
143
|
+
assert.match(empty, /unlocked/);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test('renderGoapGoal / renderGoapWhy / renderGoapPlan render without throwing on minimal state', () => {
|
|
147
|
+
for (const fn of [renderGoapGoal, renderGoapWhy, renderGoapPlan]) {
|
|
148
|
+
const out = fn({ repositoryId: 'repo', activeTicket: {}, workspaceState: {}, agentRun: {}, git: {} });
|
|
149
|
+
assert.equal(typeof out, 'string');
|
|
150
|
+
assert.ok(out.length > 0);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
@@ -7,7 +7,6 @@ export const CLOUDFLARE_OAUTH_AUTHORIZE_URL = 'https://dash.cloudflare.com/oauth
|
|
|
7
7
|
export const CLOUDFLARE_OAUTH_TOKEN_URL = 'https://dash.cloudflare.com/oauth2/token';
|
|
8
8
|
export const CLOUDFLARE_CALLBACK_PATH = '/api/connections/cloudflare/callback';
|
|
9
9
|
export const CLOUDFLARE_FIXTURE_CLIENT_ID = 'sillynotreal';
|
|
10
|
-
export const CLOUDFLARE_FIXTURE_CLIENT_SECRET = 'sillynotreal-secret';
|
|
11
10
|
|
|
12
11
|
export const CLOUDFLARE_OAUTH_REVOKE_URL = 'https://dash.cloudflare.com/oauth2/revoke';
|
|
13
12
|
|
|
@@ -22,7 +21,7 @@ export const CLOUDFLARE_CAPABILITY_SCOPES = Object.freeze({
|
|
|
22
21
|
why: 'Inspect D1 databases bound to the deployable.',
|
|
23
22
|
},
|
|
24
23
|
r2_inspect: {
|
|
25
|
-
scopes: ['workers-r2
|
|
24
|
+
scopes: ['workers-r2.read'],
|
|
26
25
|
why: 'Inspect R2 buckets bound to the deployable.',
|
|
27
26
|
},
|
|
28
27
|
worker_logs: {
|
|
@@ -31,12 +30,200 @@ export const CLOUDFLARE_CAPABILITY_SCOPES = Object.freeze({
|
|
|
31
30
|
},
|
|
32
31
|
});
|
|
33
32
|
|
|
33
|
+
// Full scope catalog for the AgentSam Local Studio OAuth client (182 total,
|
|
34
|
+
// pasted directly from the Cloudflare dashboard's own scope picker). This is
|
|
35
|
+
// what gets requested at mint time -- one authorize covers everything the
|
|
36
|
+
// client is provisioned for, rather than a hand-curated subset that has to
|
|
37
|
+
// be edited in code every time a new capability is used. CLOUDFLARE_CAPABILITY_SCOPES
|
|
38
|
+
// above stays as documentation of which specific scopes each feature
|
|
39
|
+
// actually touches -- it no longer restricts what's requested.
|
|
40
|
+
export const CLOUDFLARE_ALL_SCOPES = Object.freeze([
|
|
41
|
+
'agent-memory.write',
|
|
42
|
+
'browser-rendering.read',
|
|
43
|
+
'browser-rendering.write',
|
|
44
|
+
'cf-agents.read',
|
|
45
|
+
'cf-agents.write',
|
|
46
|
+
'cloud-connector.read',
|
|
47
|
+
'cloud-connector.write',
|
|
48
|
+
'cloudchamber.read',
|
|
49
|
+
'cloudchamber.write',
|
|
50
|
+
'constellation.read',
|
|
51
|
+
'constellation.write',
|
|
52
|
+
'd1.read',
|
|
53
|
+
'd1.write',
|
|
54
|
+
'flagship.evaluate',
|
|
55
|
+
'flagship.read',
|
|
56
|
+
'flagship.write',
|
|
57
|
+
'query-cache.read',
|
|
58
|
+
'query-cache.write',
|
|
59
|
+
'k2.read',
|
|
60
|
+
'k2.write',
|
|
61
|
+
'k2.consume',
|
|
62
|
+
'k2.produce',
|
|
63
|
+
'mcp-portals.read',
|
|
64
|
+
'mcp-portals.write',
|
|
65
|
+
'messaging.edit',
|
|
66
|
+
'messaging.read',
|
|
67
|
+
'cfspeed.read',
|
|
68
|
+
'cfspeed.write',
|
|
69
|
+
'page.read',
|
|
70
|
+
'page.write',
|
|
71
|
+
'pipelines.read',
|
|
72
|
+
'pipelines.send',
|
|
73
|
+
'pipelines.write',
|
|
74
|
+
'pubsub.read',
|
|
75
|
+
'pubsub.write',
|
|
76
|
+
'queues.read',
|
|
77
|
+
'queues.write',
|
|
78
|
+
'realtime.write',
|
|
79
|
+
'realtime.admin',
|
|
80
|
+
'realtime.read',
|
|
81
|
+
'secrets-store.read',
|
|
82
|
+
'secrets-store.write',
|
|
83
|
+
'vectorize.read',
|
|
84
|
+
'vectorize.write',
|
|
85
|
+
'workers-ci.read',
|
|
86
|
+
'workers-ci.write',
|
|
87
|
+
'containers.read',
|
|
88
|
+
'containers.write',
|
|
89
|
+
'workers-kv-storage.read',
|
|
90
|
+
'workers-kv-storage.write',
|
|
91
|
+
'workers-observability.read',
|
|
92
|
+
'workers-observability-telemetry.write',
|
|
93
|
+
'workers-observability.write',
|
|
94
|
+
'r2-catalog.read',
|
|
95
|
+
'r2-catalog.write',
|
|
96
|
+
'r2-catalog-sql.read',
|
|
97
|
+
'workers-r2-bucket-item.read',
|
|
98
|
+
'workers-r2-bucket-item.write',
|
|
99
|
+
'workers-r2.read',
|
|
100
|
+
'workers-r2.write',
|
|
101
|
+
'workers-routes.read',
|
|
102
|
+
'workers-routes.write',
|
|
103
|
+
'workers-scripts.read',
|
|
104
|
+
'workers-scripts.write',
|
|
105
|
+
'workers-tail.read',
|
|
106
|
+
'aiaudit.read',
|
|
107
|
+
'aiaudit.write',
|
|
108
|
+
'aig.read',
|
|
109
|
+
'aig.run',
|
|
110
|
+
'aig.write',
|
|
111
|
+
'ai-search.index',
|
|
112
|
+
'ai-search.read',
|
|
113
|
+
'ai-search.run',
|
|
114
|
+
'ai-search.write',
|
|
115
|
+
'agw.read',
|
|
116
|
+
'agw.run',
|
|
117
|
+
'agw.write',
|
|
118
|
+
'rag.read',
|
|
119
|
+
'rag.write',
|
|
120
|
+
'rag.run',
|
|
121
|
+
'firewall-for-ai.read',
|
|
122
|
+
'firewall-for-ai.write',
|
|
123
|
+
'websearch.read',
|
|
124
|
+
'websearch.run',
|
|
125
|
+
'websearch.write',
|
|
126
|
+
'ai-model.read',
|
|
127
|
+
'ai-model.write',
|
|
128
|
+
'ai.read',
|
|
129
|
+
'ai.write',
|
|
130
|
+
'account-dns-settings.read',
|
|
131
|
+
'account-dns-settings.write',
|
|
132
|
+
'dns-firewall.read',
|
|
133
|
+
'dns-firewall.write',
|
|
134
|
+
'dns.read',
|
|
135
|
+
'dns-view.read',
|
|
136
|
+
'dns-view.write',
|
|
137
|
+
'dns.write',
|
|
138
|
+
'registrar-domains.admin',
|
|
139
|
+
'registrar-domains.read',
|
|
140
|
+
'registrar-sandbox-domains.admin',
|
|
141
|
+
'registrar-sandbox-domains.read',
|
|
142
|
+
'zone-custom-asset.read',
|
|
143
|
+
'zone-custom-asset.write',
|
|
144
|
+
'zone-dns-settings.read',
|
|
145
|
+
'zone-dns-settings.write',
|
|
146
|
+
'zone.read',
|
|
147
|
+
'zone-settings.read',
|
|
148
|
+
'zone-settings.write',
|
|
149
|
+
'zone-versioning.read',
|
|
150
|
+
'zone-versioning.write',
|
|
151
|
+
'zone.write',
|
|
152
|
+
'fraud-detection-pii.read',
|
|
153
|
+
'account-firewall-access-rules.read',
|
|
154
|
+
'account-firewall-access-rules.write',
|
|
155
|
+
'account-security-center-insights.read',
|
|
156
|
+
'account-security-center-insights.write',
|
|
157
|
+
'account-waf.read',
|
|
158
|
+
'account-waf.write',
|
|
159
|
+
'request-tracer.read',
|
|
160
|
+
'reports-application-security-report.read',
|
|
161
|
+
'bot-management-feedback.read',
|
|
162
|
+
'bot-management-feedback.write',
|
|
163
|
+
'bot-management.read',
|
|
164
|
+
'bot-management.write',
|
|
165
|
+
'http-applications.read',
|
|
166
|
+
'http-applications.write',
|
|
167
|
+
'http-ddos-managed-ruleset.read',
|
|
168
|
+
'http-ddos-managed-ruleset.write',
|
|
169
|
+
'tag.read',
|
|
170
|
+
'tag.write',
|
|
171
|
+
'url-scanner.read',
|
|
172
|
+
'url-scanner.write',
|
|
173
|
+
'zone-security-center-insights.read',
|
|
174
|
+
'zone-security-center-insights.write',
|
|
175
|
+
'zone-waf.read',
|
|
176
|
+
'zone-waf.write',
|
|
177
|
+
'account-custom-error-rules.read',
|
|
178
|
+
'account-custom-error-rules.write',
|
|
179
|
+
'account-custom-pages.read',
|
|
180
|
+
'account-custom-pages.write',
|
|
181
|
+
'account-rule-lists.read',
|
|
182
|
+
'account-rule-lists.write',
|
|
183
|
+
'account-rulesets.read',
|
|
184
|
+
'account-rulesets.write',
|
|
185
|
+
'config-settings.read',
|
|
186
|
+
'config-settings.write',
|
|
187
|
+
'custom-errors.read',
|
|
188
|
+
'custom-errors.write',
|
|
189
|
+
'custom-pages.read',
|
|
190
|
+
'custom-pages.write',
|
|
191
|
+
'dynamic-redirect.read',
|
|
192
|
+
'dynamic-redirect.write',
|
|
193
|
+
'managed-headers.read',
|
|
194
|
+
'managed-headers.write',
|
|
195
|
+
'mass-url-redirects.read',
|
|
196
|
+
'mass-url-redirects.write',
|
|
197
|
+
'origin.read',
|
|
198
|
+
'origin.write',
|
|
199
|
+
'payments-gateway.read',
|
|
200
|
+
'payments-gateway.write',
|
|
201
|
+
'account-ssl-and-certificates.read',
|
|
202
|
+
'account-ssl-and-certificates.write',
|
|
203
|
+
'cache.purge',
|
|
204
|
+
'cache-settings.read',
|
|
205
|
+
'cache-settings.write',
|
|
206
|
+
'ssl-and-certificates.read',
|
|
207
|
+
'ssl-and-certificates.write',
|
|
208
|
+
'account-api-gateway.write',
|
|
209
|
+
'account-api-gateway.read',
|
|
210
|
+
'account-custom-asset.read',
|
|
211
|
+
'account-custom-asset.write',
|
|
212
|
+
'account-settings.read',
|
|
213
|
+
'account-settings.write',
|
|
214
|
+
'apps.write',
|
|
215
|
+
'integration.write',
|
|
216
|
+
'memberships.read',
|
|
217
|
+
'memberships.write',
|
|
218
|
+
'notifications.read',
|
|
219
|
+
'notifications.write',
|
|
220
|
+
'scim-provisioning.write',
|
|
221
|
+
'user-details.read',
|
|
222
|
+
'offline_access'
|
|
223
|
+
]);
|
|
224
|
+
|
|
34
225
|
export function requestedCloudflareScopes() {
|
|
35
|
-
|
|
36
|
-
for (const cap of Object.values(CLOUDFLARE_CAPABILITY_SCOPES)) {
|
|
37
|
-
for (const scope of cap.scopes) set.add(scope);
|
|
38
|
-
}
|
|
39
|
-
return [...set];
|
|
226
|
+
return [...CLOUDFLARE_ALL_SCOPES];
|
|
40
227
|
}
|
|
41
228
|
|
|
42
229
|
function clean(value) {
|
|
@@ -45,14 +232,17 @@ function clean(value) {
|
|
|
45
232
|
|
|
46
233
|
export function isFixtureCloudflareCredential(value) {
|
|
47
234
|
const v = clean(value);
|
|
48
|
-
return v === CLOUDFLARE_FIXTURE_CLIENT_ID
|
|
235
|
+
return v === CLOUDFLARE_FIXTURE_CLIENT_ID;
|
|
49
236
|
}
|
|
50
237
|
|
|
51
238
|
export function resolveCloudflareOAuthClient(env = {}) {
|
|
52
239
|
const clientId = clean(env.CLOUDFLARE_OAUTH_CLIENT_ID);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
240
|
+
// AgentSam Local Studio uses Cloudflare's public PKCE client. It must never
|
|
241
|
+
// read a client secret: stale Worker secrets would turn an otherwise valid
|
|
242
|
+
// PKCE exchange into an invalid mixed-auth request. Confidential Cloudflare
|
|
243
|
+
// clients belong to their owning host adapter, not this connector.
|
|
244
|
+
const present = Boolean(clientId);
|
|
245
|
+
const fixture = isFixtureCloudflareCredential(clientId);
|
|
56
246
|
if (!present) {
|
|
57
247
|
return {
|
|
58
248
|
configured: false,
|
|
@@ -60,7 +250,7 @@ export function resolveCloudflareOAuthClient(env = {}) {
|
|
|
60
250
|
fixture: false,
|
|
61
251
|
status: 'not_configured',
|
|
62
252
|
clientIdConfigured: Boolean(clientId),
|
|
63
|
-
|
|
253
|
+
tokenAuthMethod: 'none_pkce',
|
|
64
254
|
};
|
|
65
255
|
}
|
|
66
256
|
return {
|
|
@@ -69,20 +259,20 @@ export function resolveCloudflareOAuthClient(env = {}) {
|
|
|
69
259
|
fixture,
|
|
70
260
|
status: fixture ? 'fixture' : 'ready',
|
|
71
261
|
clientIdConfigured: true,
|
|
72
|
-
|
|
262
|
+
tokenAuthMethod: 'none_pkce',
|
|
73
263
|
};
|
|
74
264
|
}
|
|
75
265
|
|
|
76
266
|
export function cloudflareConnectionSafeStatus(env = {}, connection = null, ownerId = '') {
|
|
77
267
|
const client = resolveCloudflareOAuthClient(env);
|
|
78
|
-
const record = connection && connection.ownerId === ownerId ? connection : null;
|
|
268
|
+
const record = connection && connection.ownerId === ownerId && connection.status === 'connected' ? connection : null;
|
|
79
269
|
return {
|
|
80
270
|
provider: 'cloudflare',
|
|
81
271
|
status: record ? 'connected' : client.status === 'ready' ? 'ready' : client.status,
|
|
82
272
|
configured: client.configured && client.productionReady,
|
|
83
273
|
fixture: client.fixture,
|
|
84
274
|
clientId: client.clientIdConfigured ? 'configured' : 'missing',
|
|
85
|
-
|
|
275
|
+
token_auth_method: client.tokenAuthMethod,
|
|
86
276
|
callbackPath: CLOUDFLARE_CALLBACK_PATH,
|
|
87
277
|
connection: record
|
|
88
278
|
? {
|
|
@@ -113,6 +303,98 @@ export function assertConnectionOwner(connection, ownerId) {
|
|
|
113
303
|
return connection;
|
|
114
304
|
}
|
|
115
305
|
|
|
306
|
+
export async function loadCloudflareAccessToken(env, ownerId, options = {}) {
|
|
307
|
+
if (!env?.DB || !ownerId) return null;
|
|
308
|
+
const row = await env.DB.prepare(`
|
|
309
|
+
SELECT connection_id, owner_id, cloudflare_account_id, scopes, status,
|
|
310
|
+
access_token_encrypted, refresh_token_encrypted, expires_at
|
|
311
|
+
FROM agentsam_cloudflare_connections
|
|
312
|
+
WHERE owner_id = ? AND status = 'connected'
|
|
313
|
+
ORDER BY updated_at DESC LIMIT 1
|
|
314
|
+
`).bind(ownerId).first();
|
|
315
|
+
if (!row?.access_token_encrypted || row.owner_id !== ownerId) return null;
|
|
316
|
+
const { decryptSecret, sealToken } = await import('./vault.js');
|
|
317
|
+
const aad = `cloudflare-connection:${ownerId}`;
|
|
318
|
+
let accessToken = await decryptSecret(env, row.access_token_encrypted, aad);
|
|
319
|
+
let refreshToken = row.refresh_token_encrypted
|
|
320
|
+
? await decryptSecret(env, row.refresh_token_encrypted, aad)
|
|
321
|
+
: '';
|
|
322
|
+
let expiresAt = Number(row.expires_at || 0) || null;
|
|
323
|
+
let scopes = row.scopes ? String(row.scopes).split(' ').filter(Boolean) : [];
|
|
324
|
+
const now = Math.floor(Date.now() / 1000);
|
|
325
|
+
if (expiresAt && expiresAt <= now + 60) {
|
|
326
|
+
if (!refreshToken) throw new Error('cloudflare_refresh_token_missing');
|
|
327
|
+
const refreshParams = new URLSearchParams({
|
|
328
|
+
grant_type: 'refresh_token',
|
|
329
|
+
refresh_token: refreshToken,
|
|
330
|
+
client_id: String(env.CLOUDFLARE_OAUTH_CLIENT_ID || ''),
|
|
331
|
+
});
|
|
332
|
+
const refreshResponse = await (options.fetchImpl || fetch)(CLOUDFLARE_OAUTH_TOKEN_URL, {
|
|
333
|
+
method: 'POST',
|
|
334
|
+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
335
|
+
body: refreshParams,
|
|
336
|
+
});
|
|
337
|
+
if (!refreshResponse.ok) throw new Error(`cloudflare_token_refresh_failed:${refreshResponse.status}`);
|
|
338
|
+
const refreshed = await refreshResponse.json();
|
|
339
|
+
if (!refreshed?.access_token) throw new Error('cloudflare_token_refresh_missing_access_token');
|
|
340
|
+
accessToken = refreshed.access_token;
|
|
341
|
+
refreshToken = refreshed.refresh_token || refreshToken;
|
|
342
|
+
scopes = String(refreshed.scope || row.scopes || '').split(' ').filter(Boolean);
|
|
343
|
+
expiresAt = refreshed.expires_in ? now + Number(refreshed.expires_in) : null;
|
|
344
|
+
const [accessEncrypted, refreshEncrypted] = await Promise.all([
|
|
345
|
+
sealToken(env, accessToken, aad),
|
|
346
|
+
sealToken(env, refreshToken, aad),
|
|
347
|
+
]);
|
|
348
|
+
await env.DB.prepare(`
|
|
349
|
+
UPDATE agentsam_cloudflare_connections
|
|
350
|
+
SET access_token_encrypted = ?, refresh_token_encrypted = ?, scopes = ?,
|
|
351
|
+
expires_at = ?, status = 'connected', updated_at = unixepoch()
|
|
352
|
+
WHERE connection_id = ? AND owner_id = ?
|
|
353
|
+
`).bind(accessEncrypted, refreshEncrypted, scopes.join(' '), expiresAt, row.connection_id, ownerId).run();
|
|
354
|
+
}
|
|
355
|
+
return {
|
|
356
|
+
accessToken,
|
|
357
|
+
connectionId: row.connection_id,
|
|
358
|
+
accountId: row.cloudflare_account_id || null,
|
|
359
|
+
scopes,
|
|
360
|
+
expiresAt,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export async function probeCloudflareConnection(env, ownerId, options = {}) {
|
|
365
|
+
const startedAt = Date.now();
|
|
366
|
+
const checkedAt = Math.floor(startedAt / 1000);
|
|
367
|
+
try {
|
|
368
|
+
const connection = await loadCloudflareAccessToken(env, ownerId, options);
|
|
369
|
+
if (!connection) return { status: 'auth_error', healthy: false, checked_at: checkedAt, error_code: 'cloudflare_connection_missing' };
|
|
370
|
+
const response = await (options.fetchImpl || fetch)('https://dash.cloudflare.com/oauth2/userinfo', {
|
|
371
|
+
headers: { authorization: `Bearer ${connection.accessToken}`, accept: 'application/json' },
|
|
372
|
+
signal: typeof AbortSignal?.timeout === 'function' ? AbortSignal.timeout(5000) : undefined,
|
|
373
|
+
});
|
|
374
|
+
const body = await response.json().catch(() => null);
|
|
375
|
+
const healthy = response.ok && body?.error == null;
|
|
376
|
+
return {
|
|
377
|
+
status: healthy ? 'healthy' : response.status === 401 || response.status === 403 ? 'auth_error' : 'unhealthy',
|
|
378
|
+
healthy,
|
|
379
|
+
checked_at: checkedAt,
|
|
380
|
+
latency_ms: Date.now() - startedAt,
|
|
381
|
+
http_status: response.status,
|
|
382
|
+
provider_request_id: response.headers.get('cf-ray') || null,
|
|
383
|
+
account_id: connection.accountId,
|
|
384
|
+
scopes: connection.scopes,
|
|
385
|
+
error_code: healthy
|
|
386
|
+
? null
|
|
387
|
+
: body?.error || (body?.errors?.[0]?.code ? String(body.errors[0].code) : `cloudflare_http_${response.status}`),
|
|
388
|
+
error_message: healthy ? null : body?.error_description || body?.errors?.[0]?.message || 'Cloudflare OAuth probe failed',
|
|
389
|
+
};
|
|
390
|
+
} catch (error) {
|
|
391
|
+
return {
|
|
392
|
+
status: 'unreachable', healthy: false, checked_at: checkedAt, latency_ms: Date.now() - startedAt,
|
|
393
|
+
error_code: 'cloudflare_probe_failed', error_message: String(error?.message || error).slice(0, 240),
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
116
398
|
export function buildAuthorizeUrl({ clientId, redirectUri, state, codeChallenge, scopes }) {
|
|
117
399
|
const params = new URLSearchParams({
|
|
118
400
|
response_type: 'code',
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Cloudflare connection ownership is derived from
|
|
2
|
+
* Cloudflare connection ownership is derived from the REAL AgentSam identity
|
|
3
|
+
* session (packages/identity — the same `session` cookie set by
|
|
4
|
+
* /api/auth/login and every OAuth login callback). This previously
|
|
5
|
+
* hand-rolled its own cookie name (`agentsam_session`) and session table
|
|
6
|
+
* names (`agentsam_sessions`/`sessions`/`identity_sessions`) that never
|
|
7
|
+
* matched the actual identity system (cookie name `session`, sessions
|
|
8
|
+
* resolved via identity.sessionFromRequest against the real adapter) — so
|
|
9
|
+
* this connector could never actually authenticate anyone. Fixed to call
|
|
10
|
+
* the real identity service instead of guessing at its storage shape.
|
|
11
|
+
*
|
|
3
12
|
* Browser-submitted account_id / user_id / owner_id / X-User-Id are never authority.
|
|
4
13
|
*/
|
|
5
14
|
|
|
6
|
-
|
|
15
|
+
import { createIdentityService, createCloudflareD1Adapter } from '../../../identity/src/server/worker-router.js';
|
|
16
|
+
import { fetchIamProfile } from '../../../identity/src/providers/iam/profile.js';
|
|
17
|
+
import { normalizeIamIdentity } from '../../../identity/src/providers/iam/mapper.js';
|
|
18
|
+
import { resolveIamIssuer } from '../../../identity/src/contracts/auth-config.js';
|
|
7
19
|
|
|
8
|
-
|
|
9
|
-
const auth = request.headers.get('authorization') || '';
|
|
10
|
-
if (/^bearer\s+/i.test(auth)) {
|
|
11
|
-
const token = auth.replace(/^bearer\s+/i, '').trim();
|
|
12
|
-
if (token && !token.startsWith('cf_') && token !== 'sillynotreal-secret') return token;
|
|
13
|
-
}
|
|
14
|
-
const cookie = request.headers.get('cookie') || '';
|
|
15
|
-
const match = cookie.match(/(?:^|;\s*)agentsam_session=([^;]+)/);
|
|
16
|
-
return match ? decodeURIComponent(match[1]).trim() : '';
|
|
17
|
-
}
|
|
20
|
+
const UNTRUSTED = new Set(['account_id', 'user_id', 'owner_id', 'workspace_id']);
|
|
18
21
|
|
|
19
22
|
export function rejectUntrustedOwnerHints(request, url, body = {}) {
|
|
20
23
|
const headerUser = (request.headers.get('x-user-id') || '').trim();
|
|
@@ -36,40 +39,40 @@ export function rejectUntrustedOwnerHints(request, url, body = {}) {
|
|
|
36
39
|
|
|
37
40
|
export async function resolveAuthenticatedOwner(request, env, url, body) {
|
|
38
41
|
rejectUntrustedOwnerHints(request, url, body);
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
// Test/portable adapters may expose an in-memory session map. Keep this
|
|
43
|
+
// compatibility lane deliberately opt-in; production authority is D1.
|
|
44
|
+
const fixtureToken = (request.headers.get('authorization') || '').replace(/^Bearer\s+/i, '').trim();
|
|
45
|
+
const fixtureCookie = (request.headers.get('cookie') || '').match(/(?:^|;\s*)agentsam_session=([^;]+)/)?.[1] || '';
|
|
46
|
+
if (env?.fixtureSessions instanceof Map) {
|
|
47
|
+
const fixtureOwner = env.fixtureSessions.get(fixtureToken || fixtureCookie);
|
|
48
|
+
if (fixtureOwner) return String(fixtureOwner);
|
|
49
|
+
}
|
|
50
|
+
if (!env?.DB) {
|
|
41
51
|
const err = new Error('unauthenticated');
|
|
42
52
|
err.code = 'unauthenticated';
|
|
43
53
|
throw err;
|
|
44
54
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
`SELECT ${userCol} AS user_id FROM ${table} WHERE ${tokenCol} = ? LIMIT 1`,
|
|
64
|
-
)
|
|
65
|
-
.bind(sessionToken)
|
|
66
|
-
.first();
|
|
67
|
-
if (row?.user_id) return String(row.user_id);
|
|
68
|
-
} catch {
|
|
69
|
-
// table may not exist yet
|
|
70
|
-
}
|
|
55
|
+
const adapter = createCloudflareD1Adapter(env.DB);
|
|
56
|
+
const identity = createIdentityService({ adapter, env });
|
|
57
|
+
const ctx = await identity.sessionFromRequest(request);
|
|
58
|
+
if (ctx?.user?.id) return String(ctx.user.id);
|
|
59
|
+
|
|
60
|
+
// Native CLI OAuth returns a bearer access token rather than a browser
|
|
61
|
+
// cookie. Resolve that token through IAM userinfo, then map the verified
|
|
62
|
+
// IAM subject to the local auth user. No caller-supplied owner id is used.
|
|
63
|
+
const bearer = (request.headers.get('authorization') || '').replace(/^Bearer\s+/i, '').trim();
|
|
64
|
+
if (bearer) {
|
|
65
|
+
const profile = await fetchIamProfile({
|
|
66
|
+
issuer: resolveIamIssuer(env),
|
|
67
|
+
accessToken: bearer,
|
|
68
|
+
});
|
|
69
|
+
const identityProfile = profile ? normalizeIamIdentity(profile) : null;
|
|
70
|
+
if (identityProfile?.subject) {
|
|
71
|
+
const user = await adapter.findUserByProvider('iam', identityProfile.subject);
|
|
72
|
+
if (user?.id) return String(user.id);
|
|
71
73
|
}
|
|
72
74
|
}
|
|
75
|
+
|
|
73
76
|
const err = new Error('unauthenticated');
|
|
74
77
|
err.code = 'unauthenticated';
|
|
75
78
|
throw err;
|