@inneranimalmedia/agentsam-sdk 2.6.2 → 2.6.4
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 +51 -1
- package/README.md +95 -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/bin/agentsam +16 -1
- 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/AGENTSAM_DISTRIBUTION_OWNERSHIP.md +176 -0
- package/docs/architecture/AGENTSAM_GO_RUNTIME.md +282 -0
- package/docs/architecture/CODEBASEINDEX_GUIDED_PATH.md +202 -0
- package/docs/architecture/FS_E2E_CLOSURE_RECEIPT.md +59 -0
- package/docs/architecture/LOCAL_FS_AUTHORITY.md +38 -0
- package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +28 -0
- package/docs/architecture/PLAN_CLI_AND_LOCAL_STUDIO_DESKTOP.md +96 -0
- package/docs/architecture/PROVIDER-TOOLS-AND-COMPACTION.md +60 -0
- package/docs/architecture/SAM_ACTIVITY_RECOVERY_RECEIPT.md +39 -0
- package/docs/architecture/SAM_DECISION_WORK_RECEIPT.md +54 -0
- package/docs/architecture/SAM_KERNEL.md +181 -0
- package/docs/architecture/SAM_MACHINE_NORMALIZATION_PRECOMMIT_REPORT.md +208 -0
- package/docs/architecture/SLASH_SKILLS_PORTABLE.md +116 -0
- package/docs/architecture/STORAGE.md +87 -0
- package/docs/architecture/fs-e2e-receipt.latest.json +42 -0
- package/docs/architecture/previews/codebaseindex-guided-path/CODEBASEINDEX_GUIDED_PATH.md +202 -0
- package/docs/architecture/previews/codebaseindex-guided-path/index.html +321 -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/d1/0010_portable_tickets_memory.sql +140 -0
- package/migrations/d1/0011_agentsam_skill_v2.sql +185 -0
- package/migrations/d1/0011b_agentsam_skill_v2_cutover.sql +22 -0
- package/migrations/d1/0011c_agentsam_skill_v2_backfill.sql +76 -0
- package/migrations/d1/0011d_agentsam_skill_v2_retrieval_revisions.sql +50 -0
- package/migrations/d1/0012_agentsam_tools_required_seed.sql +67 -0
- package/migrations/d1/0013_identity_oauth_states.sql +15 -0
- package/migrations/d1/0014_auth_event_log.sql +20 -0
- package/migrations/d1/0015_identity_oauth_state_app_id.sql +3 -0
- package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +16 -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/migrations/sqlite/agentsam_skill_retrieval.portable.sql +42 -0
- package/package.json +107 -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 +62 -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 +239 -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 +11 -0
- package/packages/agentsam-errors/src/normalize.js +30 -0
- package/packages/agentsam-errors/src/recovery.js +301 -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 +107 -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 +176 -26
- package/packages/connectors/cloudflare/tests/connector.test.mjs +137 -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 +83 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/ui.json +35 -0
- package/packages/identity/docs/PORTABLE_IDENTITY_ARCHITECTURE.md +50 -0
- package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +31 -0
- package/packages/identity/migrations/sqlite/001_identity_core.sql +99 -0
- package/packages/identity/migrations/sqlite/002_identity_oauth_client.sql +38 -0
- package/packages/identity/migrations/sqlite/003_identity_oauth_server.sql +64 -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 +156 -18
- package/packages/identity/src/adapters/sqlite/index.js +319 -0
- package/packages/identity/src/app/verify-app.js +95 -0
- package/packages/identity/src/contracts/identity-store.js +115 -0
- package/packages/identity/src/contracts/provider.js +3 -2
- package/packages/identity/src/contracts/route-ids.js +30 -0
- package/packages/identity/src/contracts/route-projection.js +218 -0
- package/packages/identity/src/contracts/routes.js +11 -0
- package/packages/identity/src/core/browser-paths.js +4 -5
- package/packages/identity/src/core/constants.js +13 -8
- package/packages/identity/src/core/session-policy.js +32 -0
- package/packages/identity/src/frontend/auth-portal/pages/login.html +16 -9
- package/packages/identity/src/frontend/auth-portal/pages/reset.html +3 -3
- package/packages/identity/src/frontend/auth-portal/pages/signup.html +3 -3
- package/packages/identity/src/frontend/auth-portal/preview/dashboard-stub.html +1 -1
- package/packages/identity/src/index.js +27 -0
- package/packages/identity/src/oauth/README.md +10 -4
- package/packages/identity/src/oauth/credentials.js +31 -11
- package/packages/identity/src/oauth/finalize-inbound.js +1 -1
- package/packages/identity/src/oauth/iam-platform.js +13 -12
- package/packages/identity/src/oauth/redirect-paths.js +27 -36
- 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 +35 -8
- package/packages/identity/src/server/mount-policy.js +30 -0
- package/packages/identity/src/server/post-auth.js +79 -0
- package/packages/identity/src/server/worker-router.js +153 -66
- package/packages/identity/tests/finalize-inbound-oauth.test.mjs +6 -6
- package/packages/identity/tests/iam-provider.test.mjs +1 -1
- package/packages/identity/tests/identity-service.test.mjs +47 -1
- package/packages/identity/tests/oauth-credentials.test.mjs +3 -1
- package/packages/identity/tests/portable-identity-architecture.test.mjs +157 -0
- package/packages/identity/tests/session-routes-policy.test.mjs +21 -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 +31 -0
- package/packages/theme-church-site/src/harvest.json +14 -0
- package/packages/theme-church-site/src/index.js +85 -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 +31 -0
- package/packages/theme-companions-site/src/harvest.json +12 -0
- package/packages/theme-companions-site/src/index.js +83 -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 +31 -0
- package/packages/theme-floors-site/src/harvest.json +14 -0
- package/packages/theme-floors-site/src/index.js +83 -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 +31 -0
- package/packages/theme-fuelnfree-site/src/harvest.json +13 -0
- package/packages/theme-fuelnfree-site/src/index.js +82 -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 +31 -0
- package/packages/theme-handyman-site/src/harvest.json +10 -0
- package/packages/theme-handyman-site/src/index.js +84 -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 +31 -0
- package/packages/theme-insurance-site/src/harvest.json +10 -0
- package/packages/theme-insurance-site/src/index.js +84 -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 +31 -0
- package/packages/theme-shinshu-site/src/harvest.json +12 -0
- package/packages/theme-shinshu-site/src/index.js +84 -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/apps/agentsam.app.v1.schema.json +51 -0
- package/protocol/brand/brandpack.v1.schema.json +43 -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/credentials/issue.v1.schema.json +38 -0
- package/protocol/database/connection.v1.schema.json +41 -0
- package/protocol/embeddings/embedding-profile.v1.schema.json +20 -0
- package/protocol/errors/error-catalog.json +164 -0
- package/protocol/errors/error-envelope.schema.json +678 -0
- package/protocol/errors/recovery.v1.schema.json +50 -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/runtime/workspace-fs.v1.schema.json +71 -0
- package/protocol/sam/activity.v1.schema.json +48 -0
- package/protocol/sam/answer.v1.schema.json +35 -0
- package/protocol/sam/calibration.v1.schema.json +21 -0
- package/protocol/sam/decision-receipt.v1.schema.json +29 -0
- package/protocol/sam/evaluation.v1.schema.json +19 -0
- package/protocol/sam/operation.schema.json +66 -0
- package/protocol/sam/outcome.v1.schema.json +36 -0
- package/protocol/sam/question.v1.schema.json +26 -0
- package/protocol/sam/registry.seed.json +153 -0
- package/protocol/sam/result.schema.json +53 -0
- package/protocol/sam/state.v1.schema.json +23 -0
- package/protocol/skills/agentsam.interaction.v1.schema.json +50 -0
- package/protocol/skills/agentsam.skill.v1.schema.json +57 -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/protocol/ui/icon-registry.mjs +226 -0
- package/protocol/ui/icon.v1.schema.json +51 -0
- package/services/cad/server.py +249 -2
- package/skills/README.md +22 -9
- package/skills/agentsam-codebaseindex/SKILL.md +225 -0
- package/skills/catalog.json +14 -0
- 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/command-catalog.js +130 -0
- package/src/cli/dispatch.js +48 -0
- package/src/cli.js +160 -10
- 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/api-key.js +244 -0
- package/src/commands/app.js +138 -0
- package/src/commands/autorag.js +77 -0
- package/src/commands/brand.js +291 -0
- package/src/commands/cad.js +1 -0
- package/src/commands/codebaseindex.js +688 -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 +155 -27
- package/src/commands/eval.js +209 -14
- package/src/commands/go.js +678 -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/interaction-clack.js +115 -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 +110 -24
- 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 +173 -44
- package/src/commands/resume.js +9 -5
- package/src/commands/runtime-status.js +154 -0
- package/src/commands/shell.js +508 -56
- package/src/commands/skill.js +248 -0
- package/src/commands/skills.js +1 -1
- package/src/commands/start-local.js +4 -0
- package/src/commands/status.js +82 -7
- package/src/commands/tunnel.js +228 -195
- package/src/commands/whoami.js +156 -12
- 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 +298 -0
- package/src/go/cloudflare.js +608 -0
- package/src/go/container.js +120 -0
- package/src/go/contract.js +144 -0
- package/src/go/discover.js +212 -0
- package/src/go/index.js +25 -0
- package/src/go/native-probe-runner.mjs +119 -0
- package/src/go/official-registry.js +280 -0
- package/src/go/official-release.js +10 -0
- package/src/go/receipts.js +144 -0
- package/src/go/verify.js +38 -0
- package/src/index.js +127 -1
- package/src/indexing/ingest/discover-models.js +298 -0
- package/src/indexing/ingest/inventory.js +243 -0
- package/src/indexing/ingest/job-graph.js +181 -0
- package/src/indexing/ingest/materials.js +210 -0
- 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 +136 -32
- 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/local-fs/capability.js +121 -0
- package/src/local-fs/freshness.js +75 -0
- package/src/local-fs/index.js +385 -0
- package/src/local-fs/paths.js +100 -0
- package/src/local-pty/server.js +295 -19
- 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/ai-access-onboarding.js +112 -0
- package/src/models/catalog.js +329 -51
- package/src/models/discovery.js +34 -6
- package/src/models/index.js +2 -0
- package/src/models/inventory-core.js +190 -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/sam/activity/index.js +183 -0
- package/src/sam/client.js +252 -0
- package/src/sam/decision/calibration.js +109 -0
- package/src/sam/decision/confidence.js +126 -0
- package/src/sam/decision/evaluate.js +157 -0
- package/src/sam/decision/evaluators/deterministic.js +341 -0
- package/src/sam/decision/evaluators/heuristic.js +61 -0
- package/src/sam/decision/evaluators/select.js +50 -0
- package/src/sam/decision/evaluators/semantic.js +149 -0
- package/src/sam/decision/hierarchical.js +61 -0
- package/src/sam/decision/index.js +53 -0
- package/src/sam/decision/policy.js +86 -0
- package/src/sam/decision/questions.js +120 -0
- package/src/sam/decision/receipt.js +148 -0
- package/src/sam/decision/state.js +117 -0
- package/src/sam/decision/types.js +22 -0
- package/src/sam/decision/validate.js +200 -0
- package/src/sam/define.js +51 -0
- package/src/sam/index.js +65 -0
- package/src/sam/operations/brand-scan.js +62 -0
- package/src/sam/operations/cad-blender-inspect.js +36 -0
- package/src/sam/operations/codebaseindex-ingest.js +49 -0
- package/src/sam/operations/decision-evaluate.js +59 -0
- package/src/sam/operations/planning-astar.js +77 -0
- package/src/sam/operations/planning-goap.js +60 -0
- package/src/sam/operations/repository-inspect.js +72 -0
- package/src/sam/operations/security-scan.js +33 -0
- package/src/sam/operations/terminal-exec.js +29 -0
- package/src/sam/planning/astar.js +311 -0
- package/src/sam/planning/goap.js +177 -0
- package/src/sam/planning/index.js +21 -0
- package/src/sam/planning/state.js +84 -0
- package/src/sam/registry.js +48 -0
- package/src/sam/result.js +77 -0
- package/src/sam/seed.js +44 -0
- package/src/sam/types.js +91 -0
- package/src/security/local-vault.js +415 -0
- package/src/security/process.js +20 -4
- package/src/skills/catalog.js +64 -0
- package/src/skills/content-resolver.js +124 -0
- package/src/skills/hosted-store.js +37 -0
- package/src/skills/index.js +29 -64
- package/src/skills/interaction.js +102 -0
- package/src/skills/local-store.js +228 -0
- package/src/skills/manifest.js +104 -0
- package/src/skills/metrics.js +31 -0
- package/src/skills/registry.js +184 -0
- package/src/skills/runtime.js +287 -0
- package/src/skills/slash.js +44 -0
- 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 +96 -96
- 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/api-key-env-whoami.test.mjs +129 -0
- package/test/cli/codebaseindex-plan-ux.test.mjs +37 -0
- package/test/cli/eval-live.test.mjs +219 -0
- package/test/cli/go.test.mjs +128 -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/skill-npm-and-env.test.mjs +52 -0
- package/test/cli/status-actions.test.mjs +88 -0
- package/test/cli/wireframes-go-registry.test.mjs +139 -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/build-source-identity.test.mjs +31 -0
- package/test/go/cloudflare-probe.test.mjs +317 -0
- package/test/go/distribution.test.mjs +28 -0
- package/test/integration/ai-access-onboarding.test.mjs +47 -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 +5 -1
- package/test/integration/cms-site-tenancy-contract.test.mjs +256 -0
- package/test/integration/codebaseindex-ingest.test.mjs +166 -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/icon-registry.test.mjs +67 -0
- package/test/integration/ingest-discover-models.test.mjs +30 -0
- package/test/integration/install-script.test.mjs +110 -0
- package/test/integration/inventory-core.test.mjs +53 -0
- package/test/integration/local-fs.test.mjs +113 -0
- package/test/integration/plugins-cloudflare.integration.test.mjs +28 -0
- package/test/integration/provider-env-cli.test.mjs +3 -2
- package/test/integration/runtime-migrations.test.mjs +6 -1
- package/test/integration/runtime-status.integration.test.mjs +211 -0
- package/test/integration/sam-activity-recovery.test.mjs +147 -0
- package/test/integration/sam-decision.test.mjs +584 -0
- package/test/integration/sam-kernel.test.mjs +99 -0
- package/test/integration/sam-planning-astar.test.mjs +279 -0
- package/test/integration/scaffold-cloudflare.test.mjs +46 -0
- package/test/integration/skill-runtime.test.mjs +240 -0
- package/test/integration/storage-architecture.test.mjs +154 -0
- package/test/integration/store-discovery.test.mjs +44 -0
- package/test/integration/studio-fs-pty-e2e.test.mjs +294 -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 +172 -11
- 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 +151 -6
- 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({
|
|
@@ -136,47 +220,77 @@ export async function handleCloudflareConnectionRequest(request, env) {
|
|
|
136
220
|
state,
|
|
137
221
|
codeChallenge: challenge,
|
|
138
222
|
});
|
|
223
|
+
// Browser navigation → 302 to Cloudflare. XHR/fetch (Integrations UI) → JSON.
|
|
224
|
+
const accept = String(request.headers.get('accept') || '');
|
|
225
|
+
const mode = String(request.headers.get('sec-fetch-mode') || '');
|
|
226
|
+
const wantsJson = accept.includes('application/json')
|
|
227
|
+
|| mode === 'cors'
|
|
228
|
+
|| request.headers.get('x-agentsam-oauth') === 'json';
|
|
229
|
+
if (!wantsJson) {
|
|
230
|
+
return Response.redirect(authorize, 302);
|
|
231
|
+
}
|
|
139
232
|
return json({ ok: true, authorize_url: authorize, callback: CLOUDFLARE_CALLBACK_PATH });
|
|
140
233
|
}
|
|
141
234
|
|
|
142
235
|
if (url.pathname === CLOUDFLARE_CALLBACK_PATH && request.method === 'GET') {
|
|
143
236
|
const code = url.searchParams.get('code') || '';
|
|
144
237
|
const state = url.searchParams.get('state') || '';
|
|
238
|
+
const providerError = url.searchParams.get('error') || '';
|
|
145
239
|
let stored = null;
|
|
146
240
|
if (env.DB) {
|
|
147
241
|
stored = await env.DB.prepare(
|
|
148
|
-
`SELECT owner_id, code_verifier
|
|
242
|
+
`SELECT owner_id, code_verifier, created_at, return_to
|
|
243
|
+
FROM agentsam_cloudflare_oauth_state WHERE state = ?`,
|
|
149
244
|
).bind(state).first();
|
|
150
245
|
} else if (env.oauthState instanceof Map) {
|
|
151
246
|
stored = env.oauthState.get(state);
|
|
152
|
-
if (stored) stored = { owner_id: stored.ownerId, code_verifier: stored.verifier };
|
|
247
|
+
if (stored) stored = { owner_id: stored.ownerId, code_verifier: stored.verifier, return_to: stored.returnTo || '' };
|
|
153
248
|
}
|
|
154
249
|
if (!stored) {
|
|
250
|
+
// A callback without a one-time PKCE state is forged or expired. Keep
|
|
251
|
+
// this as an explicit 403 instead of redirecting into a misleading UI.
|
|
155
252
|
return json({ ok: false, error: 'cloudflare_connection_forbidden' }, 403);
|
|
156
253
|
}
|
|
157
254
|
if (!ownerId) ownerId = stored.owner_id;
|
|
158
255
|
if (stored.owner_id !== ownerId) {
|
|
159
|
-
return
|
|
256
|
+
return settingsRedirect(url, 'error', 'cloudflare_connection_forbidden', stored.return_to || '');
|
|
257
|
+
}
|
|
258
|
+
const createdAt = Number(stored.created_at || 0);
|
|
259
|
+
const now = Math.floor(Date.now() / 1000);
|
|
260
|
+
if (createdAt && now - createdAt > 10 * 60) {
|
|
261
|
+
await deleteOAuthState(env, state);
|
|
262
|
+
return settingsRedirect(url, 'error', 'oauth_state_expired', stored.return_to || '');
|
|
160
263
|
}
|
|
264
|
+
await deleteOAuthState(env, state);
|
|
265
|
+
if (providerError) {
|
|
266
|
+
return settingsRedirect(url, 'error', providerError, stored.return_to || '');
|
|
267
|
+
}
|
|
268
|
+
if (!code) {
|
|
269
|
+
return settingsRedirect(url, 'error', 'authorization_code_missing', stored.return_to || '');
|
|
270
|
+
}
|
|
271
|
+
// This is Cloudflare's public PKCE client (Token Authentication Method:
|
|
272
|
+
// None). Do not add client_secret, even if an obsolete Worker binding is
|
|
273
|
+
// present; a mixed-auth exchange is rejected by Cloudflare.
|
|
274
|
+
const tokenParams = {
|
|
275
|
+
grant_type: 'authorization_code',
|
|
276
|
+
code,
|
|
277
|
+
redirect_uri: `${url.origin}${CLOUDFLARE_CALLBACK_PATH}`,
|
|
278
|
+
client_id: String(env.CLOUDFLARE_OAUTH_CLIENT_ID),
|
|
279
|
+
code_verifier: stored.code_verifier,
|
|
280
|
+
};
|
|
161
281
|
const tokenRes = await fetch(CLOUDFLARE_OAUTH_TOKEN_URL, {
|
|
162
282
|
method: 'POST',
|
|
163
283
|
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
|
-
}),
|
|
284
|
+
body: new URLSearchParams(tokenParams),
|
|
172
285
|
});
|
|
173
286
|
if (!tokenRes.ok) {
|
|
174
|
-
|
|
287
|
+
console.error('cloudflare_token_exchange_failed', tokenRes.status);
|
|
288
|
+
return settingsRedirect(url, 'error', 'token_exchange_failed', stored.return_to || '');
|
|
175
289
|
}
|
|
176
290
|
const tokens = await tokenRes.json();
|
|
177
291
|
const connectionId = `cfconn_${crypto.randomUUID().replace(/-/g, '').slice(0, 16)}`;
|
|
178
292
|
if (tokens.access_token && !vaultConfigured(env)) {
|
|
179
|
-
return
|
|
293
|
+
return settingsRedirect(url, 'error', 'vault_unavailable', stored.return_to || '');
|
|
180
294
|
}
|
|
181
295
|
const aad = `cloudflare-connection:${ownerId}`;
|
|
182
296
|
let accessEnc = null;
|
|
@@ -185,10 +299,16 @@ export async function handleCloudflareConnectionRequest(request, env) {
|
|
|
185
299
|
accessEnc = await sealToken(env, tokens.access_token, aad);
|
|
186
300
|
refreshEnc = await sealToken(env, tokens.refresh_token, aad);
|
|
187
301
|
} catch (err) {
|
|
188
|
-
return
|
|
302
|
+
return settingsRedirect(url, 'error', err.code || 'vault_unavailable', stored.return_to || '');
|
|
189
303
|
}
|
|
190
304
|
if (env.DB) {
|
|
191
|
-
|
|
305
|
+
const removePrevious = env.DB.prepare(
|
|
306
|
+
`UPDATE agentsam_cloudflare_connections
|
|
307
|
+
SET status = 'superseded', access_token_encrypted = NULL,
|
|
308
|
+
refresh_token_encrypted = NULL, updated_at = unixepoch()
|
|
309
|
+
WHERE owner_id = ? AND status = 'connected'`,
|
|
310
|
+
).bind(ownerId);
|
|
311
|
+
const insertConnection = env.DB.prepare(
|
|
192
312
|
`INSERT INTO agentsam_cloudflare_connections (
|
|
193
313
|
connection_id, owner_id, cloudflare_account_id, scopes, status,
|
|
194
314
|
access_token_encrypted, refresh_token_encrypted, created_at, updated_at, expires_at
|
|
@@ -201,22 +321,52 @@ export async function handleCloudflareConnectionRequest(request, env) {
|
|
|
201
321
|
accessEnc,
|
|
202
322
|
refreshEnc,
|
|
203
323
|
tokens.expires_in ? Math.floor(Date.now() / 1000) + Number(tokens.expires_in) : null,
|
|
204
|
-
)
|
|
324
|
+
);
|
|
325
|
+
if (typeof env.DB.batch === 'function') {
|
|
326
|
+
await env.DB.batch([removePrevious, insertConnection]);
|
|
327
|
+
} else {
|
|
328
|
+
await removePrevious.run();
|
|
329
|
+
await insertConnection.run();
|
|
330
|
+
}
|
|
331
|
+
await seedKnownCloudflareResources(env, ownerId, connectionId, tokens.account_id || null);
|
|
205
332
|
}
|
|
206
|
-
return
|
|
333
|
+
return settingsRedirect(url, 'connected', '', stored.return_to || '');
|
|
207
334
|
}
|
|
208
335
|
|
|
209
336
|
if (url.pathname === '/api/connections/cloudflare/disconnect' && request.method === 'POST') {
|
|
337
|
+
let providerRevoked = false;
|
|
210
338
|
if (env.DB) {
|
|
211
339
|
const row = await env.DB.prepare(
|
|
212
|
-
`SELECT connection_id, owner_id
|
|
340
|
+
`SELECT connection_id, owner_id, access_token_encrypted
|
|
341
|
+
FROM agentsam_cloudflare_connections
|
|
342
|
+
WHERE owner_id = ? AND status = 'connected'
|
|
343
|
+
ORDER BY updated_at DESC LIMIT 1`,
|
|
213
344
|
).bind(ownerId).first();
|
|
214
345
|
if (row) {
|
|
215
346
|
assertConnectionOwner({ ownerId: row.owner_id, connectionId: row.connection_id }, ownerId);
|
|
216
|
-
|
|
347
|
+
if (row.access_token_encrypted) {
|
|
348
|
+
try {
|
|
349
|
+
const token = await decryptSecret(env, row.access_token_encrypted, `cloudflare-connection:${ownerId}`);
|
|
350
|
+
const revokeParams = new URLSearchParams({ token, client_id: String(env.CLOUDFLARE_OAUTH_CLIENT_ID) });
|
|
351
|
+
const revokeResponse = await fetch(CLOUDFLARE_OAUTH_REVOKE_URL, {
|
|
352
|
+
method: 'POST',
|
|
353
|
+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
354
|
+
body: revokeParams,
|
|
355
|
+
});
|
|
356
|
+
providerRevoked = revokeResponse.ok;
|
|
357
|
+
} catch (error) {
|
|
358
|
+
console.error('cloudflare_token_revoke_failed', String(error?.message || error));
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
await env.DB.prepare(`
|
|
362
|
+
UPDATE agentsam_cloudflare_connections
|
|
363
|
+
SET status = 'revoked', access_token_encrypted = NULL,
|
|
364
|
+
refresh_token_encrypted = NULL, expires_at = unixepoch(), updated_at = unixepoch()
|
|
365
|
+
WHERE connection_id = ? AND owner_id = ?
|
|
366
|
+
`).bind(row.connection_id, ownerId).run();
|
|
217
367
|
}
|
|
218
368
|
}
|
|
219
|
-
return json({ ok: true, status: 'not_configured' });
|
|
369
|
+
return json({ ok: true, status: 'not_configured', provider_revoked: providerRevoked });
|
|
220
370
|
}
|
|
221
371
|
|
|
222
372
|
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,139 @@ 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: {
|
|
68
|
+
authorization: 'Bearer fixture',
|
|
69
|
+
accept: 'application/json',
|
|
70
|
+
},
|
|
71
|
+
}),
|
|
72
|
+
{
|
|
73
|
+
DB,
|
|
74
|
+
fixtureSessions: new Map([['fixture', 'user_123']]),
|
|
75
|
+
CLOUDFLARE_OAUTH_CLIENT_ID: 'real-client-id',
|
|
76
|
+
},
|
|
77
|
+
);
|
|
78
|
+
assert.equal(response.status, 200);
|
|
79
|
+
assert.equal(
|
|
80
|
+
calls.some((call) => call.sql.includes('DELETE FROM agentsam_cloudflare_oauth_state WHERE created_at < unixepoch() - 600')),
|
|
81
|
+
true,
|
|
82
|
+
);
|
|
83
|
+
const stateInsert = calls.find((call) => call.sql.includes('INSERT INTO agentsam_cloudflare_oauth_state'));
|
|
84
|
+
assert.ok(stateInsert);
|
|
85
|
+
assert.equal(stateInsert.args.at(-1), null);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('redirects browser starts to Cloudflare authorization', async () => {
|
|
89
|
+
const oauthState = new Map();
|
|
90
|
+
const response = await handleCloudflareConnectionRequest(
|
|
91
|
+
new Request('https://agentsam.example/api/connections/cloudflare/start', {
|
|
92
|
+
headers: { authorization: 'Bearer fixture' },
|
|
93
|
+
}),
|
|
94
|
+
{
|
|
95
|
+
fixtureSessions: new Map([['fixture', 'user_123']]),
|
|
96
|
+
oauthState,
|
|
97
|
+
CLOUDFLARE_OAUTH_CLIENT_ID: 'real-client-id',
|
|
98
|
+
},
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
assert.equal(response.status, 302);
|
|
102
|
+
const location = new URL(response.headers.get('location'));
|
|
103
|
+
assert.equal(location.origin, 'https://dash.cloudflare.com');
|
|
104
|
+
assert.equal(location.pathname, '/oauth2/auth');
|
|
105
|
+
assert.equal(location.searchParams.get('client_id'), 'real-client-id');
|
|
106
|
+
assert.equal(location.searchParams.get('redirect_uri'), 'https://agentsam.example/api/connections/cloudflare/callback');
|
|
107
|
+
assert.equal(oauthState.size, 1);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('consumes callback state and stores only encrypted OAuth tokens', async () => {
|
|
111
|
+
const now = Math.floor(Date.now() / 1000);
|
|
112
|
+
const calls = [];
|
|
113
|
+
const statements = [];
|
|
114
|
+
const DB = {
|
|
115
|
+
prepare(sql) {
|
|
116
|
+
const statement = {
|
|
117
|
+
sql,
|
|
118
|
+
args: [],
|
|
119
|
+
bind(...args) {
|
|
120
|
+
this.args = args;
|
|
121
|
+
return this;
|
|
122
|
+
},
|
|
123
|
+
async first() {
|
|
124
|
+
if (sql.includes('agentsam_cloudflare_oauth_state')) {
|
|
125
|
+
return { owner_id: 'user_123', code_verifier: 'verifier', created_at: now };
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
},
|
|
129
|
+
async run() {
|
|
130
|
+
calls.push({ sql, args: this.args });
|
|
131
|
+
return { success: true };
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
statements.push(statement);
|
|
135
|
+
return statement;
|
|
136
|
+
},
|
|
137
|
+
async batch(batchStatements) {
|
|
138
|
+
for (const statement of batchStatements) await statement.run();
|
|
139
|
+
return batchStatements.map(() => ({ success: true }));
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
const originalFetch = globalThis.fetch;
|
|
143
|
+
globalThis.fetch = async (_input, init) => {
|
|
144
|
+
const body = new URLSearchParams(init.body);
|
|
145
|
+
assert.equal(body.get('client_secret'), null);
|
|
146
|
+
return new Response(JSON.stringify({
|
|
147
|
+
access_token: 'access-plaintext',
|
|
148
|
+
refresh_token: 'refresh-plaintext',
|
|
149
|
+
account_id: 'account_123',
|
|
150
|
+
scope: 'd1.read workers-scripts.write',
|
|
151
|
+
expires_in: 3600,
|
|
152
|
+
}), { status: 200, headers: { 'content-type': 'application/json' } });
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
const response = await handleCloudflareConnectionRequest(
|
|
157
|
+
new Request('https://agentsam.example/api/connections/cloudflare/callback?code=code_123&state=state_123'),
|
|
158
|
+
{
|
|
159
|
+
DB,
|
|
160
|
+
CLOUDFLARE_OAUTH_CLIENT_ID: 'real-client-id',
|
|
161
|
+
CLOUDFLARE_OAUTH_CLIENT_SECRET: 'obsolete-secret-must-not-be-sent',
|
|
162
|
+
VAULT_MASTER_KEY: '01234567890123456789012345678901',
|
|
163
|
+
},
|
|
164
|
+
);
|
|
165
|
+
assert.equal(response.status, 302);
|
|
166
|
+
assert.equal(
|
|
167
|
+
response.headers.get('location'),
|
|
168
|
+
'https://agentsam.example/settings/integrations?connection=cloudflare&result=connected',
|
|
169
|
+
);
|
|
170
|
+
assert.equal(calls.some((call) => call.sql.includes('DELETE FROM agentsam_cloudflare_oauth_state')), true);
|
|
171
|
+
const insert = calls.find((call) => call.sql.includes('INSERT INTO agentsam_cloudflare_connections'));
|
|
172
|
+
assert.ok(insert);
|
|
173
|
+
assert.notEqual(insert.args[4], 'access-plaintext');
|
|
174
|
+
assert.notEqual(insert.args[5], 'refresh-plaintext');
|
|
175
|
+
} finally {
|
|
176
|
+
globalThis.fetch = originalFetch;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
44
179
|
});
|
|
@@ -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
|
+
});
|