@inneranimalmedia/agentsam-sdk 2.6.2 → 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/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/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 +3 -2
- 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/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/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 +117 -9
- 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/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/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 +118 -37
- package/src/commands/resume.js +9 -5
- package/src/commands/runtime-status.js +154 -0
- package/src/commands/shell.js +466 -55
- package/src/commands/status.js +82 -7
- package/src/commands/tunnel.js +228 -195
- package/src/commands/whoami.js +78 -6
- 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 -51
- 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 +8 -2
- package/src/lib/agent-instructions.js +3 -0
- package/src/lib/auth.js +7 -3
- 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 +37 -18
- package/src/lib/deploy/local-studio.js +6 -5
- 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 +73 -11
- 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 +9 -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 +24 -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 +11 -4
- package/src/ui/wireframes.js +166 -0
- package/test/account-session.test.mjs +28 -0
- package/test/apps-scaffold-contract.test.mjs +16 -1
- 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/shell.test.mjs +149 -4
- package/test/smoke.mjs +2 -2
- package/test/tools-search.test.mjs +33 -0
- package/test/unit/website-assets-bindings.test.mjs +60 -0
- package/test/whoami-resume.test.mjs +82 -3
- package/examples/gorilla-shell/README.md +0 -15
- package/src/lib/gorilla-template.js +0 -54
- 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
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
assertConnectionOwner,
|
|
10
10
|
} from './index.js';
|
|
11
11
|
import { resolveAuthenticatedOwner } from './owner.js';
|
|
12
|
-
import { sealToken, vaultConfigured } from './vault.js';
|
|
12
|
+
import { decryptSecret, sealToken, vaultConfigured } from './vault.js';
|
|
13
13
|
|
|
14
14
|
function json(data, status = 200) {
|
|
15
15
|
return new Response(JSON.stringify(data), {
|
|
@@ -22,6 +22,35 @@ function redirect(location) {
|
|
|
22
22
|
return new Response(null, { status: 302, headers: { location } });
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
function settingsRedirect(url, result, error = '', returnTo = '') {
|
|
26
|
+
const destination = returnTo ? new URL(returnTo) : new URL('/settings/integrations', url.origin);
|
|
27
|
+
destination.searchParams.set('connection', 'cloudflare');
|
|
28
|
+
destination.searchParams.set('result', result);
|
|
29
|
+
if (error) destination.searchParams.set('error', error);
|
|
30
|
+
return redirect(destination.toString());
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function resolveReturnTo(url) {
|
|
34
|
+
const raw = url.searchParams.get('return_to') || '';
|
|
35
|
+
if (!raw) return '';
|
|
36
|
+
try {
|
|
37
|
+
const destination = new URL(raw, url.origin);
|
|
38
|
+
return destination.origin === url.origin ? destination.toString() : '';
|
|
39
|
+
} catch {
|
|
40
|
+
return '';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function deleteOAuthState(env, state) {
|
|
45
|
+
if (env.DB) {
|
|
46
|
+
await env.DB.prepare(
|
|
47
|
+
`DELETE FROM agentsam_cloudflare_oauth_state WHERE state = ?`,
|
|
48
|
+
).bind(state).run();
|
|
49
|
+
} else if (env.oauthState instanceof Map) {
|
|
50
|
+
env.oauthState.delete(state);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
25
54
|
export function isCloudflareConnectionPath(pathname) {
|
|
26
55
|
return pathname === '/api/connections/cloudflare'
|
|
27
56
|
|| pathname === '/api/connections/cloudflare/start'
|
|
@@ -47,10 +76,58 @@ async function ensureTables(env) {
|
|
|
47
76
|
state TEXT PRIMARY KEY,
|
|
48
77
|
owner_id TEXT NOT NULL,
|
|
49
78
|
code_verifier TEXT NOT NULL,
|
|
50
|
-
created_at INTEGER
|
|
79
|
+
created_at INTEGER,
|
|
80
|
+
return_to TEXT
|
|
81
|
+
)`).run();
|
|
82
|
+
await env.DB.prepare(`CREATE TABLE IF NOT EXISTS integration_resources (
|
|
83
|
+
id TEXT PRIMARY KEY,
|
|
84
|
+
tenant_id TEXT NOT NULL,
|
|
85
|
+
connection_id TEXT NOT NULL,
|
|
86
|
+
provider TEXT NOT NULL,
|
|
87
|
+
resource_type TEXT NOT NULL,
|
|
88
|
+
provider_resource_id TEXT,
|
|
89
|
+
name TEXT,
|
|
90
|
+
url TEXT,
|
|
91
|
+
metadata_json TEXT DEFAULT '{}',
|
|
92
|
+
synced_at TEXT,
|
|
93
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
94
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
51
95
|
)`).run();
|
|
52
96
|
}
|
|
53
97
|
|
|
98
|
+
async function seedKnownCloudflareResources(env, ownerId, connectionId, cloudflareAccountId) {
|
|
99
|
+
if (!env?.DB?.prepare || !cloudflareAccountId) return;
|
|
100
|
+
let configuredScopes = {};
|
|
101
|
+
try { configuredScopes = JSON.parse(env.AGENTSAM_RESOURCE_SCOPE_JSON || '{}'); } catch { configuredScopes = {}; }
|
|
102
|
+
const resources = [
|
|
103
|
+
{ key: 'agentsam-sdk', type: 'worker', id: 'agentsam-sdk', name: 'AgentSam SDK / Local Studio' },
|
|
104
|
+
{ key: 'agentsam-cad-creator', type: 'worker', id: 'agentsam-cad-creator', name: 'AgentSam CAD Creator' },
|
|
105
|
+
{ key: 'agentsam-client-cms-editor', type: 'worker', id: 'agentsam-client-cms-editor', name: 'AgentSam Client CMS Editor' },
|
|
106
|
+
{ key: 'fuelnfreetime', type: 'worker', id: 'fuelnfreetime', name: 'Fuel & Free Time', metadata: {
|
|
107
|
+
zone_id: '816a5d2284103e4481987ceeb16c2ca9',
|
|
108
|
+
d1_database_id: '9fd6ff92-e407-4b51-8b01-3c93f3845bb2',
|
|
109
|
+
r2_bucket: 'fuelnfreetime',
|
|
110
|
+
...(configuredScopes.fuelnfreetime || {}),
|
|
111
|
+
} },
|
|
112
|
+
];
|
|
113
|
+
const statements = resources.map((resource) => env.DB.prepare(`
|
|
114
|
+
INSERT OR REPLACE INTO integration_resources (
|
|
115
|
+
id, tenant_id, connection_id, provider, resource_type, provider_resource_id,
|
|
116
|
+
name, metadata_json, synced_at, updated_at
|
|
117
|
+
) VALUES (?, ?, ?, 'cloudflare', ?, ?, ?, ?, datetime('now'), datetime('now'))
|
|
118
|
+
`).bind(
|
|
119
|
+
`ires_cf_${cloudflareAccountId}_${resource.key}`,
|
|
120
|
+
ownerId,
|
|
121
|
+
connectionId,
|
|
122
|
+
resource.type,
|
|
123
|
+
resource.id,
|
|
124
|
+
resource.name,
|
|
125
|
+
JSON.stringify({ cloudflare_account_id: cloudflareAccountId, ...(resource.metadata || {}) }),
|
|
126
|
+
));
|
|
127
|
+
if (typeof env.DB.batch === 'function') await env.DB.batch(statements);
|
|
128
|
+
else for (const statement of statements) await statement.run();
|
|
129
|
+
}
|
|
130
|
+
|
|
54
131
|
export async function handleCloudflareConnectionRequest(request, env) {
|
|
55
132
|
const url = new URL(request.url);
|
|
56
133
|
const client = resolveCloudflareOAuthClient(env);
|
|
@@ -98,7 +175,9 @@ export async function handleCloudflareConnectionRequest(request, env) {
|
|
|
98
175
|
if (env.DB) {
|
|
99
176
|
const row = await env.DB.prepare(
|
|
100
177
|
`SELECT connection_id, owner_id, cloudflare_account_id, scopes, status, created_at, updated_at, expires_at
|
|
101
|
-
FROM agentsam_cloudflare_connections
|
|
178
|
+
FROM agentsam_cloudflare_connections
|
|
179
|
+
WHERE owner_id = ? AND status = 'connected'
|
|
180
|
+
ORDER BY updated_at DESC LIMIT 1`,
|
|
102
181
|
).bind(ownerId).first();
|
|
103
182
|
if (row) {
|
|
104
183
|
connection = {
|
|
@@ -122,12 +201,17 @@ export async function handleCloudflareConnectionRequest(request, env) {
|
|
|
122
201
|
const verifier = btoa(String.fromCharCode(...verifierBytes)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
123
202
|
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier));
|
|
124
203
|
const challenge = btoa(String.fromCharCode(...new Uint8Array(digest))).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
204
|
+
const returnTo = resolveReturnTo(url);
|
|
125
205
|
if (env.DB) {
|
|
126
206
|
await env.DB.prepare(
|
|
127
|
-
`
|
|
128
|
-
).
|
|
207
|
+
`DELETE FROM agentsam_cloudflare_oauth_state WHERE created_at < unixepoch() - 600`,
|
|
208
|
+
).run();
|
|
209
|
+
await env.DB.prepare(
|
|
210
|
+
`INSERT INTO agentsam_cloudflare_oauth_state (state, owner_id, code_verifier, created_at, return_to)
|
|
211
|
+
VALUES (?, ?, ?, unixepoch(), ?)`,
|
|
212
|
+
).bind(state, ownerId, verifier, returnTo || null).run();
|
|
129
213
|
} else if (env.oauthState instanceof Map) {
|
|
130
|
-
env.oauthState.set(state, { ownerId, verifier });
|
|
214
|
+
env.oauthState.set(state, { ownerId, verifier, returnTo });
|
|
131
215
|
}
|
|
132
216
|
const redirectUri = `${url.origin}${CLOUDFLARE_CALLBACK_PATH}`;
|
|
133
217
|
const authorize = buildAuthorizeUrl({
|
|
@@ -142,41 +226,62 @@ export async function handleCloudflareConnectionRequest(request, env) {
|
|
|
142
226
|
if (url.pathname === CLOUDFLARE_CALLBACK_PATH && request.method === 'GET') {
|
|
143
227
|
const code = url.searchParams.get('code') || '';
|
|
144
228
|
const state = url.searchParams.get('state') || '';
|
|
229
|
+
const providerError = url.searchParams.get('error') || '';
|
|
145
230
|
let stored = null;
|
|
146
231
|
if (env.DB) {
|
|
147
232
|
stored = await env.DB.prepare(
|
|
148
|
-
`SELECT owner_id, code_verifier
|
|
233
|
+
`SELECT owner_id, code_verifier, created_at, return_to
|
|
234
|
+
FROM agentsam_cloudflare_oauth_state WHERE state = ?`,
|
|
149
235
|
).bind(state).first();
|
|
150
236
|
} else if (env.oauthState instanceof Map) {
|
|
151
237
|
stored = env.oauthState.get(state);
|
|
152
|
-
if (stored) stored = { owner_id: stored.ownerId, code_verifier: stored.verifier };
|
|
238
|
+
if (stored) stored = { owner_id: stored.ownerId, code_verifier: stored.verifier, return_to: stored.returnTo || '' };
|
|
153
239
|
}
|
|
154
240
|
if (!stored) {
|
|
241
|
+
// A callback without a one-time PKCE state is forged or expired. Keep
|
|
242
|
+
// this as an explicit 403 instead of redirecting into a misleading UI.
|
|
155
243
|
return json({ ok: false, error: 'cloudflare_connection_forbidden' }, 403);
|
|
156
244
|
}
|
|
157
245
|
if (!ownerId) ownerId = stored.owner_id;
|
|
158
246
|
if (stored.owner_id !== ownerId) {
|
|
159
|
-
return
|
|
247
|
+
return settingsRedirect(url, 'error', 'cloudflare_connection_forbidden', stored.return_to || '');
|
|
248
|
+
}
|
|
249
|
+
const createdAt = Number(stored.created_at || 0);
|
|
250
|
+
const now = Math.floor(Date.now() / 1000);
|
|
251
|
+
if (createdAt && now - createdAt > 10 * 60) {
|
|
252
|
+
await deleteOAuthState(env, state);
|
|
253
|
+
return settingsRedirect(url, 'error', 'oauth_state_expired', stored.return_to || '');
|
|
160
254
|
}
|
|
255
|
+
await deleteOAuthState(env, state);
|
|
256
|
+
if (providerError) {
|
|
257
|
+
return settingsRedirect(url, 'error', providerError, stored.return_to || '');
|
|
258
|
+
}
|
|
259
|
+
if (!code) {
|
|
260
|
+
return settingsRedirect(url, 'error', 'authorization_code_missing', stored.return_to || '');
|
|
261
|
+
}
|
|
262
|
+
// This is Cloudflare's public PKCE client (Token Authentication Method:
|
|
263
|
+
// None). Do not add client_secret, even if an obsolete Worker binding is
|
|
264
|
+
// present; a mixed-auth exchange is rejected by Cloudflare.
|
|
265
|
+
const tokenParams = {
|
|
266
|
+
grant_type: 'authorization_code',
|
|
267
|
+
code,
|
|
268
|
+
redirect_uri: `${url.origin}${CLOUDFLARE_CALLBACK_PATH}`,
|
|
269
|
+
client_id: String(env.CLOUDFLARE_OAUTH_CLIENT_ID),
|
|
270
|
+
code_verifier: stored.code_verifier,
|
|
271
|
+
};
|
|
161
272
|
const tokenRes = await fetch(CLOUDFLARE_OAUTH_TOKEN_URL, {
|
|
162
273
|
method: 'POST',
|
|
163
274
|
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
164
|
-
body: new URLSearchParams(
|
|
165
|
-
grant_type: 'authorization_code',
|
|
166
|
-
code,
|
|
167
|
-
redirect_uri: `${url.origin}${CLOUDFLARE_CALLBACK_PATH}`,
|
|
168
|
-
client_id: String(env.CLOUDFLARE_OAUTH_CLIENT_ID),
|
|
169
|
-
client_secret: String(env.CLOUDFLARE_OAUTH_CLIENT_SECRET),
|
|
170
|
-
code_verifier: stored.code_verifier,
|
|
171
|
-
}),
|
|
275
|
+
body: new URLSearchParams(tokenParams),
|
|
172
276
|
});
|
|
173
277
|
if (!tokenRes.ok) {
|
|
174
|
-
|
|
278
|
+
console.error('cloudflare_token_exchange_failed', tokenRes.status);
|
|
279
|
+
return settingsRedirect(url, 'error', 'token_exchange_failed', stored.return_to || '');
|
|
175
280
|
}
|
|
176
281
|
const tokens = await tokenRes.json();
|
|
177
282
|
const connectionId = `cfconn_${crypto.randomUUID().replace(/-/g, '').slice(0, 16)}`;
|
|
178
283
|
if (tokens.access_token && !vaultConfigured(env)) {
|
|
179
|
-
return
|
|
284
|
+
return settingsRedirect(url, 'error', 'vault_unavailable', stored.return_to || '');
|
|
180
285
|
}
|
|
181
286
|
const aad = `cloudflare-connection:${ownerId}`;
|
|
182
287
|
let accessEnc = null;
|
|
@@ -185,10 +290,16 @@ export async function handleCloudflareConnectionRequest(request, env) {
|
|
|
185
290
|
accessEnc = await sealToken(env, tokens.access_token, aad);
|
|
186
291
|
refreshEnc = await sealToken(env, tokens.refresh_token, aad);
|
|
187
292
|
} catch (err) {
|
|
188
|
-
return
|
|
293
|
+
return settingsRedirect(url, 'error', err.code || 'vault_unavailable', stored.return_to || '');
|
|
189
294
|
}
|
|
190
295
|
if (env.DB) {
|
|
191
|
-
|
|
296
|
+
const removePrevious = env.DB.prepare(
|
|
297
|
+
`UPDATE agentsam_cloudflare_connections
|
|
298
|
+
SET status = 'superseded', access_token_encrypted = NULL,
|
|
299
|
+
refresh_token_encrypted = NULL, updated_at = unixepoch()
|
|
300
|
+
WHERE owner_id = ? AND status = 'connected'`,
|
|
301
|
+
).bind(ownerId);
|
|
302
|
+
const insertConnection = env.DB.prepare(
|
|
192
303
|
`INSERT INTO agentsam_cloudflare_connections (
|
|
193
304
|
connection_id, owner_id, cloudflare_account_id, scopes, status,
|
|
194
305
|
access_token_encrypted, refresh_token_encrypted, created_at, updated_at, expires_at
|
|
@@ -201,22 +312,52 @@ export async function handleCloudflareConnectionRequest(request, env) {
|
|
|
201
312
|
accessEnc,
|
|
202
313
|
refreshEnc,
|
|
203
314
|
tokens.expires_in ? Math.floor(Date.now() / 1000) + Number(tokens.expires_in) : null,
|
|
204
|
-
)
|
|
315
|
+
);
|
|
316
|
+
if (typeof env.DB.batch === 'function') {
|
|
317
|
+
await env.DB.batch([removePrevious, insertConnection]);
|
|
318
|
+
} else {
|
|
319
|
+
await removePrevious.run();
|
|
320
|
+
await insertConnection.run();
|
|
321
|
+
}
|
|
322
|
+
await seedKnownCloudflareResources(env, ownerId, connectionId, tokens.account_id || null);
|
|
205
323
|
}
|
|
206
|
-
return
|
|
324
|
+
return settingsRedirect(url, 'connected', '', stored.return_to || '');
|
|
207
325
|
}
|
|
208
326
|
|
|
209
327
|
if (url.pathname === '/api/connections/cloudflare/disconnect' && request.method === 'POST') {
|
|
328
|
+
let providerRevoked = false;
|
|
210
329
|
if (env.DB) {
|
|
211
330
|
const row = await env.DB.prepare(
|
|
212
|
-
`SELECT connection_id, owner_id
|
|
331
|
+
`SELECT connection_id, owner_id, access_token_encrypted
|
|
332
|
+
FROM agentsam_cloudflare_connections
|
|
333
|
+
WHERE owner_id = ? AND status = 'connected'
|
|
334
|
+
ORDER BY updated_at DESC LIMIT 1`,
|
|
213
335
|
).bind(ownerId).first();
|
|
214
336
|
if (row) {
|
|
215
337
|
assertConnectionOwner({ ownerId: row.owner_id, connectionId: row.connection_id }, ownerId);
|
|
216
|
-
|
|
338
|
+
if (row.access_token_encrypted) {
|
|
339
|
+
try {
|
|
340
|
+
const token = await decryptSecret(env, row.access_token_encrypted, `cloudflare-connection:${ownerId}`);
|
|
341
|
+
const revokeParams = new URLSearchParams({ token, client_id: String(env.CLOUDFLARE_OAUTH_CLIENT_ID) });
|
|
342
|
+
const revokeResponse = await fetch(CLOUDFLARE_OAUTH_REVOKE_URL, {
|
|
343
|
+
method: 'POST',
|
|
344
|
+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
345
|
+
body: revokeParams,
|
|
346
|
+
});
|
|
347
|
+
providerRevoked = revokeResponse.ok;
|
|
348
|
+
} catch (error) {
|
|
349
|
+
console.error('cloudflare_token_revoke_failed', String(error?.message || error));
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
await env.DB.prepare(`
|
|
353
|
+
UPDATE agentsam_cloudflare_connections
|
|
354
|
+
SET status = 'revoked', access_token_encrypted = NULL,
|
|
355
|
+
refresh_token_encrypted = NULL, expires_at = unixepoch(), updated_at = unixepoch()
|
|
356
|
+
WHERE connection_id = ? AND owner_id = ?
|
|
357
|
+
`).bind(row.connection_id, ownerId).run();
|
|
217
358
|
}
|
|
218
359
|
}
|
|
219
|
-
return json({ ok: true, status: 'not_configured' });
|
|
360
|
+
return json({ ok: true, status: 'not_configured', provider_revoked: providerRevoked });
|
|
220
361
|
}
|
|
221
362
|
|
|
222
363
|
return json({ ok: false, error: 'not_found' }, 404);
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
cloudflareConnectionSafeStatus,
|
|
6
6
|
resolveCloudflareOAuthClient,
|
|
7
7
|
} from '../src/index.js';
|
|
8
|
+
import { handleCloudflareConnectionRequest } from '../src/routes.js';
|
|
8
9
|
|
|
9
10
|
describe('cloudflare connector', () => {
|
|
10
11
|
it('reports not_configured when credentials are absent', () => {
|
|
@@ -17,7 +18,6 @@ describe('cloudflare connector', () => {
|
|
|
17
18
|
it('loads fake fixtures without treating them as production authority', () => {
|
|
18
19
|
const client = resolveCloudflareOAuthClient({
|
|
19
20
|
CLOUDFLARE_OAUTH_CLIENT_ID: 'sillynotreal',
|
|
20
|
-
CLOUDFLARE_OAUTH_CLIENT_SECRET: 'sillynotreal-secret',
|
|
21
21
|
});
|
|
22
22
|
assert.equal(client.configured, true);
|
|
23
23
|
assert.equal(client.fixture, true);
|
|
@@ -32,7 +32,7 @@ describe('cloudflare connector', () => {
|
|
|
32
32
|
});
|
|
33
33
|
const blob = JSON.stringify(status);
|
|
34
34
|
assert.equal(blob.includes('sillynotreal-secret'), false);
|
|
35
|
-
assert.equal(status.
|
|
35
|
+
assert.equal(status.token_auth_method, 'none_pkce');
|
|
36
36
|
assert.equal(status.configured, false);
|
|
37
37
|
});
|
|
38
38
|
|
|
@@ -41,4 +41,114 @@ describe('cloudflare connector', () => {
|
|
|
41
41
|
assert.throws(() => assertConnectionOwner(record, 'connor'), /cloudflare_connection_forbidden/);
|
|
42
42
|
assert.equal(assertConnectionOwner(record, 'sam').connectionId, 'c1');
|
|
43
43
|
});
|
|
44
|
+
|
|
45
|
+
it('supports a production PKCE client with no client secret', () => {
|
|
46
|
+
const client = resolveCloudflareOAuthClient({
|
|
47
|
+
CLOUDFLARE_OAUTH_CLIENT_ID: 'real-client-id',
|
|
48
|
+
});
|
|
49
|
+
assert.equal(client.productionReady, true);
|
|
50
|
+
assert.equal(client.clientIdConfigured, true);
|
|
51
|
+
assert.equal(client.tokenAuthMethod, 'none_pkce');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('keeps connector return paths same-origin', async () => {
|
|
55
|
+
const calls = [];
|
|
56
|
+
const DB = {
|
|
57
|
+
prepare(sql) {
|
|
58
|
+
return {
|
|
59
|
+
args: [],
|
|
60
|
+
bind(...args) { this.args = args; return this; },
|
|
61
|
+
async run() { calls.push({ sql, args: this.args }); return { success: true }; },
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
const response = await handleCloudflareConnectionRequest(
|
|
66
|
+
new Request('https://agentsam.example/api/connections/cloudflare/start?return_to=https://untrusted.example/after', {
|
|
67
|
+
headers: { authorization: 'Bearer fixture' },
|
|
68
|
+
}),
|
|
69
|
+
{
|
|
70
|
+
DB,
|
|
71
|
+
fixtureSessions: new Map([['fixture', 'user_123']]),
|
|
72
|
+
CLOUDFLARE_OAUTH_CLIENT_ID: 'real-client-id',
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
assert.equal(response.status, 200);
|
|
76
|
+
assert.equal(
|
|
77
|
+
calls.some((call) => call.sql.includes('DELETE FROM agentsam_cloudflare_oauth_state WHERE created_at < unixepoch() - 600')),
|
|
78
|
+
true,
|
|
79
|
+
);
|
|
80
|
+
const stateInsert = calls.find((call) => call.sql.includes('INSERT INTO agentsam_cloudflare_oauth_state'));
|
|
81
|
+
assert.ok(stateInsert);
|
|
82
|
+
assert.equal(stateInsert.args.at(-1), null);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('consumes callback state and stores only encrypted OAuth tokens', async () => {
|
|
86
|
+
const now = Math.floor(Date.now() / 1000);
|
|
87
|
+
const calls = [];
|
|
88
|
+
const statements = [];
|
|
89
|
+
const DB = {
|
|
90
|
+
prepare(sql) {
|
|
91
|
+
const statement = {
|
|
92
|
+
sql,
|
|
93
|
+
args: [],
|
|
94
|
+
bind(...args) {
|
|
95
|
+
this.args = args;
|
|
96
|
+
return this;
|
|
97
|
+
},
|
|
98
|
+
async first() {
|
|
99
|
+
if (sql.includes('agentsam_cloudflare_oauth_state')) {
|
|
100
|
+
return { owner_id: 'user_123', code_verifier: 'verifier', created_at: now };
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
},
|
|
104
|
+
async run() {
|
|
105
|
+
calls.push({ sql, args: this.args });
|
|
106
|
+
return { success: true };
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
statements.push(statement);
|
|
110
|
+
return statement;
|
|
111
|
+
},
|
|
112
|
+
async batch(batchStatements) {
|
|
113
|
+
for (const statement of batchStatements) await statement.run();
|
|
114
|
+
return batchStatements.map(() => ({ success: true }));
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
const originalFetch = globalThis.fetch;
|
|
118
|
+
globalThis.fetch = async (_input, init) => {
|
|
119
|
+
const body = new URLSearchParams(init.body);
|
|
120
|
+
assert.equal(body.get('client_secret'), null);
|
|
121
|
+
return new Response(JSON.stringify({
|
|
122
|
+
access_token: 'access-plaintext',
|
|
123
|
+
refresh_token: 'refresh-plaintext',
|
|
124
|
+
account_id: 'account_123',
|
|
125
|
+
scope: 'd1.read workers-scripts.write',
|
|
126
|
+
expires_in: 3600,
|
|
127
|
+
}), { status: 200, headers: { 'content-type': 'application/json' } });
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const response = await handleCloudflareConnectionRequest(
|
|
132
|
+
new Request('https://agentsam.example/api/connections/cloudflare/callback?code=code_123&state=state_123'),
|
|
133
|
+
{
|
|
134
|
+
DB,
|
|
135
|
+
CLOUDFLARE_OAUTH_CLIENT_ID: 'real-client-id',
|
|
136
|
+
CLOUDFLARE_OAUTH_CLIENT_SECRET: 'obsolete-secret-must-not-be-sent',
|
|
137
|
+
VAULT_MASTER_KEY: '01234567890123456789012345678901',
|
|
138
|
+
},
|
|
139
|
+
);
|
|
140
|
+
assert.equal(response.status, 302);
|
|
141
|
+
assert.equal(
|
|
142
|
+
response.headers.get('location'),
|
|
143
|
+
'https://agentsam.example/settings/integrations?connection=cloudflare&result=connected',
|
|
144
|
+
);
|
|
145
|
+
assert.equal(calls.some((call) => call.sql.includes('DELETE FROM agentsam_cloudflare_oauth_state')), true);
|
|
146
|
+
const insert = calls.find((call) => call.sql.includes('INSERT INTO agentsam_cloudflare_connections'));
|
|
147
|
+
assert.ok(insert);
|
|
148
|
+
assert.notEqual(insert.args[4], 'access-plaintext');
|
|
149
|
+
assert.notEqual(insert.args[5], 'refresh-plaintext');
|
|
150
|
+
} finally {
|
|
151
|
+
globalThis.fetch = originalFetch;
|
|
152
|
+
}
|
|
153
|
+
});
|
|
44
154
|
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# @inneranimalmedia/heuristic-theme
|
|
2
|
+
|
|
3
|
+
Stock AgentSam CMS storefront shell theme. Exports a deterministic theme contract consumed by CMS presets and `theme.storefront.shell`.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
import { createStorefrontShellTheme } from "@inneranimalmedia/heuristic-theme";
|
|
7
|
+
|
|
8
|
+
const theme = createStorefrontShellTheme();
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Historical gallery demos live in `apps/theme-gallery-preview` — this package owns the reusable stock contract, not donor site archives.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@inneranimalmedia/heuristic-theme",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Stock AgentSam CMS storefront shell theme contract (heuristic-theme).",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js",
|
|
9
|
+
"./theme": "./src/theme.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"src",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "node --test test/*.test.mjs"
|
|
17
|
+
},
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=22 <25"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT"
|
|
25
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createStorefrontShellTheme } from "./theme.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Durable agentsam_products payload for the stock heuristic theme.
|
|
5
|
+
* Caller resolves repository_id against live code_repositories before UPSERT.
|
|
6
|
+
*/
|
|
7
|
+
export function createHeuristicThemeProductRow({ accountId, repositoryId = null } = {}) {
|
|
8
|
+
const theme = createStorefrontShellTheme();
|
|
9
|
+
return {
|
|
10
|
+
account_id: accountId || null,
|
|
11
|
+
slug: theme.slug,
|
|
12
|
+
name: theme.displayName,
|
|
13
|
+
kind: "theme",
|
|
14
|
+
status: "wired",
|
|
15
|
+
repository_id: repositoryId,
|
|
16
|
+
canonical_path: "packages/heuristic-theme",
|
|
17
|
+
package_name: "@inneranimalmedia/heuristic-theme",
|
|
18
|
+
metadata: {
|
|
19
|
+
origin: "gallery_mount",
|
|
20
|
+
normalization_state: "wired",
|
|
21
|
+
package: "@inneranimalmedia/heuristic-theme",
|
|
22
|
+
preview_kind: "live",
|
|
23
|
+
capabilities: ["theme.storefront.shell"],
|
|
24
|
+
app_manifest: null,
|
|
25
|
+
help_root: "docs/",
|
|
26
|
+
},
|
|
27
|
+
capability: "theme.storefront.shell",
|
|
28
|
+
relationships: [
|
|
29
|
+
{
|
|
30
|
+
relationship_type: "packaged_as",
|
|
31
|
+
target_type: "sdk-package",
|
|
32
|
+
target_slug: "heuristic-theme",
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** @typedef {{ id: string, slug: string, displayName: string, version: string, kind: string, surfaces: string[], slots: Record<string, string[]>, tokens: Record<string, string>, sections: Array<{ type: string, label: string }>, metadata: Record<string, unknown> }} StorefrontShellTheme */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Deterministic stock CMS storefront shell theme contract.
|
|
5
|
+
* @returns {StorefrontShellTheme}
|
|
6
|
+
*/
|
|
7
|
+
export function createStorefrontShellTheme() {
|
|
8
|
+
return {
|
|
9
|
+
id: "theme.storefront.shell",
|
|
10
|
+
slug: "heuristic-theme",
|
|
11
|
+
displayName: "Heuristic Theme",
|
|
12
|
+
version: "0.1.0",
|
|
13
|
+
kind: "storefront-shell",
|
|
14
|
+
surfaces: ["cms.editor", "cms.preview", "theme.gallery"],
|
|
15
|
+
slots: {
|
|
16
|
+
shell: ["header", "main", "footer"],
|
|
17
|
+
page: ["hero", "products", "content", "footer"],
|
|
18
|
+
navigation: ["brand", "links", "cta"],
|
|
19
|
+
},
|
|
20
|
+
tokens: {
|
|
21
|
+
"--color-bg": "#F9F7F2",
|
|
22
|
+
"--color-ink": "#101014",
|
|
23
|
+
"--color-accent": "#1e6a6f",
|
|
24
|
+
"--color-muted": "#8a8a95",
|
|
25
|
+
"--font-display": "\"Iowan Old Style\", \"Palatino Linotype\", Palatino, serif",
|
|
26
|
+
"--font-body": "ui-sans-serif, system-ui, -apple-system, sans-serif",
|
|
27
|
+
"--radius-control": "8px",
|
|
28
|
+
},
|
|
29
|
+
sections: [
|
|
30
|
+
{ type: "hero", label: "Editorial hero" },
|
|
31
|
+
{ type: "products", label: "Product grid" },
|
|
32
|
+
{ type: "footer", label: "Footer" },
|
|
33
|
+
],
|
|
34
|
+
metadata: {
|
|
35
|
+
package: "@inneranimalmedia/heuristic-theme",
|
|
36
|
+
capability: "theme.storefront.shell",
|
|
37
|
+
deterministic: true,
|
|
38
|
+
demoSite: "demo",
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import { createStorefrontShellTheme } from "../src/index.js";
|
|
4
|
+
|
|
5
|
+
test("createStorefrontShellTheme returns stable stock contract", () => {
|
|
6
|
+
const theme = createStorefrontShellTheme();
|
|
7
|
+
assert.equal(theme.id, "theme.storefront.shell");
|
|
8
|
+
assert.equal(theme.slug, "heuristic-theme");
|
|
9
|
+
assert.equal(theme.kind, "storefront-shell");
|
|
10
|
+
assert.ok(theme.surfaces.includes("cms.editor"));
|
|
11
|
+
assert.ok(theme.slots.shell.includes("header"));
|
|
12
|
+
assert.equal(theme.tokens["--color-accent"], "#1e6a6f");
|
|
13
|
+
assert.equal(theme.metadata.package, "@inneranimalmedia/heuristic-theme");
|
|
14
|
+
assert.deepEqual(createStorefrontShellTheme(), theme);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
import { createHeuristicThemeProductRow } from "../src/index.js";
|
|
18
|
+
|
|
19
|
+
test("createHeuristicThemeProductRow emits D1-ready product identity", () => {
|
|
20
|
+
const row = createHeuristicThemeProductRow({ accountId: "acct_demo", repositoryId: "repo_sdk" });
|
|
21
|
+
assert.equal(row.slug, "heuristic-theme");
|
|
22
|
+
assert.equal(row.kind, "theme");
|
|
23
|
+
assert.equal(row.status, "wired");
|
|
24
|
+
assert.equal(row.metadata.capabilities[0], "theme.storefront.shell");
|
|
25
|
+
assert.equal(row.canonical_path, "packages/heuristic-theme");
|
|
26
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "agentsam.feature.v1",
|
|
3
|
+
"id": "identity.oauth-login-portal",
|
|
4
|
+
"name": "OAuth Login Portal",
|
|
5
|
+
"kind": "integration",
|
|
6
|
+
"status": "extracted",
|
|
7
|
+
"package": {
|
|
8
|
+
"name": "@inneranimalmedia/agentsam-sdk-identity",
|
|
9
|
+
"version": "2.6.2",
|
|
10
|
+
"directory": "packages/identity"
|
|
11
|
+
},
|
|
12
|
+
"provides": [
|
|
13
|
+
"identity.init",
|
|
14
|
+
"identity.login",
|
|
15
|
+
"identity.session",
|
|
16
|
+
"identity.oauth",
|
|
17
|
+
"identity.password-reset",
|
|
18
|
+
"identity.portal-ui"
|
|
19
|
+
],
|
|
20
|
+
"runtime": [
|
|
21
|
+
"worker",
|
|
22
|
+
"browser"
|
|
23
|
+
],
|
|
24
|
+
"contributes": {
|
|
25
|
+
"ui": [
|
|
26
|
+
"auth-portal"
|
|
27
|
+
],
|
|
28
|
+
"migrations": [
|
|
29
|
+
"src/migrations/0001_identity_core.sql",
|
|
30
|
+
"src/migrations/0002_company.sql"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"artifacts": [
|
|
34
|
+
{
|
|
35
|
+
"kind": "provider-catalog",
|
|
36
|
+
"path": "./providers.json"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"kind": "resources",
|
|
40
|
+
"path": "./resources.json"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"kind": "routes",
|
|
44
|
+
"path": "./routes.json"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"kind": "ui",
|
|
48
|
+
"path": "./ui.json"
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"activation": {
|
|
52
|
+
"steps": [
|
|
53
|
+
"validate_manifest",
|
|
54
|
+
"check_runtime",
|
|
55
|
+
"resolve_requires",
|
|
56
|
+
"plan_migrations",
|
|
57
|
+
"plan_routes",
|
|
58
|
+
"operator_approval",
|
|
59
|
+
"activate",
|
|
60
|
+
"verify",
|
|
61
|
+
"write_install_receipt"
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
}
|