@inneranimalmedia/agentsam-sdk 2.6.5 → 2.6.7
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 +29 -0
- package/apps/README.md +5 -0
- package/apps/cad-creator/README.md +4 -4
- package/apps/cad-creator/shared/cad/package.json +1 -1
- package/apps/client-cms-editor/AGENTS.md +12 -7
- package/apps/client-cms-editor/README.md +76 -48
- package/apps/client-cms-editor/agentsam.app.json +26 -9
- package/apps/client-cms-editor/backend/package.json +20 -3
- package/apps/client-cms-editor/backend/src/api/client.ts +134 -101
- package/apps/client-cms-editor/backend/src/index.ts +1 -1
- package/apps/client-cms-editor/backend/src/model.ts +11 -115
- package/apps/client-cms-editor/backend/src/preview/bridge.ts +1 -1
- package/apps/client-cms-editor/backend/tsconfig.json +6 -1
- package/apps/client-cms-editor/bin/agentsam-cms.js +262 -0
- package/apps/client-cms-editor/bin/agentsam-cms.mjs +2 -228
- package/apps/client-cms-editor/frontend/package.json +16 -7
- package/apps/client-cms-editor/frontend/src/AgentSamDrawer.tsx +9 -41
- package/apps/client-cms-editor/frontend/src/CmsAgentSurface.tsx +19 -174
- package/apps/client-cms-editor/frontend/src/adapters/heuristic.ts +29 -0
- package/apps/client-cms-editor/frontend/src/adapters/http.ts +628 -0
- package/apps/client-cms-editor/frontend/src/adapters/memory.ts +510 -0
- package/apps/client-cms-editor/frontend/src/editor/CmsEditor.tsx +213 -0
- package/apps/client-cms-editor/frontend/src/editor/CmsEditorProvider.tsx +20 -0
- package/apps/client-cms-editor/frontend/src/editor/canvas/PreviewCanvas.tsx +53 -0
- package/apps/client-cms-editor/frontend/src/{CmsEditor.tsx → editor/legacy/CmsEditorPrototype.tsx} +52 -23
- package/apps/client-cms-editor/frontend/src/editor/useCmsEditorController.ts +218 -0
- package/apps/client-cms-editor/frontend/src/index.ts +19 -5
- package/apps/client-cms-editor/frontend/src/lib/agent-host.ts +24 -0
- package/apps/client-cms-editor/frontend/src/main.tsx +82 -8
- package/apps/client-cms-editor/frontend/src/mount.tsx +92 -30
- package/apps/client-cms-editor/frontend/src/styles/agentsam-drawer.css +1 -1
- package/apps/client-cms-editor/frontend/src/styles/cmsShell.css +8 -8
- package/apps/client-cms-editor/frontend/src/styles/studio.css +55 -3
- package/apps/client-cms-editor/frontend/tsconfig.json +12 -1
- package/apps/client-cms-editor/frontend/vite.config.ts +12 -0
- package/apps/client-cms-editor/package-lock.json +973 -134
- package/apps/client-cms-editor/package.json +118 -6
- package/apps/client-cms-editor/reference/harvest/HARVEST_RECEIPT.json +201 -0
- package/apps/client-cms-editor/reference/harvest/PROVENANCE_HISTORY.txt +10 -0
- package/apps/client-cms-editor/reference/harvest/README.md +8 -0
- package/apps/client-cms-editor/reference/harvest/plans/ARCHIVE-INTAKE.md +135 -0
- package/apps/client-cms-editor/reference/harvest/plans/CHATGPT-IDENTITY-HARVEST.md +83 -0
- package/apps/client-cms-editor/reference/harvest/plans/CMS-EDITOR-HARVEST.md +166 -0
- package/apps/client-cms-editor/reference/harvest/plans/HARVEST-INDEX.md +196 -0
- package/apps/client-cms-editor/reference/harvest/plans/INNERANIMALS-CONTENT-001.md +137 -0
- package/apps/client-cms-editor/reference/harvest/plans/NO-IMPLICIT-SIDE-EFFECTS.md +87 -0
- package/apps/client-cms-editor/reference/harvest/plans/STOREFRONT-SURFACE-MAP.md +140 -0
- package/apps/client-cms-editor/reference/harvest/plans/THEME-INNERANIMALS-HARVEST.md +137 -0
- package/apps/client-cms-editor/reference/harvest/plans/TOOLING-LAB.md +63 -0
- package/apps/client-cms-editor/reference/harvest/plans/harvest-manifest.json +97 -0
- package/apps/client-cms-editor/reference/harvest/plans/local-cms-harvest-schema.sql +328 -0
- package/apps/client-cms-editor/shared/cms/package.json +17 -7
- package/apps/client-cms-editor/shared/cms/src/adapter.ts +204 -0
- package/apps/client-cms-editor/shared/cms/src/agent-context.ts +7 -5
- package/apps/client-cms-editor/shared/cms/src/editor-types.ts +32 -0
- package/apps/client-cms-editor/shared/cms/src/host.ts +82 -0
- package/apps/client-cms-editor/shared/cms/src/index.ts +4 -0
- package/apps/client-cms-editor/shared/cms/src/map.ts +115 -0
- package/apps/client-cms-editor/shared/cms/src/starter-pack.ts +158 -0
- package/contracts/source-types.v1.json +353 -0
- package/docs/CMS_CONTEXTUAL_COMPOSER.md +1 -1
- package/docs/PRODUCT_LIFECYCLE.md +566 -0
- package/docs/THEME_REFINERY.md +2 -2
- package/docs/architecture/AGENTSAM_RUNTIME_PROTOCOL.md +40 -20
- package/docs/content-studio/REVISION_GATE_2026-09-27.md +1 -1
- package/docs/plans/LOCAL_STUDIO_DESKTOP_RELEASE_2026-09-29.md +150 -0
- package/migrations/d1/0017_identity_native_oauth.sql +21 -0
- package/native/agentsam-machine/Cargo.lock +426 -0
- package/native/agentsam-machine/Cargo.toml +9 -0
- package/native/agentsam-machine/cli/Cargo.toml +14 -0
- package/native/agentsam-machine/cli/src/main.rs +77 -0
- package/native/agentsam-machine/core/Cargo.toml +15 -0
- package/native/agentsam-machine/core/src/assets.rs +790 -0
- package/native/agentsam-machine/core/src/bound.rs +298 -0
- package/native/agentsam-machine/core/src/enrich.rs +706 -0
- package/native/agentsam-machine/core/src/frontend.rs +442 -0
- package/native/agentsam-machine/core/src/lib.rs +1086 -0
- package/native/agentsam-machine/core/src/liquid.rs +528 -0
- package/native/agentsam-machine/core/src/source_types.rs +78 -0
- package/package.json +51 -21
- package/packages/agentsam-brand/README.md +1 -1
- package/packages/agentsam-brand/package.json +4 -4
- package/packages/agentsam-brand/src/index.js +1 -1
- package/packages/agentsam-contracts/package.json +13 -3
- package/packages/agentsam-contracts/src/tools.ts +22 -0
- package/packages/agentsam-errors/package.json +13 -3
- package/packages/agentsam-knowledge/package.json +18 -4
- package/packages/agentsam-knowledge/src/autorag/index.js +10 -3
- package/packages/agentsam-knowledge/src/backends/index.js +33 -1
- package/packages/agentsam-knowledge/test/autorag.test.mjs +60 -1
- package/packages/agentsam-nav/package.json +24 -6
- package/packages/agentsam-queue-control/README.md +1 -1
- package/packages/agentsam-queue-control/package.json +7 -2
- package/packages/agentsam-rapid-rust/src/main.rs +1 -1
- package/packages/agentsam-repository/package.json +13 -3
- package/packages/agentsam-repository/src/source-types.js +8 -0
- package/packages/agentsam-vault/package.json +14 -4
- package/packages/agentsam-workbench/package.json +15 -4
- package/packages/agentsam-workbench/src/agent/ToolPermissionRequest.tsx +94 -0
- package/packages/agentsam-workbench/src/agent/index.ts +2 -0
- package/packages/agentsam-workbench/src/agent/tool-permission.css +134 -0
- package/packages/connectors/cloudflare/package.json +13 -3
- package/packages/connectors/cloudflare/src/api-client.js +3 -2
- package/packages/connectors/cloudflare/src/families/vectorize.js +127 -0
- package/packages/connectors/cloudflare/src/index.js +1 -0
- package/packages/heuristic-theme/README.md +2 -2
- package/packages/heuristic-theme/package.json +8 -3
- package/packages/heuristic-theme/src/registry.js +2 -2
- package/packages/heuristic-theme/src/theme.js +1 -1
- package/packages/heuristic-theme/test/theme.test.mjs +1 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +1 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +27 -7
- package/packages/identity/README.md +2 -2
- package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +18 -15
- package/packages/identity/migrations/apply-portable.js +109 -0
- package/packages/identity/migrations/sqlite/004_identity_oauth_consent_catalog.sql +1 -1
- package/packages/identity/migrations/sqlite/005_identity_company_native.sql +52 -0
- package/packages/identity/package.json +27 -6
- package/packages/identity/schema/agentsam.identity/manifest.json +101 -0
- package/packages/identity/scripts/local-identity-bridge.mjs +13 -7
- package/packages/identity/scripts/preview-auth-portal.mjs +6 -6
- package/packages/identity/src/adapters/cloudflare-d1/index.js +8 -401
- package/packages/identity/src/adapters/iam-compat/index.js +540 -0
- package/packages/identity/src/adapters/portable-d1/index.js +18 -0
- package/packages/identity/src/adapters/portable-store.js +479 -0
- package/packages/identity/src/adapters/sqlite/index.js +13 -312
- package/packages/identity/src/contracts/auth-config.js +0 -1
- package/packages/identity/src/contracts/identity-store.js +56 -5
- package/packages/identity/src/contracts/provider.js +1 -0
- package/packages/identity/src/contracts/sign-in-options.js +104 -0
- package/packages/identity/src/core/constants.js +1 -1
- package/packages/identity/src/core/session-policy.js +31 -0
- package/packages/identity/src/frontend/auth-portal/pages/login.html +6 -6
- package/packages/identity/src/frontend/auth-portal/pages/reset.html +5 -5
- package/packages/identity/src/frontend/auth-portal/pages/signup.html +5 -5
- package/packages/identity/src/frontend/auth-portal/shared/company-branding.js +1 -1
- package/packages/identity/src/frontend/auth-portal/shared/desktop-identity-bridge.js +6 -37
- package/packages/identity/src/index.js +28 -1
- package/packages/identity/src/migrations/README.md +23 -23
- package/packages/identity/src/oauth/README.md +1 -1
- package/packages/identity/src/oauth/credentials.js +10 -11
- package/packages/identity/src/oauth/google-desktop-exchange.js +195 -27
- package/packages/identity/src/oauth/iam-platform.js +21 -9
- package/packages/identity/src/oauth/native-handoff.js +136 -0
- package/packages/identity/src/providers/chatgpt/headers.js +65 -0
- package/packages/identity/src/providers/chatgpt/index.js +86 -0
- package/packages/identity/src/providers/chatgpt/mapper.js +43 -0
- package/packages/identity/src/providers/chatgpt/paths.js +45 -0
- package/packages/identity/src/providers/github/oauth.js +1 -2
- package/packages/identity/src/providers/github/profile.js +16 -2
- package/packages/identity/src/providers/index.js +11 -3
- package/packages/identity/src/server/identity-service.js +2 -1
- package/packages/identity/src/server/worker-router.js +71 -18
- package/packages/identity/tests/chatgpt-provider.test.mjs +75 -0
- package/packages/identity/tests/google-desktop-identity-login.test.mjs +210 -0
- package/packages/identity/tests/identity-init-scaffold.test.mjs +15 -4
- package/packages/identity/tests/lane1-identity-store-parity.test.mjs +527 -0
- package/packages/identity/tests/lane1-packed-consumer.test.mjs +175 -0
- package/packages/identity/tests/native-oauth-handoff.test.mjs +292 -0
- package/packages/identity/tests/oauth-credentials.test.mjs +4 -4
- package/packages/identity/tests/preview-auth-portal.test.mjs +4 -2
- package/packages/identity/tests/session-routes-policy.test.mjs +13 -1
- package/packages/identity/tests/worker-runtime-boundary.test.mjs +11 -0
- package/packages/providers/completeful/package.json +7 -2
- package/packages/theme-church-site/package.json +17 -6
- package/packages/theme-church-site/src/harvest.json +4 -2
- package/packages/theme-church-site/src/index.js +7 -3
- package/packages/theme-church-site/test/theme.test.mjs +4 -2
- package/packages/theme-companions-site/package.json +17 -6
- package/packages/theme-companions-site/src/harvest.json +4 -2
- package/packages/theme-companions-site/src/index.js +7 -3
- package/packages/theme-companions-site/test/theme.test.mjs +4 -2
- package/packages/theme-floors-site/package.json +17 -6
- package/packages/theme-floors-site/src/harvest.json +4 -2
- package/packages/theme-floors-site/src/index.js +7 -3
- package/packages/theme-floors-site/test/theme.test.mjs +4 -2
- package/packages/theme-fuelnfree-site/package.json +17 -6
- package/packages/theme-fuelnfree-site/src/harvest.json +4 -2
- package/packages/theme-fuelnfree-site/src/index.js +7 -3
- package/packages/theme-fuelnfree-site/test/theme.test.mjs +4 -2
- package/packages/theme-handyman-site/package.json +17 -6
- package/packages/theme-handyman-site/src/harvest.json +4 -2
- package/packages/theme-handyman-site/src/index.js +7 -3
- package/packages/theme-handyman-site/test/theme.test.mjs +4 -2
- package/packages/theme-insurance-site/package.json +17 -6
- package/packages/theme-insurance-site/src/harvest.json +4 -2
- package/packages/theme-insurance-site/src/index.js +7 -3
- package/packages/theme-insurance-site/test/theme.test.mjs +4 -2
- package/packages/theme-scenes/README.md +1 -1
- package/packages/theme-scenes/package.json +4 -3
- package/packages/theme-scenes/src/registry.js +187 -0
- package/packages/theme-shinshu-site/package.json +17 -6
- package/packages/theme-shinshu-site/src/harvest.json +4 -2
- package/packages/theme-shinshu-site/src/index.js +7 -3
- package/packages/theme-shinshu-site/test/theme.test.mjs +4 -2
- package/packages/work-graph/package.json +14 -4
- package/protocol/FILEMETA_V1.md +2 -2
- package/protocol/capabilities/manifest.json +1 -1
- package/protocol/database/agentsam.schema-pack.v1.schema.json +72 -0
- package/protocol/presets/catalog.json +2 -2
- package/protocol/theme-refinery/lineage-registry.json +105 -0
- package/protocol/theme-refinery/product-metadata.schema.json +21 -1
- package/skills/grok-auth/SKILL.md +110 -0
- package/skills/grok-auth/agentsam.skill.json +25 -0
- package/skills/grok-auth/references/grok-identity.md +64 -0
- package/skills/grok-auth/references/per-user-data.md +49 -0
- package/skills/grok-auth/references/prewired-and-env.md +54 -0
- package/skills/grok-auth/references/session-ui.md +133 -0
- package/skills/grok-auth/references/sign-in-methods.md +55 -0
- package/skills/grok-auth/references/wiring.md +71 -0
- package/skills/grok-building-games/SKILL.md +213 -0
- package/skills/grok-building-games/agentsam.skill.json +25 -0
- package/skills/grok-building-games/references/3d-libs.md +64 -0
- package/skills/grok-building-games/references/ai-pathfinding.md +122 -0
- package/skills/grok-building-games/references/audio.md +129 -0
- package/skills/grok-building-games/references/babylon.md +202 -0
- package/skills/grok-building-games/references/collision-physics.md +122 -0
- package/skills/grok-building-games/references/ecs-architecture.md +111 -0
- package/skills/grok-building-games/references/game-feel-juice.md +110 -0
- package/skills/grok-building-games/references/genres/board-card-chess.md +89 -0
- package/skills/grok-building-games/references/genres/endless-runner.md +83 -0
- package/skills/grok-building-games/references/genres/fps.md +105 -0
- package/skills/grok-building-games/references/genres/platformer-2d.md +97 -0
- package/skills/grok-building-games/references/genres/puzzle-match3-tetris.md +131 -0
- package/skills/grok-building-games/references/genres/racing-kart.md +106 -0
- package/skills/grok-building-games/references/genres/topdown-twin-stick.md +97 -0
- package/skills/grok-building-games/references/genres/tower-defense.md +84 -0
- package/skills/grok-building-games/references/genres/voxel-minecraft.md +89 -0
- package/skills/grok-building-games/references/input.md +139 -0
- package/skills/grok-building-games/references/phaser.md +277 -0
- package/skills/grok-building-games/references/procedural-generation.md +141 -0
- package/skills/grok-building-games/references/save-persistence.md +108 -0
- package/skills/grok-building-games/references/threejs-foundational.md +148 -0
- package/skills/grok-controls/SKILL.md +274 -0
- package/skills/grok-controls/agentsam.skill.json +25 -0
- package/skills/grok-design-ui/SKILL.md +122 -0
- package/skills/grok-design-ui/agentsam.skill.json +25 -0
- package/skills/grok-design-ui/references/animations.md +379 -0
- package/skills/grok-design-ui/references/performance.md +88 -0
- package/skills/grok-design-ui/references/refined-ui.md +384 -0
- package/skills/grok-design-ui/references/surfaces.md +247 -0
- package/skills/grok-design-ui/references/typography.md +123 -0
- package/skills/grok-game-animation-frames/SKILL.md +84 -0
- package/skills/grok-game-animation-frames/agentsam.skill.json +25 -0
- package/skills/grok-game-asset-core/SKILL.md +69 -0
- package/skills/grok-game-asset-core/agentsam.skill.json +25 -0
- package/skills/grok-game-character-consistency/SKILL.md +69 -0
- package/skills/grok-game-character-consistency/agentsam.skill.json +25 -0
- package/skills/grok-game-tilesets/SKILL.md +65 -0
- package/skills/grok-game-tilesets/agentsam.skill.json +25 -0
- package/skills/grok-game-ui-icons/SKILL.md +56 -0
- package/skills/grok-game-ui-icons/agentsam.skill.json +25 -0
- package/skills/grok-generate2dmap/LICENSE +21 -0
- package/skills/grok-generate2dmap/SKILL.md +120 -0
- package/skills/grok-generate2dmap/SOURCE.md +6 -0
- package/skills/grok-generate2dmap/agentsam.skill.json +25 -0
- package/skills/grok-generate2dmap/references/deliverables.md +101 -0
- package/skills/grok-generate2dmap/references/layered-map-contract.md +209 -0
- package/skills/grok-generate2dmap/references/map-strategies.md +341 -0
- package/skills/grok-generate2dmap/references/object-production-gate.md +24 -0
- package/skills/grok-generate2dmap/references/pipeline.md +149 -0
- package/skills/grok-generate2dmap/references/prop-pack-contract.md +174 -0
- package/skills/grok-generate2dmap/references/side-scroll-stages.md +29 -0
- package/skills/grok-generate2dmap/scripts/compose_layered_preview.py +157 -0
- package/skills/grok-generate2dmap/scripts/extract_prop_pack.py +369 -0
- package/skills/grok-generate2dsprite/LICENSE +21 -0
- package/skills/grok-generate2dsprite/SKILL.md +313 -0
- package/skills/grok-generate2dsprite/SOURCE.md +6 -0
- package/skills/grok-generate2dsprite/agentsam.skill.json +25 -0
- package/skills/grok-generate2dsprite/references/modes.md +124 -0
- package/skills/grok-generate2dsprite/references/prompt-rules.md +315 -0
- package/skills/grok-generate2dsprite/scripts/generate2dsprite.py +1031 -0
- package/skills/grok-generate2dsprite/scripts/make_layout_guide.py +109 -0
- package/skills/grok-imagine/SKILL.md +201 -0
- package/skills/grok-imagine/agentsam.skill.json +25 -0
- package/skills/grok-multiplayer-p2p/SKILL.md +111 -0
- package/skills/grok-multiplayer-p2p/agentsam.skill.json +25 -0
- package/skills/grok-multiplayer-p2p/references/react-binding.md +144 -0
- package/skills/grok-multiplayer-p2p/references/signaling-relay.md +269 -0
- package/skills/grok-neon/SKILL.md +157 -0
- package/skills/grok-neon/agentsam.skill.json +25 -0
- package/skills/grok-og/SKILL.md +102 -0
- package/skills/grok-og/agentsam.skill.json +25 -0
- package/skills/grok-og/references/brand-pass.md +53 -0
- package/skills/grok-og/references/custom-card.md +107 -0
- package/skills/grok-og/references/favicon-and-icons.md +48 -0
- package/skills/grok-og/references/og-type-contract.md +18 -0
- package/skills/grok-og/references/placeholder-card.md +21 -0
- package/skills/grok-og/references/x-banner.md +41 -0
- package/skills/grok-threejs/SKILL.md +67 -0
- package/skills/grok-threejs/agentsam.skill.json +25 -0
- package/skills/grok-threejs/references/llms-full.txt +2780 -0
- package/skills/grok-video2dsprite/LICENSE +21 -0
- package/skills/grok-video2dsprite/SKILL.md +236 -0
- package/skills/grok-video2dsprite/SOURCE.md +6 -0
- package/skills/grok-video2dsprite/agentsam.skill.json +25 -0
- package/skills/grok-video2dsprite/references/pipeline.md +90 -0
- package/skills/grok-video2dsprite/references/prompt-rules.md +63 -0
- package/skills/grok-video2dsprite/scripts/video2dsprite.py +490 -0
- package/skills/grok-xai-api/SKILL.md +152 -0
- package/skills/grok-xai-api/agentsam.skill.json +25 -0
- package/src/cli/command-catalog.js +46 -4
- package/src/cli/dispatch.js +1 -0
- package/src/cli.js +10 -0
- package/src/cloudflare/runtime-status.js +2 -1
- package/src/commands/autorag.js +67 -13
- package/src/commands/cheat-sheet.js +29 -4
- package/src/commands/codebaseindex.js +45 -2
- package/src/commands/knowledge.js +59 -2
- package/src/commands/machine-binary.js +103 -0
- package/src/commands/machine.js +137 -0
- package/src/commands/security.js +67 -4
- package/src/commands/setup.js +33 -16
- package/src/commands/status.js +8 -1
- package/src/features/resolve.js +1 -0
- package/src/knowledge/engine.js +21 -2
- package/src/knowledge/runtime-discovery.js +127 -0
- package/src/lib/identity-scaffold.js +53 -13
- package/src/lib/setup/recipes.js +1 -1
- package/src/models/discovery.js +40 -22
- package/src/models/inventory-core.d.ts +105 -0
- package/src/models/inventory-core.js +54 -6
- package/src/security/logs.js +3 -0
- package/src/ui/cli/help.js +41 -0
- package/test/apps-scaffold-contract.test.mjs +3 -2
- package/test/cli/api-key-env-whoami.test.mjs +2 -2
- package/test/cli/catalog-authority.test.mjs +64 -0
- package/test/cli/machine-command.test.mjs +34 -0
- package/test/fixtures/project-authority/customer-app/.agentsam/app.json +5 -0
- package/test/fixtures/project-authority/customer-app/apps/my-product/index.ts +1 -0
- package/test/fixtures/project-authority/customer-app/wrangler.toml +17 -0
- package/test/integration/autorag-project-authority.integration.test.mjs +51 -0
- package/test/integration/autorag-runtime-discovery.test.mjs +107 -0
- package/test/integration/cms-app-scaffold.test.mjs +37 -31
- package/test/integration/cms-site-tenancy-contract.test.mjs +28 -17
- package/test/integration/codebaseindex-ingest.test.mjs +41 -0
- package/test/integration/database-hosted-honesty.test.mjs +49 -0
- package/test/integration/desktop-keychain-boundary.test.mjs +45 -0
- package/test/integration/hosted-work-host-authority.test.mjs +47 -0
- package/test/integration/inventory-eligibility.test.mjs +59 -0
- package/test/integration/local-provider-bridge.test.mjs +65 -0
- package/test/integration/local-studio-settings-production.test.mjs +40 -0
- package/test/integration/lockfile-sync.test.mjs +26 -0
- package/test/integration/provider-env-cli.test.mjs +13 -3
- package/test/integration/runtime-status.integration.test.mjs +16 -1
- package/test/integration/theme-package-registry.test.mjs +31 -0
- package/test/repository-snapshot-view.test.mjs +2 -2
- package/test/security.test.mjs +14 -0
- package/test/terminal-machine-identity.test.mjs +2 -2
- package/apps/client-cms-editor/backend/src/demo-bootstrap.ts +0 -145
- package/packages/agentsam-nav/dist/Nav.d.ts +0 -43
- package/packages/agentsam-nav/dist/NavCollapsible.d.ts +0 -10
- package/packages/agentsam-nav/dist/NavContent.d.ts +0 -2
- package/packages/agentsam-nav/dist/NavFooter.d.ts +0 -2
- package/packages/agentsam-nav/dist/NavGroup.d.ts +0 -3
- package/packages/agentsam-nav/dist/NavHeader.d.ts +0 -2
- package/packages/agentsam-nav/dist/NavMenu.d.ts +0 -22
- package/packages/agentsam-nav/dist/NavProvider.d.ts +0 -35
- package/packages/agentsam-nav/dist/NavTrigger.d.ts +0 -2
- package/packages/agentsam-nav/dist/Surfaces.d.ts +0 -41
- package/packages/agentsam-nav/dist/browser.d.ts +0 -11
- package/packages/agentsam-nav/dist/browser.global.js +0 -132
- package/packages/agentsam-nav/dist/browser.js +0 -613
- package/packages/agentsam-nav/dist/contracts.d.ts +0 -76
- package/packages/agentsam-nav/dist/index.d.ts +0 -11
- package/packages/agentsam-nav/dist/index.js +0 -614
- package/packages/agentsam-nav/dist/legacy.css +0 -83
- package/packages/agentsam-nav/dist/shell.css +0 -113
- package/packages/agentsam-nav/dist/theme.css +0 -113
- package/packages/agentsam-nav/dist/utils.d.ts +0 -1
- package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +0 -670
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Reading the user, protecting routes, and preventing flicker
|
|
2
|
+
|
|
3
|
+
## When sign-in UI may render (hard rules)
|
|
4
|
+
|
|
5
|
+
- **Connector / owner-data apps: never gate the data fetch behind a session.**
|
|
6
|
+
When the data comes from the app's connector grants, the fetch runs on the
|
|
7
|
+
gate-injected connector token — a chain that does not involve the app
|
|
8
|
+
session. Fetch first; use the session for personalization only (greeting,
|
|
9
|
+
per-user rows). Requiring sign-in before fetching adds a click that changes
|
|
10
|
+
nothing.
|
|
11
|
+
- **A sign-in CTA may render only after the session check has RESOLVED to no
|
|
12
|
+
user** — never while `isPending` is true (no CTA flash on load), and never
|
|
13
|
+
as a reaction to a data error (the `app-data` skill's error mapping owns
|
|
14
|
+
those states; only its `login` kind ever shows "Continue with Grok").
|
|
15
|
+
- **In preview, gate identity signs the owner in with zero clicks** — a
|
|
16
|
+
visible sign-in button for the owner in the preview is a bug to fix, not a
|
|
17
|
+
style choice (`grok-identity.md`).
|
|
18
|
+
- **Use `<SignInGate>` from `@/lib/auth/gates`** — `{ children, fallback? }`:
|
|
19
|
+
nothing while pending, `children` when signed in, `fallback` (or the
|
|
20
|
+
standard provider buttons) only once signed out is known. Do not hand-roll
|
|
21
|
+
sign-in CTAs from `useCurrentUser()`.
|
|
22
|
+
|
|
23
|
+
## Reading the user / protecting routes
|
|
24
|
+
|
|
25
|
+
`@/lib/auth/use-current-user` (with auth on these reflect the REAL session, so a
|
|
26
|
+
preview visitor is signed out until they sign in):
|
|
27
|
+
|
|
28
|
+
- `useCurrentUser()` → `AppUser | null` — for display. `null` means *loading OR
|
|
29
|
+
signed out*, so never redirect on it alone.
|
|
30
|
+
- `useCurrentUserState()` → `{ user, isPending }` — for guards: wait for
|
|
31
|
+
`isPending` to clear before treating `user: null` as signed out, or a hard
|
|
32
|
+
reload bounces signed-in users to sign-in.
|
|
33
|
+
|
|
34
|
+
**State components** from `@/lib/auth/gates`: `SignedIn`, `SignedOut`,
|
|
35
|
+
`SignInGate` (`{ children, fallback? }` — nothing while pending, `children`
|
|
36
|
+
signed in, `fallback` or the standard provider buttons only once signed out is
|
|
37
|
+
known; prefer it over hand-rolled sign-in CTAs), `RedirectToSignIn`,
|
|
38
|
+
`UserButton`. (When auth is disabled via `VITE_AUTH_ENABLED=false` they apply
|
|
39
|
+
dev-user semantics so a non-auth app still renders.)
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { useCurrentUser, useCurrentUserState } from "@/lib/auth/use-current-user";
|
|
43
|
+
import { RedirectToSignIn, SignedIn, SignedOut, UserButton } from "@/lib/auth/gates";
|
|
44
|
+
|
|
45
|
+
function Navbar() {
|
|
46
|
+
const user = useCurrentUser(); // display only — null may just mean "loading"
|
|
47
|
+
return (
|
|
48
|
+
<>
|
|
49
|
+
<span>{user?.displayName ?? "Guest"}</span>
|
|
50
|
+
<SignedOut><a href="/login">Sign in</a></SignedOut>
|
|
51
|
+
<SignedIn><UserButton /></SignedIn>
|
|
52
|
+
</>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function AccountPage() {
|
|
57
|
+
const { user, isPending } = useCurrentUserState();
|
|
58
|
+
if (isPending) return null; // session still resolving
|
|
59
|
+
if (!user) return <RedirectToSignIn />; // client-side Navigate — not window.location
|
|
60
|
+
return <h1>Welcome, {user.displayName}</h1>;
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Sign out with `<UserButton />` or `signOut()` from `@/lib/auth/client`.
|
|
65
|
+
|
|
66
|
+
Session loading is the **same in live preview and when deployed**: wait for
|
|
67
|
+
`isPending` from `useCurrentUserState()` (backed by `/api/auth/get-session`).
|
|
68
|
+
The only live-preview difference is **how sign-in starts** (popup + bearer hand-off
|
|
69
|
+
instead of a full-page OAuth redirect) — not how guests vs signed-in users are
|
|
70
|
+
detected. Prefer `<RedirectToSignIn />` (TanStack `<Navigate>`) over
|
|
71
|
+
`window.location.href = "/login"` so a signed-out redirect does not full-reload
|
|
72
|
+
the SPA.
|
|
73
|
+
|
|
74
|
+
## Preventing auth flicker
|
|
75
|
+
|
|
76
|
+
`useSession()` resolves on the client, so a naive UI flashes signed-out →
|
|
77
|
+
signed-in on load. Rules:
|
|
78
|
+
|
|
79
|
+
1. **Gate on `isPending`, not `user` alone — and render a same-sized skeleton.**
|
|
80
|
+
Showing the SAME placeholder while `isPending` (server render + first client
|
|
81
|
+
paint) makes it one clean swap (skeleton → content) with no flash and no SSR
|
|
82
|
+
hydration mismatch. Don't return `null` in a slot that then grows — reserve the
|
|
83
|
+
space:
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import { useCurrentUserState } from "@/lib/auth/use-current-user";
|
|
87
|
+
import { UserButton } from "@/lib/auth/gates";
|
|
88
|
+
|
|
89
|
+
function AuthSlot() {
|
|
90
|
+
const { user, isPending } = useCurrentUserState();
|
|
91
|
+
if (isPending) return <div className="h-8 w-8 animate-pulse rounded-full bg-black/10" />;
|
|
92
|
+
return user ? <UserButton /> : <a href="/login">Sign in</a>;
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
2. **Guard at a layout boundary** (nav / page shell), not in leaf components that
|
|
97
|
+
mount/unmount — `useSession` is one shared store, so keep one stable consumer
|
|
98
|
+
per region instead of re-gating everywhere.
|
|
99
|
+
|
|
100
|
+
3. **Zero-flash when deployed: SSR the session from the cookie.** On a deployed
|
|
101
|
+
app (and top-level navigations) the session cookie is same-origin, so the server
|
|
102
|
+
already knows the user on the first request — resolve it in the root route and
|
|
103
|
+
render the authed shell immediately:
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
// src/routes/__root.tsx (excerpt)
|
|
107
|
+
import { createServerFn } from "@tanstack/react-start";
|
|
108
|
+
import { createRootRoute } from "@tanstack/react-router";
|
|
109
|
+
|
|
110
|
+
const fetchSessionUser = createServerFn({ method: "GET" }).handler(async () => {
|
|
111
|
+
// Cookie path only — works when deployed / on top-level loads.
|
|
112
|
+
const { getSessionUser } = await import("@/lib/auth/verify.server");
|
|
113
|
+
const u = await getSessionUser();
|
|
114
|
+
return u ? { id: u.id, email: u.email } : null;
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
export const Route = createRootRoute({
|
|
118
|
+
beforeLoad: async () => ({ sessionUser: await fetchSessionUser() }),
|
|
119
|
+
// Merge into the existing root — keep the existing head().
|
|
120
|
+
// component: prefer `sessionUser` for the FIRST paint when deployed, then
|
|
121
|
+
// `useCurrentUserState()` for live in-page updates.
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Sign-in/out navigate, so `beforeLoad` re-runs and the context stays fresh; call
|
|
126
|
+
`router.invalidate()` if you change auth state without navigating.
|
|
127
|
+
|
|
128
|
+
In live preview the session often rides a bearer after popup sign-in, so cookie
|
|
129
|
+
SSR may still return null until the client `useSession()` runs with the bearer
|
|
130
|
+
attached — still gate on `isPending`, same as when deployed.
|
|
131
|
+
|
|
132
|
+
The template already enables Better Auth's `session.cookieCache`, so `/get-session`
|
|
133
|
+
answers from a cookie when one is present (no DB round-trip).
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Supported sign-in methods (Google, X, email/password — and nothing else)
|
|
2
|
+
|
|
3
|
+
Use **only** these three — no other method is supported:
|
|
4
|
+
|
|
5
|
+
- **Google** and **X** — federated through the Grok broker (pre-wired here). The
|
|
6
|
+
broker federates these two upstreams and nothing else, so do **not** add entries
|
|
7
|
+
to `GROK_PROVIDERS` beyond them (the broker rejects an unknown `idp`).
|
|
8
|
+
- **Email + password** — this app's OWN Better Auth, persisted in your database
|
|
9
|
+
(never the broker, never mocked). Better Auth is DB-backed in BOTH modes — real
|
|
10
|
+
Postgres when deployed and the embedded PGLite in the sandbox preview — so
|
|
11
|
+
email/password accounts are stored and survive across requests, **in preview
|
|
12
|
+
too**. It's off by default. Enable it by editing **only**
|
|
13
|
+
`src/lib/auth/email-password.ts`:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
// src/lib/auth/email-password.ts
|
|
17
|
+
export const emailAndPasswordEnabled = true; // was false
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Do not edit or rewrite `src/lib/auth/server.ts`** (or any other file under
|
|
21
|
+
`src/lib/auth/` except `email-password.ts` for this flag). That file is
|
|
22
|
+
pre-wired; "fixing" it by regenerating Better Auth config breaks live-preview
|
|
23
|
+
sign-in.
|
|
24
|
+
|
|
25
|
+
The pre-applied schema already has the `account.password` column — no migration
|
|
26
|
+
needed. Then build sign-up / sign-in forms with `authClient.signUp.email(...)`
|
|
27
|
+
and `authClient.signIn.email(...)` from `@/lib/auth/client`.
|
|
28
|
+
|
|
29
|
+
**Do not** add `emailAndPassword` as a plugin entry (that is a syntax/type
|
|
30
|
+
error). **Do not** invent a new Better Auth config.
|
|
31
|
+
|
|
32
|
+
If sign-up/sign-in returns **"Invalid origin"**, do **not** disable CSRF and
|
|
33
|
+
do **not** edit `server.ts`. The template's `trustedOrigins` already covers
|
|
34
|
+
`*.grok-sandbox.com` and local loopback on port 8080 (`localhost` /
|
|
35
|
+
`127.0.0.1` / `[::1]`). Open the app at one of those origins (not a random
|
|
36
|
+
host/port).
|
|
37
|
+
|
|
38
|
+
Do **NOT** add or use anything else: no other social / OAuth providers (GitHub,
|
|
39
|
+
Apple, Discord, Microsoft, Facebook, …), and no magic links, passkeys, one-time
|
|
40
|
+
codes / OTP, phone / SMS, or anonymous sign-in.
|
|
41
|
+
|
|
42
|
+
## Security model (already handled — don't undo it)
|
|
43
|
+
|
|
44
|
+
- **Headless broker**: the broker offers the upstream sign-in methods
|
|
45
|
+
and holds their shared secrets; this app only holds its own per-app client
|
|
46
|
+
id/secret and names the upstream it wants via each provider's `idp` hint. The
|
|
47
|
+
broker forwards straight to Google/X. Users never see the broker.
|
|
48
|
+
- **`__Host-` cookies + `trustedOrigins`**: a sibling `*.grok.me` app can't toss a
|
|
49
|
+
`Domain=.grok.me` cookie, and Better Auth rejects cross-origin `/api/auth`
|
|
50
|
+
calls.
|
|
51
|
+
- **Sibling isolation**: `authMiddleware` rejects scripted cross-site/same-site
|
|
52
|
+
requests (Fetch-Metadata), so a sibling can't ride this app's session cookie
|
|
53
|
+
into its server functions.
|
|
54
|
+
- The upstream Google/X tokens live only on the broker; this app only ever gets a
|
|
55
|
+
broker-issued identity and mints its own local session.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Wiring the routes (do this once)
|
|
2
|
+
|
|
3
|
+
**Live-preview popup is PRE-WIRED — do not create it.**
|
|
4
|
+
`signIn` opens `/auth/popup`; the template Vite plugin
|
|
5
|
+
(`authPopupPlugin` in `vite.config.ts`) serves it via `popup.server.ts`.
|
|
6
|
+
**Never** add `src/routes/auth/popup.tsx` (or any React page / client OAuth at
|
|
7
|
+
that path). Doing so loads the full app shell in the popup ("the app opened
|
|
8
|
+
instead of Google") — that is always wrong.
|
|
9
|
+
|
|
10
|
+
**1. Mount Better Auth** — create the catch-all API route (this is what makes
|
|
11
|
+
`/api/auth/*` work; the broker's OAuth callback lands here):
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// src/routes/api/auth/$.ts
|
|
15
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
16
|
+
import { auth } from "@/lib/auth/server";
|
|
17
|
+
|
|
18
|
+
export const Route = createFileRoute("/api/auth/$")({
|
|
19
|
+
server: {
|
|
20
|
+
handlers: {
|
|
21
|
+
GET: ({ request }) => auth.handler(request),
|
|
22
|
+
POST: ({ request }) => auth.handler(request),
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**2. Add a sign-in page** — buttons that kick off the broker flow. Import from
|
|
29
|
+
`@/lib/auth/client`. With the flag on, `authEnabled` is true in preview and
|
|
30
|
+
deployed, so the buttons show and work in the live preview; the `else` branch
|
|
31
|
+
shows while auth is still disabled (`VITE_AUTH_ENABLED=false`):
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
// src/routes/login.tsx
|
|
35
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
36
|
+
import { GROK_PROVIDERS, authEnabled, signIn } from "@/lib/auth/client";
|
|
37
|
+
|
|
38
|
+
export const Route = createFileRoute("/login")({ component: Login });
|
|
39
|
+
|
|
40
|
+
function Login() {
|
|
41
|
+
return (
|
|
42
|
+
<main className="grid min-h-screen place-items-center p-6">
|
|
43
|
+
<div className="w-full max-w-sm space-y-3">
|
|
44
|
+
<h1 className="text-xl font-semibold">Sign in</h1>
|
|
45
|
+
{authEnabled ? (
|
|
46
|
+
GROK_PROVIDERS.map((p) => (
|
|
47
|
+
<button
|
|
48
|
+
key={p.providerId}
|
|
49
|
+
type="button"
|
|
50
|
+
onClick={() => signIn(p.providerId, { callbackURL: "/" })}
|
|
51
|
+
className="w-full cursor-pointer rounded-md border border-neutral-300 px-4 py-2 hover:bg-neutral-100 dark:border-neutral-700 dark:hover:bg-neutral-900"
|
|
52
|
+
>
|
|
53
|
+
Continue with {p.label}
|
|
54
|
+
</button>
|
|
55
|
+
))
|
|
56
|
+
) : (
|
|
57
|
+
<p className="text-sm text-neutral-500">Sign-in is disabled.</p>
|
|
58
|
+
)}
|
|
59
|
+
</div>
|
|
60
|
+
</main>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`RedirectToSignIn` sends signed-out users to `/login` by default (override with
|
|
66
|
+
`<RedirectToSignIn to="/somewhere" />`). Style the page however you like — see
|
|
67
|
+
the `design-ui` skill.
|
|
68
|
+
|
|
69
|
+
That's it — call `signIn(providerId)` from your sign-in buttons. The popup,
|
|
70
|
+
bearer-token hand-off, and request attachment are all inside `src/lib/auth` +
|
|
71
|
+
the Vite plugin; leave them alone.
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: building-games
|
|
3
|
+
description: >
|
|
4
|
+
Build browser games and interactive/canvas/3D experiences in this TanStack
|
|
5
|
+
Start + React app. Use for any game, simulation, or WebGL/Canvas experience —
|
|
6
|
+
2D or 3D, single-player. Covers the game loop & timing, 3D orientation/camera
|
|
7
|
+
conventions, collision, performance, assets, audio, save, game feel, and
|
|
8
|
+
per-genre playbooks. For WASD / vehicle / flight **input signs and inverted
|
|
9
|
+
A/D**, open the **`controls`** skill — do not rely on this file or racing-kart
|
|
10
|
+
alone. Triggers on "game", "minecraft", "fps", "platformer", "racing",
|
|
11
|
+
"tetris", "snake", "shooter", "3d", "three.js", "canvas", "voxel", "physics".
|
|
12
|
+
metadata:
|
|
13
|
+
short-description: "Browser games: loop, 3D orientation, camera, perf, assets, genres"
|
|
14
|
+
user-invocable: false
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Building Games
|
|
18
|
+
|
|
19
|
+
Build a **playable, correct** browser game — not a static screenshot. A game is
|
|
20
|
+
just a React route with a `<canvas>` (or `<Canvas>` for R3F) plus DOM overlay UI.
|
|
21
|
+
Style the overlay (start screen, HUD, menus) with the **`design-ui`** skill; this
|
|
22
|
+
skill owns the gameplay loop and world.
|
|
23
|
+
|
|
24
|
+
**Controls / inverted A/D:** open **`.grok/skills/controls/SKILL.md`** **before**
|
|
25
|
+
writing WASD, steering, or flight input. Vehicle/flight demos often ship with
|
|
26
|
+
A/D flipped if you only read this file or a single genre playbook.
|
|
27
|
+
|
|
28
|
+
**Scope note — single-player, bots, or small P2P co-op:**
|
|
29
|
+
- Ship **single-player** or **single-player + AI/bots** by default.
|
|
30
|
+
- **2–8 player co-op / casual realtime** (shared cursors, party games, casual
|
|
31
|
+
action among friends) is supported — use the **`multiplayer-p2p` skill**
|
|
32
|
+
(WebRTC mesh, signaled at `/api/rtc`). Read its trust model first.
|
|
33
|
+
- P2P is the only supported multiplayer right now. Do not half-build sockets
|
|
34
|
+
that can’t connect.
|
|
35
|
+
|
|
36
|
+
**References (load on demand):**
|
|
37
|
+
- **`controls` skill** (`../controls/`) — **required** for movement/steer/flight:
|
|
38
|
+
player-visible A/D, inverted-steer anti-pattern, flight ailerons, mandatory
|
|
39
|
+
self-test + `window.__controlsTest`. Not optional for vehicles/planes.
|
|
40
|
+
- `references/threejs-foundational.md` — the deep 3D/loop/perf reference. Read for 3D.
|
|
41
|
+
- `references/3d-libs.md` — three.js + @react-three/fiber + drei + rapier usage.
|
|
42
|
+
- **`threejs` skill** (`../threejs/`) — official full Three.js + TSL API dump
|
|
43
|
+
(`llms-full.txt`). Load for advanced materials/shaders/WebGPU/loaders; not for
|
|
44
|
+
simple 2D canvas games.
|
|
45
|
+
- `references/babylon.md` — Babylon.js, the batteries-included 3D engine alternative.
|
|
46
|
+
- `references/phaser.md` — Phaser 3, the default engine for 2D games.
|
|
47
|
+
- `references/ecs-architecture.md` — entity-component-system structure for larger games.
|
|
48
|
+
- `references/genres/*.md` — per-genre playbooks (fps, platformer-2d, racing-kart,
|
|
49
|
+
puzzle-match3-tetris, voxel-minecraft, endless-runner, topdown-twin-stick,
|
|
50
|
+
tower-defense, board-card-chess). Genre files **do not** replace **`controls`**.
|
|
51
|
+
- `references/game-feel-juice.md`, `input.md`, `audio.md`, `collision-physics.md`,
|
|
52
|
+
`save-persistence.md`, `procedural-generation.md`, `ai-pathfinding.md`.
|
|
53
|
+
- **`game-asset-core`** (+ `game-animation-frames` / `game-tilesets` /
|
|
54
|
+
`game-character-consistency` / `game-ui-icons`) — engine-ready 2D art defaults
|
|
55
|
+
and verification when generating sprites, sheets, tiles, or UI (see §6).
|
|
56
|
+
|
|
57
|
+
Pick the specific genre/topic reference for the build; this file is the universal
|
|
58
|
+
core for loop/world. **Input signs → `controls`.** **2D game art → `game-asset-core`.**
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 1. Game loop & timing (the #1 correctness issue)
|
|
63
|
+
|
|
64
|
+
- Drive the loop with the engine's RAF loop (`renderer.setAnimationLoop`, R3F
|
|
65
|
+
`useFrame`, or `requestAnimationFrame` for 2D canvas). **Never** `setInterval`/
|
|
66
|
+
`setTimeout`/`Date.now()` for game timing.
|
|
67
|
+
- **Scale ALL movement/animation by delta time** (seconds) so speed is frame-rate
|
|
68
|
+
independent (60Hz vs 144Hz). Compute delta **once per frame** and reuse it.
|
|
69
|
+
- three.js: use `THREE.Timer` (not `Clock` — `Clock.getDelta()` returns ~0 on a
|
|
70
|
+
second call in the same frame, a classic freeze bug).
|
|
71
|
+
- **Cap delta** (`min(delta, 0.1)`) so a backgrounded tab doesn't teleport things.
|
|
72
|
+
- **Fixed timestep for physics/gameplay:** accumulate delta and step simulation at
|
|
73
|
+
a fixed rate (e.g. 1/60) while rendering at display rate — prevents tunneling and
|
|
74
|
+
non-determinism.
|
|
75
|
+
|
|
76
|
+
## 2. Controls (delegate to the `controls` skill)
|
|
77
|
+
|
|
78
|
+
**Open `.grok/skills/controls/SKILL.md` before implementing any WASD / steer /
|
|
79
|
+
flight code.** That skill is the source of truth for:
|
|
80
|
+
|
|
81
|
+
- Player-visible **A = left / D = right** (chase cam, while moving forward)
|
|
82
|
+
- Why **`KeyA → steer−` + `yaw += steer * +rate` inverts** (most common bug)
|
|
83
|
+
- Vehicle vs FPS (strafe ≠ steer), fixed-wing ailerons, heli/drone notes
|
|
84
|
+
- Mandatory self-test + `window.__controlsTest` probe
|
|
85
|
+
|
|
86
|
+
Do **not** treat `genres/racing-kart.md` as the only place steer signs live —
|
|
87
|
+
planes, jetskis, and mechs never open it.
|
|
88
|
+
|
|
89
|
+
**Short reminder (full detail in `controls`):**
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
// Vehicle yaw body (chase cam): A must increase yaw with this basis
|
|
93
|
+
forward = (-sin(yaw), 0, -cos(yaw))
|
|
94
|
+
// KeyA → steer = +1; yaw += steer * turnRate * speedFactor * dt
|
|
95
|
+
// WRONG (ships inverted): KeyA → steer = -1; yaw += steer * turnRate * dt
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
- **Pointer lock:** mouse-look only — implement WASD yourself; click-to-play
|
|
99
|
+
overlay; dismiss on lock.
|
|
100
|
+
- Track keys with held state + **dt**; unify devices via `references/input.md`.
|
|
101
|
+
- **Finish:** run the `controls` skill checklist. Screenshot-only is insufficient
|
|
102
|
+
for vehicles/flight.
|
|
103
|
+
|
|
104
|
+
## 3. 3D orientation & world objects (the "sideways/backwards" bugs)
|
|
105
|
+
|
|
106
|
+
- three.js is **right-handed, +Y up**: +X right, +Y up, +Z toward viewer. **Meshes
|
|
107
|
+
face +Z; cameras look −Z** (the classic "camera backwards" gotcha).
|
|
108
|
+
- Primitives like `Cone`/`Cylinder` point **+Y** by default → rotate to align a
|
|
109
|
+
tip with forward (`geo.rotateX(Math.PI/2)`).
|
|
110
|
+
- **Orienting a mesh to face `forward`** (meshes face **+Z**): simplest correct way
|
|
111
|
+
is `mesh.lookAt(mesh.position.clone().add(forward))`. To build the basis by hand,
|
|
112
|
+
set the **+Z column to `forward`** and choose the x-axis that keeps it a *proper*
|
|
113
|
+
right-handed rotation (`det = +1`):
|
|
114
|
+
`xAxis = normalize(cross(up, forward))`, then `makeBasis(xAxis, up, forward)`.
|
|
115
|
+
Note this is `cross(up, forward)` — **not** the movement `right = cross(forward, up)`
|
|
116
|
+
from §2. Targeting +Z (instead of a camera's −Z) flips the x-axis sign so that
|
|
117
|
+
`xAxis × up = forward`; the frame stays right-handed (no mirroring). Do **not** use
|
|
118
|
+
`makeBasis(xAxis, up, -forward)` for a mesh — that targets −forward (the *camera*
|
|
119
|
+
convention) so the mesh faces **backwards**.
|
|
120
|
+
- **Orienting a camera** to look along `forward` (cameras look **−Z**): set the +Z
|
|
121
|
+
column to `-forward` — `xAxis = normalize(cross(forward, up))`, then
|
|
122
|
+
`makeBasis(xAxis, up, -forward)` (or just `camera.lookAt(target)`).
|
|
123
|
+
- Keep a consistent world `up` so objects stay upright; only rotate flat primitives
|
|
124
|
+
to stand up.
|
|
125
|
+
- Verify glTF import orientation; debug with `AxesHelper`/`ArrowHelper`. Upright
|
|
126
|
+
self-test: characters stand on the ground plane, not lying/sunk.
|
|
127
|
+
|
|
128
|
+
## 4. Camera must agree with movement
|
|
129
|
+
|
|
130
|
+
- Keep a **dedicated `moveForward`/`moveRight`** for movement, computed once and
|
|
131
|
+
never mutated by camera code (aliasing a shared temp vector makes camera and
|
|
132
|
+
movement disagree — a real repro bug).
|
|
133
|
+
- Third-person follow: `desired = playerPos + up*height + moveForward*(-followDist)`;
|
|
134
|
+
lerp the camera toward it (use exp-based smoothing, delta-scaled), `lookAt(player)`.
|
|
135
|
+
- Isolate-the-layer debug order: (1) keys register → (2) movement signs correct →
|
|
136
|
+
(3) camera agrees. Fix in that order.
|
|
137
|
+
|
|
138
|
+
## 5. Performance
|
|
139
|
+
|
|
140
|
+
- **Minimize draw calls** (`renderer.info.render.calls`, target <100): share
|
|
141
|
+
materials, `InstancedMesh`/`BatchedMesh` for repeated objects, atlases.
|
|
142
|
+
- **Dispose GPU resources yourself** (`geometry/material/texture.dispose()`) on
|
|
143
|
+
level change — three.js does not GC them. **Pool** bullets/enemies/particles.
|
|
144
|
+
- No per-frame allocations (reuse temp vectors). Compress textures; LOD for distance.
|
|
145
|
+
|
|
146
|
+
## 6. Assets (avoid the generated-photo trap)
|
|
147
|
+
|
|
148
|
+
- **Interactive 3D elements** (weapon viewmodels, characters, props, projectiles)
|
|
149
|
+
→ build from **3D geometry / glTF**, not a generated image. A flat photorealistic
|
|
150
|
+
JPG of a gun-in-hands used as an FPS viewmodel looks wrong, can't animate, and
|
|
151
|
+
(JPG has **no alpha**) renders as a black box. Parent a real 3D viewmodel to the
|
|
152
|
+
camera as an overlay render layer.
|
|
153
|
+
- Reserve image generation for **flat 2D** assets only (textures, sky/menu
|
|
154
|
+
backgrounds, 2D sprites, UI art). **Never** use a generated photo as a 3D mesh,
|
|
155
|
+
viewmodel, or character substitute — build those in 3D geometry / glTF.
|
|
156
|
+
Set `crossOrigin="anonymous"` on images drawn to canvas/textures.
|
|
157
|
+
See the **`imagine`** skill (2D only — image tools cannot produce real 3D).
|
|
158
|
+
- **Engine-ready game art doctrine** → open **`game-asset-core`**
|
|
159
|
+
(`../game-asset-core/`) for defaults + blind verify + retry discipline, then the
|
|
160
|
+
matching specialist: **`game-animation-frames`** (loop / motion laws),
|
|
161
|
+
**`game-tilesets`**, **`game-character-consistency`**, **`game-ui-icons`**.
|
|
162
|
+
These are **QC/doctrine**, not the export pipeline. Do not ship stick-figure
|
|
163
|
+
placeholders when real art is expected.
|
|
164
|
+
- **2D game sprites / animation sheets** → run **`generate2dsprite`**
|
|
165
|
+
(`.grok/skills/generate2dsprite/SKILL.md`): solid **`#FF00FF`** magenta
|
|
166
|
+
`imagine_text_to_image` sheets + chroma postprocess scripts (magenta is required for the
|
|
167
|
+
processor). Wire transparent PNGs/GIFs into Canvas/Phaser. Still apply
|
|
168
|
+
**`game-asset-core`** (+ animation/character specialists when relevant).
|
|
169
|
+
- **2D maps / levels / prop packs** → open **`generate2dmap`**
|
|
170
|
+
(`.grok/skills/generate2dmap/SKILL.md`). Prefer foundation-only base + separate
|
|
171
|
+
props/collision for playable maps. Browser default: `raw_canvas` / Phaser.
|
|
172
|
+
Tileable ground/walls → also **`game-tilesets`** for 2×2 seam checks.
|
|
173
|
+
- **Optional denser locomotion** → run **`video2dsprite`** (Grok
|
|
174
|
+
`imagine_image_to_video` + sandbox scripts; magenta base). Prefer `generate2dsprite`
|
|
175
|
+
for crisp production heroes. Use **`game-animation-frames`** for loop/flip-test
|
|
176
|
+
laws; prefer **`video2dsprite`** over ad-hoc ffmpeg-only harvest in this
|
|
177
|
+
sandbox.
|
|
178
|
+
|
|
179
|
+
## 7. Audio, save, feel
|
|
180
|
+
- **Audio**: unlock `AudioContext` on the first user gesture (tap-to-start) or iOS
|
|
181
|
+
is silent; re-resume on `visibilitychange`. (`references/audio.md`)
|
|
182
|
+
- **Save**: `localStorage`/IndexedDB with a `version` field + migrations.
|
|
183
|
+
- **Juice**: screen shake, hit-stop, eased tweens, particles — cheap, huge
|
|
184
|
+
perceived-quality lift. Keep presentation separate from simulation.
|
|
185
|
+
|
|
186
|
+
## 8. Mobile
|
|
187
|
+
- Distinguish canvas buffer size from CSS size; respect `devicePixelRatio`.
|
|
188
|
+
- `touch-action: none`, letterbox-fit to a base resolution, handle orientation.
|
|
189
|
+
- Touch controls (virtual joystick + action buttons), ≥44px targets.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Stack / engine choice
|
|
194
|
+
- **3D → three.js**, ideally via **@react-three/fiber + drei** (fits the React
|
|
195
|
+
app; drei gives pointer-lock/controls/loaders) + **@react-three/rapier** for
|
|
196
|
+
physics/character controllers. See `references/3d-libs.md`.
|
|
197
|
+
- **2D →** native Canvas 2D is enough for snake/tetris/flappy/platformer; reach for
|
|
198
|
+
Phaser only when the genre needs it.
|
|
199
|
+
- These game deps are **not preinstalled** — `npm install` them (and make sure they
|
|
200
|
+
land in `package.json` so the Vercel build has them).
|
|
201
|
+
|
|
202
|
+
## Finish criteria (before "done")
|
|
203
|
+
- Loads with **no console errors**; visible gameplay (not a blank canvas).
|
|
204
|
+
- **`controls` skill self-test passed** (A = left / D = right from chase cam
|
|
205
|
+
while moving forward; flip one sign if inverted). Not screenshot-only.
|
|
206
|
+
- 3D upright & camera-agrees self-tests pass (§3, §4).
|
|
207
|
+
- Runs on mobile viewport with touch controls.
|
|
208
|
+
- Production build (`npm run build`) renders the built output, not just dev.
|
|
209
|
+
- **Share / X card:** open the **`og`** skill — custom `public/og.jpg` **and**
|
|
210
|
+
`"type": "x:game"` in `src/lib/og/site.json`. X uses `og:type="x:game"`
|
|
211
|
+
to present the unfurl as a game card; do not use `twitter:card` or invent
|
|
212
|
+
`x:type` for this. `browser-smoke` / `brand-check` warn when canvas apps omit
|
|
213
|
+
the `site.json` field.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "agentsam.skill.v1",
|
|
3
|
+
"id": "grok-building-games",
|
|
4
|
+
"name": "Grok \u00b7 building-games",
|
|
5
|
+
"description": "Browser games: loop, 3D orientation, camera, perf, assets, genres",
|
|
6
|
+
"icon": "skill",
|
|
7
|
+
"slash": {
|
|
8
|
+
"suggested": "/grok-building-games"
|
|
9
|
+
},
|
|
10
|
+
"instructions": {
|
|
11
|
+
"source": "local_file",
|
|
12
|
+
"ref": "SKILL.md"
|
|
13
|
+
},
|
|
14
|
+
"execution": {
|
|
15
|
+
"mode": "turn",
|
|
16
|
+
"tools": [],
|
|
17
|
+
"operations": [],
|
|
18
|
+
"capabilities": []
|
|
19
|
+
},
|
|
20
|
+
"provenance": {
|
|
21
|
+
"source": "apps/local-studio/.grok/skills",
|
|
22
|
+
"vendor": "grok",
|
|
23
|
+
"status": "imported"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# 3D libraries for this stack (three.js + React Three Fiber + drei + rapier)
|
|
2
|
+
|
|
3
|
+
The app is React/TanStack. The idiomatic way to do 3D here is **React Three
|
|
4
|
+
Fiber (R3F)** — write three.js as React components inside a `<Canvas>` on a
|
|
5
|
+
route. It deploys like any other page.
|
|
6
|
+
|
|
7
|
+
> These are **not preinstalled**. Install and confirm they land in `package.json`:
|
|
8
|
+
> `npm i three @react-three/fiber @react-three/drei @react-three/rapier`
|
|
9
|
+
> (+ `npm i -D @types/three`). If the deploy build has no three, the game is blank.
|
|
10
|
+
|
|
11
|
+
## When to use what
|
|
12
|
+
- **three.js** — the engine. Raw three is fine for a self-contained canvas; prefer
|
|
13
|
+
R3F when the game has React UI/state around it.
|
|
14
|
+
- **@react-three/fiber** — renders three as React; `useFrame((state, delta) => …)`
|
|
15
|
+
is your game loop (delta is seconds — scale movement by it, see SKILL §1).
|
|
16
|
+
- **@react-three/drei** — helpers so you don't hand-roll bug-prone code:
|
|
17
|
+
`<PointerLockControls/>`, `useKeyboardControls`, `<OrbitControls/>`,
|
|
18
|
+
`useGLTF`, `<Environment/>`, `<Instances/>`, `<Stats/>`.
|
|
19
|
+
- **@react-three/rapier** — physics + **character controller** (capsule +
|
|
20
|
+
autostep + snap-to-ground). Use for FPS/platformer movement and collisions
|
|
21
|
+
instead of hand-rolled raycasts. `<Physics>`, `<RigidBody>`, `useRapier`.
|
|
22
|
+
|
|
23
|
+
## Minimal R3F shape
|
|
24
|
+
```tsx
|
|
25
|
+
import { Canvas, useFrame } from "@react-three/fiber";
|
|
26
|
+
import { PointerLockControls, useKeyboardControls } from "@react-three/drei";
|
|
27
|
+
|
|
28
|
+
function Player() {
|
|
29
|
+
useFrame((_, delta) => {
|
|
30
|
+
const d = Math.min(delta, 0.1); // cap delta (SKILL §1)
|
|
31
|
+
// move with a dedicated moveForward/moveRight basis (SKILL §2/§4)
|
|
32
|
+
});
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default function Game() {
|
|
37
|
+
return (
|
|
38
|
+
<Canvas camera={{ position: [0, 1.7, 5], fov: 75 }} shadows dpr={[1, 2]}>
|
|
39
|
+
{/* scene */}
|
|
40
|
+
<PointerLockControls /> {/* mouse-look ONLY — implement WASD yourself */}
|
|
41
|
+
<Player />
|
|
42
|
+
</Canvas>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Gotchas (map to the SKILL universals)
|
|
48
|
+
- **Controls:** drei `PointerLockControls` is mouse-look only — WASD is yours
|
|
49
|
+
(SKILL §2). Gate `.lock()` behind a "click to play" overlay and dismiss it on lock.
|
|
50
|
+
- **Orientation:** meshes face +Z, camera looks −Z; right-handed +Y up (SKILL §3).
|
|
51
|
+
- **Delta:** `useFrame` delta is seconds; cap it; fixed-step physics via rapier's
|
|
52
|
+
own stepping. Don't read `THREE.Clock.getDelta()` twice a frame.
|
|
53
|
+
- **Perf:** `<Instances>`/`InstancedMesh` for repeats; dispose on unmount (R3F
|
|
54
|
+
auto-disposes objects it created, but not manual textures/loaders — dispose those).
|
|
55
|
+
Set `dpr={[1, 2]}` to cap retina cost.
|
|
56
|
+
- **Mobile:** R3F sets pixel ratio via `dpr`; still add touch controls + `touch-action:none`.
|
|
57
|
+
|
|
58
|
+
## Alternatives
|
|
59
|
+
- **Babylon.js** (`references/babylon.md`) — batteries-included 3D (Havok physics,
|
|
60
|
+
inspector, SceneOptimizer). Viable if you want an all-in-one engine, but it's a
|
|
61
|
+
separate paradigm from React; default to three/R3F for consistency with the app.
|
|
62
|
+
|
|
63
|
+
Sources: R3F docs (https://r3f.docs.pmnd.rs), drei (https://github.com/pmndrs/drei),
|
|
64
|
+
react-three-rapier (https://github.com/pmndrs/react-three-rapier), three.js docs.
|