forgeos 0.1.0-alpha.2 → 0.1.0-alpha.21
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/.npmignore +4 -0
- package/AGENTS.md +168 -81
- package/CHANGELOG.md +211 -0
- package/README.md +88 -14
- package/adapters/go/README.md +23 -0
- package/adapters/go/go.mod +3 -0
- package/adapters/go/http.go +149 -0
- package/adapters/go/registry.go +234 -0
- package/adapters/go/types.go +136 -0
- package/adapters/java/README.md +68 -0
- package/adapters/java/pom.xml +34 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Auth.java +20 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Diagnostic.java +16 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Entry.java +38 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/EntryKind.java +16 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ErrorInfo.java +4 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Forge.java +94 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeCall.java +12 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeContext.java +11 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHandler.java +8 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHttpHandler.java +179 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeRegistry.java +121 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Json.java +14 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Manifest.java +14 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/RequestEnvelope.java +6 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ResponseEnvelope.java +25 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Risk.java +18 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Schemas.java +36 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Service.java +65 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/TransactionMode.java +18 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/TypedForgeHandler.java +6 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Auth.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Diagnostic.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Entry.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/EntryKind.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ErrorInfo.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Forge.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeCall.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeContext.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeHandler.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeHttpHandler.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry$EntryOption.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry$RegisteredEntry.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry$RegistryOption.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Json.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Manifest.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/RequestEnvelope.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ResponseEnvelope.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Risk.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Schemas.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Service.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/TransactionMode.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/TypedForgeHandler.class +0 -0
- package/adapters/java/target/forge-java-adapter-0.1.0-alpha.11.jar +0 -0
- package/adapters/java/target/maven-archiver/pom.properties +3 -0
- package/adapters/java/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +23 -0
- package/adapters/java/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +20 -0
- package/adapters/java-spring-boot-starter/README.md +32 -0
- package/adapters/java-spring-boot-starter/pom.xml +36 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeCommand.java +22 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeExternalService.java +15 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeQuery.java +16 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.java +18 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.java +16 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringRuntime.java +104 -0
- package/adapters/java-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
- package/adapters/java-spring-boot-starter/target/classes/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
- package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeCommand.class +0 -0
- package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeExternalService.class +0 -0
- package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeQuery.class +0 -0
- package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.class +0 -0
- package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.class +0 -0
- package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeSpringRuntime.class +0 -0
- package/adapters/java-spring-boot-starter/target/forge-java-spring-boot-starter-0.1.0-alpha.11.jar +0 -0
- package/adapters/java-spring-boot-starter/target/maven-archiver/pom.properties +3 -0
- package/adapters/java-spring-boot-starter/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +6 -0
- package/adapters/java-spring-boot-starter/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +6 -0
- package/bin/forge.mjs +18 -0
- package/docs/changelog.md +242 -0
- package/docs/forge-protocol.md +189 -0
- package/examples/go-billing/go.mod +7 -0
- package/examples/go-billing/main.go +120 -0
- package/examples/java-billing/pom.xml +52 -0
- package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/CreateInvoiceInput.java +4 -0
- package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Invoice.java +11 -0
- package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Main.java +127 -0
- package/examples/java-billing/target/classes/dev/forgeos/examples/billing/CreateInvoiceInput.class +0 -0
- package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Invoice.class +0 -0
- package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Main$EmptyInput.class +0 -0
- package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Main$Options.class +0 -0
- package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Main.class +0 -0
- package/examples/java-billing/target/java-billing-0.1.0-alpha.11-all.jar +0 -0
- package/examples/java-billing/target/java-billing-0.1.0-alpha.11.jar +0 -0
- package/examples/java-billing/target/maven-archiver/pom.properties +3 -0
- package/examples/java-billing/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +5 -0
- package/examples/java-billing/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +3 -0
- package/package.json +29 -7
- package/schemas/forge-manifest.schema.json +57 -0
- package/src/forge/_generated/releaseManifest.json +1 -2
- package/src/forge/_generated/releaseManifest.ts +3 -3
- package/src/forge/agent-adapters/index.ts +1511 -123
- package/src/forge/agent-adapters/types.ts +216 -1
- package/src/forge/agent-memory/bridge.ts +1245 -0
- package/src/forge/agent-memory/context-pack.ts +151 -0
- package/src/forge/agent-memory/hook-runner.ts +312 -0
- package/src/forge/agent-memory/mcp.ts +224 -0
- package/src/forge/agent-memory/normalize.ts +498 -0
- package/src/forge/agent-memory/redaction.ts +103 -0
- package/src/forge/agent-memory/sources/claude-code.ts +51 -0
- package/src/forge/agent-memory/sources/codex-hook-runner.mjs +273 -0
- package/src/forge/agent-memory/sources/codex.ts +119 -0
- package/src/forge/agent-memory/sources/cursor.ts +35 -0
- package/src/forge/agent-memory/types.ts +191 -0
- package/src/forge/bench.ts +248 -0
- package/src/forge/brownfield-import/index.ts +801 -0
- package/src/forge/brownfield-import/types.ts +127 -0
- package/src/forge/cair/action-journal.ts +61 -0
- package/src/forge/cair/action-parser.ts +314 -0
- package/src/forge/cair/action-validator.ts +40 -0
- package/src/forge/cair/actions.ts +1818 -0
- package/src/forge/cair/format.ts +77 -0
- package/src/forge/cair/index.ts +106 -0
- package/src/forge/cair/query.ts +478 -0
- package/src/forge/cair/snapshot.ts +315 -0
- package/src/forge/cair/types.ts +248 -0
- package/src/forge/cli/ai.ts +671 -3
- package/src/forge/cli/auth.ts +36 -1
- package/src/forge/cli/build.ts +20 -4
- package/src/forge/cli/changed.ts +300 -0
- package/src/forge/cli/codex-app-server.ts +877 -0
- package/src/forge/cli/commands.ts +1285 -7
- package/src/forge/cli/db.ts +121 -2
- package/src/forge/cli/deps.ts +79 -12
- package/src/forge/cli/dev.ts +502 -38
- package/src/forge/cli/docs.ts +265 -0
- package/src/forge/cli/handoff.ts +250 -0
- package/src/forge/cli/index.ts +1 -0
- package/src/forge/cli/main.ts +49 -3
- package/src/forge/cli/new.ts +3 -1
- package/src/forge/cli/next-actions.ts +23 -0
- package/src/forge/cli/output.ts +290 -1
- package/src/forge/cli/parse.ts +770 -36
- package/src/forge/cli/query.ts +32 -0
- package/src/forge/cli/release.ts +35 -11
- package/src/forge/cli/rls.ts +568 -17
- package/src/forge/cli/run.ts +41 -0
- package/src/forge/cli/secrets.ts +46 -1
- package/src/forge/cli/security.ts +381 -0
- package/src/forge/cli/self-host.ts +56 -14
- package/src/forge/cli/studio.ts +2163 -0
- package/src/forge/cli/verify.ts +1422 -32
- package/src/forge/compiler/agent-contract/build.ts +725 -41
- package/src/forge/compiler/agent-contract/types.ts +85 -0
- package/src/forge/compiler/ai-registry/build.ts +62 -1
- package/src/forge/compiler/ai-registry/constants.ts +1 -1
- package/src/forge/compiler/ai-registry/parse.ts +168 -5
- package/src/forge/compiler/api-surface/build.ts +47 -0
- package/src/forge/compiler/app-graph/build.ts +68 -8
- package/src/forge/compiler/app-graph/extract.ts +107 -0
- package/src/forge/compiler/app-graph/forge-apis.ts +1 -0
- package/src/forge/compiler/app-graph/module-graph.ts +73 -78
- package/src/forge/compiler/app-graph/parser.ts +24 -24
- package/src/forge/compiler/app-graph/profile.ts +26 -0
- package/src/forge/compiler/app-graph/versions.ts +1 -1
- package/src/forge/compiler/classifier/capabilities.ts +3 -2
- package/src/forge/compiler/classifier/classify.ts +32 -8
- package/src/forge/compiler/classifier/secrets.ts +3 -2
- package/src/forge/compiler/classifier/signals.ts +91 -1
- package/src/forge/compiler/client-sdk/build-manifest.ts +59 -0
- package/src/forge/compiler/client-sdk/render-client.ts +188 -13
- package/src/forge/compiler/data-graph/parse.ts +3 -3
- package/src/forge/compiler/data-graph/sql/ddl.ts +60 -2
- package/src/forge/compiler/data-graph/sql/serialize.ts +4 -0
- package/src/forge/compiler/data-graph/sql/types.ts +1 -0
- package/src/forge/compiler/dev-manifest/build.ts +3 -0
- package/src/forge/compiler/diagnostics/codes.ts +35 -0
- package/src/forge/compiler/diagnostics/create.ts +8 -3
- package/src/forge/compiler/diagnostics/index.ts +2 -0
- package/src/forge/compiler/emitter/barrel.ts +3 -0
- package/src/forge/compiler/emitter/render.ts +5 -0
- package/src/forge/compiler/external-manifest/registry.ts +205 -0
- package/src/forge/compiler/external-manifest/types.ts +91 -0
- package/src/forge/compiler/external-manifest/validate.ts +373 -0
- package/src/forge/compiler/frontend-graph/build.ts +85 -13
- package/src/forge/compiler/integration/add.ts +498 -22
- package/src/forge/compiler/integration/snapshot.ts +2 -0
- package/src/forge/compiler/make-registry/build.ts +19 -7
- package/src/forge/compiler/orchestrator/plan-profile.ts +23 -0
- package/src/forge/compiler/orchestrator/plan.ts +78 -7
- package/src/forge/compiler/orchestrator/profile.ts +65 -0
- package/src/forge/compiler/orchestrator/run.ts +97 -31
- package/src/forge/compiler/orchestrator/serialize.ts +101 -8
- package/src/forge/compiler/package-graph/compiler.ts +13 -3
- package/src/forge/compiler/package-manager/adapter.ts +4 -1
- package/src/forge/compiler/package-manager/commands.ts +4 -0
- package/src/forge/compiler/package-manager/executor.ts +30 -1
- package/src/forge/compiler/policy-registry/build.ts +44 -1
- package/src/forge/compiler/test-graph/build.ts +11 -3
- package/src/forge/compiler/types/ai-registry.ts +25 -1
- package/src/forge/compiler/types/app-graph.ts +9 -2
- package/src/forge/compiler/types/cli.ts +76 -1
- package/src/forge/compiler/types/dev-manifest.ts +3 -0
- package/src/forge/compiler/types/frontend-graph.ts +2 -2
- package/src/forge/delta/classifier.ts +52 -0
- package/src/forge/delta/explain.ts +126 -0
- package/src/forge/delta/git-observer.ts +43 -0
- package/src/forge/delta/ids.ts +44 -0
- package/src/forge/delta/index.ts +13 -0
- package/src/forge/delta/recorder.ts +402 -0
- package/src/forge/delta/redaction.ts +50 -0
- package/src/forge/delta/schema.ts +240 -0
- package/src/forge/delta/session.ts +142 -0
- package/src/forge/delta/status.ts +489 -0
- package/src/forge/delta/store.ts +2975 -0
- package/src/forge/delta/timeline.ts +104 -0
- package/src/forge/dev/server.ts +768 -15
- package/src/forge/dev/types.ts +15 -1
- package/src/forge/dev/watch.ts +17 -7
- package/src/forge/dev-console/cycle.ts +233 -21
- package/src/forge/dev-console/types.ts +46 -1
- package/src/forge/impact/index.ts +46 -8
- package/src/forge/impact/types.ts +6 -0
- package/src/forge/intent/index.ts +35 -16
- package/src/forge/make/index.ts +149 -6
- package/src/forge/make/templates.ts +343 -2
- package/src/forge/make/types.ts +3 -1
- package/src/forge/refactor/index.ts +1 -0
- package/src/forge/repair/rules/index.ts +2 -2
- package/src/forge/review/index.ts +158 -12
- package/src/forge/review/types.ts +15 -0
- package/src/forge/runtime/ai/context.ts +210 -5
- package/src/forge/runtime/ai/types.ts +70 -0
- package/src/forge/runtime/auth/claims.ts +32 -0
- package/src/forge/runtime/auth/errors.ts +2 -0
- package/src/forge/runtime/context/create-context.ts +30 -6
- package/src/forge/runtime/db/generated-client.ts +13 -2
- package/src/forge/runtime/db/memory-adapter.ts +2 -2
- package/src/forge/runtime/db/pglite-adapter.ts +77 -2
- package/src/forge/runtime/db/postgres-adapter.ts +6 -3
- package/src/forge/runtime/executor.ts +112 -2
- package/src/forge/runtime/external/bridge.ts +649 -0
- package/src/forge/runtime/runner/run-entry.ts +16 -7
- package/src/forge/runtime/telemetry/scrubber.ts +91 -10
- package/src/forge/runtime/webhooks/security.ts +184 -0
- package/src/forge/server.ts +100 -2
- package/src/forge/version.ts +1 -1
- package/src/forge/vue/index.ts +407 -0
- package/src/forge/workspace/change-summary.ts +209 -0
- package/src/forge/workspace/forge-cli.ts +14 -0
- package/src/forge/workspace/git-summary.ts +279 -0
- package/templates/agent-workroom/AGENTS.md +29 -0
- package/templates/agent-workroom/README.md +34 -0
- package/templates/agent-workroom/forge.config.ts +3 -0
- package/templates/agent-workroom/package.json +33 -0
- package/templates/agent-workroom/src/actions/indexAgentSignal.ts +10 -0
- package/templates/agent-workroom/src/commands/openWorkroom.ts +61 -0
- package/templates/agent-workroom/src/commands/recordAgentSignal.ts +119 -0
- package/templates/agent-workroom/src/commands/recordCheckRun.ts +52 -0
- package/templates/agent-workroom/src/forge/schema.ts +54 -0
- package/templates/agent-workroom/src/policies.ts +6 -0
- package/templates/agent-workroom/src/queries/listWorkrooms.ts +11 -0
- package/templates/agent-workroom/src/queries/liveWorkroom.ts +63 -0
- package/templates/agent-workroom/tsconfig.json +16 -0
- package/templates/agent-workroom/web/index.html +12 -0
- package/templates/agent-workroom/web/package.json +21 -0
- package/templates/agent-workroom/web/src/App.tsx +345 -0
- package/templates/agent-workroom/web/src/lib/forge.ts +13 -0
- package/templates/agent-workroom/web/src/main.tsx +13 -0
- package/templates/agent-workroom/web/src/styles.css +545 -0
- package/templates/agent-workroom/web/tsconfig.json +27 -0
- package/templates/b2b-support-web/package.json +2 -0
- package/templates/b2b-support-web/tsconfig.json +4 -1
- package/templates/b2b-support-web/web/package.json +1 -1
- package/templates/minimal-web/package.json +2 -1
- package/templates/minimal-web/tsconfig.json +3 -1
- package/templates/minimal-web/web/package.json +2 -2
- package/src/forge/_generated/actionSubscriptions.json +0 -2
- package/src/forge/_generated/actionSubscriptions.ts +0 -10
- package/src/forge/_generated/agentAdapterManifest.json +0 -2
- package/src/forge/_generated/agentAdapterManifest.ts +0 -73
- package/src/forge/_generated/agentContract.json +0 -2
- package/src/forge/_generated/agentContract.ts +0 -7696
- package/src/forge/_generated/agentQuickstart.md +0 -32
- package/src/forge/_generated/aiContext.ts +0 -59
- package/src/forge/_generated/aiModels.json +0 -2
- package/src/forge/_generated/aiModels.ts +0 -35
- package/src/forge/_generated/aiProviders.json +0 -2
- package/src/forge/_generated/aiProviders.ts +0 -23
- package/src/forge/_generated/aiRegistry.json +0 -2
- package/src/forge/_generated/aiRegistry.ts +0 -29
- package/src/forge/_generated/api.json +0 -2
- package/src/forge/_generated/api.ts +0 -8
- package/src/forge/_generated/appGraph.json +0 -2
- package/src/forge/_generated/appGraph.ts +0 -14667
- package/src/forge/_generated/appMap.md +0 -35
- package/src/forge/_generated/artifactManifest.json +0 -2
- package/src/forge/_generated/artifactManifest.ts +0 -7
- package/src/forge/_generated/authClaims.json +0 -2
- package/src/forge/_generated/authClaims.ts +0 -13
- package/src/forge/_generated/authConfig.json +0 -2
- package/src/forge/_generated/authConfig.ts +0 -17
- package/src/forge/_generated/authContext.ts +0 -23
- package/src/forge/_generated/authRegistry.json +0 -2
- package/src/forge/_generated/authRegistry.ts +0 -25
- package/src/forge/_generated/buildInfo.json +0 -2
- package/src/forge/_generated/buildInfo.ts +0 -9
- package/src/forge/_generated/capabilityMap.json +0 -2
- package/src/forge/_generated/capabilityMap.md +0 -15
- package/src/forge/_generated/capabilityMap.ts +0 -17
- package/src/forge/_generated/client.ts +0 -282
- package/src/forge/_generated/clientApi.ts +0 -9
- package/src/forge/_generated/clientManifest.json +0 -2
- package/src/forge/_generated/clientManifest.ts +0 -39
- package/src/forge/_generated/clientTypes.ts +0 -78
- package/src/forge/_generated/configRegistry.json +0 -2
- package/src/forge/_generated/configRegistry.ts +0 -4
- package/src/forge/_generated/dataGraph.json +0 -2
- package/src/forge/_generated/dataGraph.ts +0 -8
- package/src/forge/_generated/db.json +0 -2
- package/src/forge/_generated/db.ts +0 -2
- package/src/forge/_generated/dbSecurityManifest.json +0 -2
- package/src/forge/_generated/dbSecurityManifest.ts +0 -15
- package/src/forge/_generated/dbSessionContext.json +0 -2
- package/src/forge/_generated/dbSessionContext.ts +0 -39
- package/src/forge/_generated/deployManifest.json +0 -2
- package/src/forge/_generated/deployManifest.ts +0 -14
- package/src/forge/_generated/devManifest.json +0 -2
- package/src/forge/_generated/devManifest.ts +0 -47
- package/src/forge/_generated/envSchema.json +0 -2
- package/src/forge/_generated/envSchema.ts +0 -59
- package/src/forge/_generated/frontendGraph.json +0 -2
- package/src/forge/_generated/frontendGraph.ts +0 -27
- package/src/forge/_generated/importGuards.json +0 -2
- package/src/forge/_generated/importGuards.ts +0 -686
- package/src/forge/_generated/index.ts +0 -67
- package/src/forge/_generated/liveProductionManifest.json +0 -2
- package/src/forge/_generated/liveProductionManifest.ts +0 -23
- package/src/forge/_generated/liveProtocol.json +0 -2
- package/src/forge/_generated/liveProtocol.ts +0 -21
- package/src/forge/_generated/liveQueryRegistry.json +0 -2
- package/src/forge/_generated/liveQueryRegistry.ts +0 -9
- package/src/forge/_generated/liveTransportConfig.json +0 -2
- package/src/forge/_generated/liveTransportConfig.ts +0 -19
- package/src/forge/_generated/makeRegistry.json +0 -2
- package/src/forge/_generated/makeRegistry.ts +0 -163
- package/src/forge/_generated/makeTemplates.json +0 -2
- package/src/forge/_generated/makeTemplates.ts +0 -61
- package/src/forge/_generated/mockMap.json +0 -2
- package/src/forge/_generated/mockMap.ts +0 -7
- package/src/forge/_generated/operationPlaybooks.md +0 -147
- package/src/forge/_generated/packageGraph.json +0 -2
- package/src/forge/_generated/packageGraph.ts +0 -245249
- package/src/forge/_generated/packageUpgradeRegistry.json +0 -2
- package/src/forge/_generated/packageUpgradeRegistry.ts +0 -15
- package/src/forge/_generated/permissionMatrix.json +0 -2
- package/src/forge/_generated/permissionMatrix.ts +0 -7
- package/src/forge/_generated/policyRegistry.json +0 -2
- package/src/forge/_generated/policyRegistry.ts +0 -11
- package/src/forge/_generated/queryRegistry.json +0 -2
- package/src/forge/_generated/queryRegistry.ts +0 -9
- package/src/forge/_generated/react.d.ts +0 -22
- package/src/forge/_generated/react.ts +0 -29
- package/src/forge/_generated/reactManifest.json +0 -2
- package/src/forge/_generated/reactManifest.ts +0 -19
- package/src/forge/_generated/rlsPolicies.json +0 -2
- package/src/forge/_generated/rlsPolicies.sql +0 -34
- package/src/forge/_generated/rlsPolicies.ts +0 -6
- package/src/forge/_generated/runtimeGraph.json +0 -2
- package/src/forge/_generated/runtimeGraph.ts +0 -8
- package/src/forge/_generated/runtimeMatrix.json +0 -2
- package/src/forge/_generated/runtimeMatrix.ts +0 -327385
- package/src/forge/_generated/runtimeRegistry.ts +0 -2
- package/src/forge/_generated/runtimeRules.md +0 -79
- package/src/forge/_generated/secretRegistry.json +0 -2
- package/src/forge/_generated/secretRegistry.ts +0 -50
- package/src/forge/_generated/secretsContext.ts +0 -11
- package/src/forge/_generated/serverApi.ts +0 -10
- package/src/forge/_generated/sourceMapManifest.json +0 -2
- package/src/forge/_generated/sourceMapManifest.ts +0 -7
- package/src/forge/_generated/sqlPlan.json +0 -2
- package/src/forge/_generated/sqlPlan.ts +0 -88
- package/src/forge/_generated/subscriptionManifest.json +0 -2
- package/src/forge/_generated/subscriptionManifest.ts +0 -7
- package/src/forge/_generated/symbolicationManifest.json +0 -2
- package/src/forge/_generated/symbolicationManifest.ts +0 -17
- package/src/forge/_generated/telemetryRegistry.json +0 -2
- package/src/forge/_generated/telemetryRegistry.ts +0 -9
- package/src/forge/_generated/telemetrySinks.json +0 -2
- package/src/forge/_generated/telemetrySinks.ts +0 -11
- package/src/forge/_generated/tenantScope.json +0 -2
- package/src/forge/_generated/tenantScope.ts +0 -8
- package/src/forge/_generated/testGraph.json +0 -2
- package/src/forge/_generated/testGraph.ts +0 -3108
- package/src/forge/_generated/testPlanRegistry.json +0 -2
- package/src/forge/_generated/testPlanRegistry.ts +0 -33
- package/src/forge/_generated/uiRoutes.json +0 -2
- package/src/forge/_generated/uiRoutes.ts +0 -16
- package/src/forge/_generated/uiScenarios.json +0 -2
- package/src/forge/_generated/uiScenarios.ts +0 -30
- package/src/forge/_generated/uiTestManifest.json +0 -2
- package/src/forge/_generated/uiTestManifest.ts +0 -27
- package/src/forge/_generated/workflowRegistry.json +0 -2
- package/src/forge/_generated/workflowRegistry.ts +0 -9
- package/src/forge/_generated/workflowSubscriptions.json +0 -2
- package/src/forge/_generated/workflowSubscriptions.ts +0 -10
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { createDiagnostic } from "../diagnostics/create.ts";
|
|
2
|
+
import type { Diagnostic } from "../types/diagnostic.ts";
|
|
3
|
+
import {
|
|
4
|
+
FORGE_EXTERNAL_MANIFEST_PROTOCOL_VERSION,
|
|
5
|
+
type ForgeExternalEntryKind,
|
|
6
|
+
type ForgeExternalEntryRisk,
|
|
7
|
+
type ForgeExternalManifest,
|
|
8
|
+
type ForgeExternalManifestEntry,
|
|
9
|
+
type ForgeExternalManifestRegistryFile,
|
|
10
|
+
type ForgeExternalTransportKind,
|
|
11
|
+
type ForgeExternalTransactionMode,
|
|
12
|
+
} from "./types.ts";
|
|
13
|
+
|
|
14
|
+
const TRANSPORTS: ForgeExternalTransportKind[] = ["http", "grpc", "stdio"];
|
|
15
|
+
const ENTRY_KINDS: ForgeExternalEntryKind[] = ["command", "query"];
|
|
16
|
+
const RISKS: ForgeExternalEntryRisk[] = ["read", "write", "destructive", "external"];
|
|
17
|
+
const TRANSACTIONS: ForgeExternalTransactionMode[] = [
|
|
18
|
+
"read-only",
|
|
19
|
+
"external-managed",
|
|
20
|
+
"forge-managed",
|
|
21
|
+
"saga",
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
function isObject(value: unknown): value is Record<string, unknown> {
|
|
25
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isString(value: unknown): value is string {
|
|
29
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function stringArray(value: unknown): value is string[] {
|
|
33
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function commandArgsArray(value: unknown): value is string[] {
|
|
37
|
+
return Array.isArray(value) &&
|
|
38
|
+
value.length > 0 &&
|
|
39
|
+
typeof value[0] === "string" &&
|
|
40
|
+
value[0].length > 0 &&
|
|
41
|
+
value.every((item) => typeof item === "string");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function externalDiagnostic(
|
|
45
|
+
severity: Diagnostic["severity"],
|
|
46
|
+
code: string,
|
|
47
|
+
message: string,
|
|
48
|
+
file?: string,
|
|
49
|
+
fixHint?: string,
|
|
50
|
+
): Diagnostic {
|
|
51
|
+
return createDiagnostic({
|
|
52
|
+
severity,
|
|
53
|
+
code,
|
|
54
|
+
message,
|
|
55
|
+
...(file ? { file } : {}),
|
|
56
|
+
...(fixHint ? { fixHint } : {}),
|
|
57
|
+
docs: ["docs/forge-protocol.md", "schemas/forge-manifest.schema.json"],
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function validateEntry(
|
|
62
|
+
entry: unknown,
|
|
63
|
+
index: number,
|
|
64
|
+
serviceName: string,
|
|
65
|
+
diagnostics: Diagnostic[],
|
|
66
|
+
file?: string,
|
|
67
|
+
): ForgeExternalManifestEntry | null {
|
|
68
|
+
if (!isObject(entry)) {
|
|
69
|
+
diagnostics.push(externalDiagnostic(
|
|
70
|
+
"error",
|
|
71
|
+
"FORGE_EXTERNAL_ENTRY_OBJECT",
|
|
72
|
+
`external manifest entry at index ${index} must be an object`,
|
|
73
|
+
file,
|
|
74
|
+
));
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const name = entry.name;
|
|
79
|
+
const kind = entry.kind;
|
|
80
|
+
if (!isString(name)) {
|
|
81
|
+
diagnostics.push(externalDiagnostic(
|
|
82
|
+
"error",
|
|
83
|
+
"FORGE_EXTERNAL_ENTRY_NAME",
|
|
84
|
+
`external manifest entry at index ${index} must have a non-empty name`,
|
|
85
|
+
file,
|
|
86
|
+
));
|
|
87
|
+
}
|
|
88
|
+
if (!ENTRY_KINDS.includes(kind as ForgeExternalEntryKind)) {
|
|
89
|
+
diagnostics.push(externalDiagnostic(
|
|
90
|
+
"error",
|
|
91
|
+
"FORGE_EXTERNAL_ENTRY_KIND",
|
|
92
|
+
`external manifest entry '${String(name || index)}' must be kind command or query`,
|
|
93
|
+
file,
|
|
94
|
+
));
|
|
95
|
+
}
|
|
96
|
+
if (entry.effects !== undefined && !stringArray(entry.effects)) {
|
|
97
|
+
diagnostics.push(externalDiagnostic(
|
|
98
|
+
"error",
|
|
99
|
+
"FORGE_EXTERNAL_ENTRY_EFFECTS",
|
|
100
|
+
`external manifest entry '${String(name || index)}' effects must be a string array`,
|
|
101
|
+
file,
|
|
102
|
+
));
|
|
103
|
+
}
|
|
104
|
+
if (entry.risk !== undefined && !RISKS.includes(entry.risk as ForgeExternalEntryRisk)) {
|
|
105
|
+
diagnostics.push(externalDiagnostic(
|
|
106
|
+
"error",
|
|
107
|
+
"FORGE_EXTERNAL_ENTRY_RISK",
|
|
108
|
+
`external manifest entry '${String(name || index)}' has unsupported risk '${String(entry.risk)}'`,
|
|
109
|
+
file,
|
|
110
|
+
));
|
|
111
|
+
}
|
|
112
|
+
if (
|
|
113
|
+
entry.transaction !== undefined &&
|
|
114
|
+
!TRANSACTIONS.includes(entry.transaction as ForgeExternalTransactionMode)
|
|
115
|
+
) {
|
|
116
|
+
diagnostics.push(externalDiagnostic(
|
|
117
|
+
"error",
|
|
118
|
+
"FORGE_EXTERNAL_ENTRY_TRANSACTION",
|
|
119
|
+
`external manifest entry '${String(name || index)}' has unsupported transaction mode '${String(entry.transaction)}'`,
|
|
120
|
+
file,
|
|
121
|
+
));
|
|
122
|
+
}
|
|
123
|
+
if (
|
|
124
|
+
entry.kind === "query" &&
|
|
125
|
+
entry.transaction !== undefined &&
|
|
126
|
+
entry.transaction !== "read-only"
|
|
127
|
+
) {
|
|
128
|
+
diagnostics.push(externalDiagnostic(
|
|
129
|
+
"error",
|
|
130
|
+
"FORGE_EXTERNAL_QUERY_TRANSACTION",
|
|
131
|
+
`external query '${serviceName}.${String(name)}' must use transaction read-only when transaction is declared`,
|
|
132
|
+
file,
|
|
133
|
+
"Declare command for writes, or set transaction to read-only for external queries.",
|
|
134
|
+
));
|
|
135
|
+
}
|
|
136
|
+
if (entry.kind === "query" && entry.risk !== undefined && entry.risk !== "read") {
|
|
137
|
+
diagnostics.push(externalDiagnostic(
|
|
138
|
+
"error",
|
|
139
|
+
"FORGE_EXTERNAL_QUERY_RISK",
|
|
140
|
+
`external query '${serviceName}.${String(name)}' must use risk read when risk is declared`,
|
|
141
|
+
file,
|
|
142
|
+
));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!isString(name) || !ENTRY_KINDS.includes(kind as ForgeExternalEntryKind)) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
name,
|
|
151
|
+
kind: kind as ForgeExternalEntryKind,
|
|
152
|
+
...(isString(entry.description) ? { description: entry.description } : {}),
|
|
153
|
+
...(isString(entry.path) ? { path: entry.path } : {}),
|
|
154
|
+
...(entry.method === "GET" || entry.method === "POST" ? { method: entry.method } : {}),
|
|
155
|
+
...(entry.inputSchema !== undefined ? { inputSchema: entry.inputSchema } : {}),
|
|
156
|
+
...(entry.outputSchema !== undefined ? { outputSchema: entry.outputSchema } : {}),
|
|
157
|
+
...(isString(entry.policy) ? { policy: entry.policy } : {}),
|
|
158
|
+
...(typeof entry.tenantScoped === "boolean" ? { tenantScoped: entry.tenantScoped } : {}),
|
|
159
|
+
...(TRANSACTIONS.includes(entry.transaction as ForgeExternalTransactionMode)
|
|
160
|
+
? { transaction: entry.transaction as ForgeExternalTransactionMode }
|
|
161
|
+
: {}),
|
|
162
|
+
...(RISKS.includes(entry.risk as ForgeExternalEntryRisk)
|
|
163
|
+
? { risk: entry.risk as ForgeExternalEntryRisk }
|
|
164
|
+
: {}),
|
|
165
|
+
...(typeof entry.needsApproval === "boolean" ? { needsApproval: entry.needsApproval } : {}),
|
|
166
|
+
...(stringArray(entry.effects) ? { effects: entry.effects } : {}),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function validateExternalManifest(
|
|
171
|
+
value: unknown,
|
|
172
|
+
options: { file?: string } = {},
|
|
173
|
+
): { manifest: ForgeExternalManifest | null; diagnostics: Diagnostic[] } {
|
|
174
|
+
const diagnostics: Diagnostic[] = [];
|
|
175
|
+
if (!isObject(value)) {
|
|
176
|
+
return {
|
|
177
|
+
manifest: null,
|
|
178
|
+
diagnostics: [
|
|
179
|
+
externalDiagnostic(
|
|
180
|
+
"error",
|
|
181
|
+
"FORGE_EXTERNAL_MANIFEST_OBJECT",
|
|
182
|
+
"forge external manifest must be a JSON object",
|
|
183
|
+
options.file,
|
|
184
|
+
),
|
|
185
|
+
],
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (value.forgeProtocol !== FORGE_EXTERNAL_MANIFEST_PROTOCOL_VERSION) {
|
|
190
|
+
diagnostics.push(externalDiagnostic(
|
|
191
|
+
"error",
|
|
192
|
+
"FORGE_EXTERNAL_PROTOCOL_VERSION",
|
|
193
|
+
`forgeProtocol must be '${FORGE_EXTERNAL_MANIFEST_PROTOCOL_VERSION}'`,
|
|
194
|
+
options.file,
|
|
195
|
+
));
|
|
196
|
+
}
|
|
197
|
+
if (!isString(value.language)) {
|
|
198
|
+
diagnostics.push(externalDiagnostic(
|
|
199
|
+
"error",
|
|
200
|
+
"FORGE_EXTERNAL_LANGUAGE",
|
|
201
|
+
"external manifest must declare a non-empty language",
|
|
202
|
+
options.file,
|
|
203
|
+
));
|
|
204
|
+
}
|
|
205
|
+
if (!isObject(value.service)) {
|
|
206
|
+
diagnostics.push(externalDiagnostic(
|
|
207
|
+
"error",
|
|
208
|
+
"FORGE_EXTERNAL_SERVICE",
|
|
209
|
+
"external manifest must declare a service object",
|
|
210
|
+
options.file,
|
|
211
|
+
));
|
|
212
|
+
}
|
|
213
|
+
if (!Array.isArray(value.entries)) {
|
|
214
|
+
diagnostics.push(externalDiagnostic(
|
|
215
|
+
"error",
|
|
216
|
+
"FORGE_EXTERNAL_ENTRIES",
|
|
217
|
+
"external manifest must declare an entries array",
|
|
218
|
+
options.file,
|
|
219
|
+
));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const service = isObject(value.service) ? value.service : {};
|
|
223
|
+
if (!isString(service.name)) {
|
|
224
|
+
diagnostics.push(externalDiagnostic(
|
|
225
|
+
"error",
|
|
226
|
+
"FORGE_EXTERNAL_SERVICE_NAME",
|
|
227
|
+
"external service must have a non-empty name",
|
|
228
|
+
options.file,
|
|
229
|
+
));
|
|
230
|
+
}
|
|
231
|
+
if (!TRANSPORTS.includes(service.transport as ForgeExternalTransportKind)) {
|
|
232
|
+
diagnostics.push(externalDiagnostic(
|
|
233
|
+
"error",
|
|
234
|
+
"FORGE_EXTERNAL_SERVICE_TRANSPORT",
|
|
235
|
+
`external service '${String(service.name || "unknown")}' must use transport http, grpc, or stdio`,
|
|
236
|
+
options.file,
|
|
237
|
+
));
|
|
238
|
+
}
|
|
239
|
+
if (service.transport === "http" && !isString(service.baseUrl)) {
|
|
240
|
+
diagnostics.push(externalDiagnostic(
|
|
241
|
+
"error",
|
|
242
|
+
"FORGE_EXTERNAL_SERVICE_BASE_URL",
|
|
243
|
+
`external service '${String(service.name || "unknown")}' uses http transport and must declare a non-empty baseUrl`,
|
|
244
|
+
options.file,
|
|
245
|
+
"Set service.baseUrl to the external runtime base URL.",
|
|
246
|
+
));
|
|
247
|
+
}
|
|
248
|
+
const hasCommand = isString(service.command);
|
|
249
|
+
const hasCommandArgs = commandArgsArray(service.commandArgs);
|
|
250
|
+
if (service.commandArgs !== undefined && !hasCommandArgs) {
|
|
251
|
+
diagnostics.push(externalDiagnostic(
|
|
252
|
+
"error",
|
|
253
|
+
"FORGE_EXTERNAL_SERVICE_COMMAND_ARGS",
|
|
254
|
+
`external service '${String(service.name || "unknown")}' commandArgs must be a non-empty string array`,
|
|
255
|
+
options.file,
|
|
256
|
+
"Set service.commandArgs to an array whose first item is the executable.",
|
|
257
|
+
));
|
|
258
|
+
}
|
|
259
|
+
if (service.transport === "stdio" && !hasCommand && !hasCommandArgs) {
|
|
260
|
+
diagnostics.push(externalDiagnostic(
|
|
261
|
+
"error",
|
|
262
|
+
"FORGE_EXTERNAL_SERVICE_COMMAND",
|
|
263
|
+
`external service '${String(service.name || "unknown")}' uses stdio transport and must declare a non-empty command or commandArgs`,
|
|
264
|
+
options.file,
|
|
265
|
+
"Set service.command to a command line string or service.commandArgs to a structured executable/args array.",
|
|
266
|
+
));
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const entries = Array.isArray(value.entries)
|
|
270
|
+
? value.entries
|
|
271
|
+
.map((entry, index) => validateEntry(entry, index, String(service.name || "unknown"), diagnostics, options.file))
|
|
272
|
+
.filter((entry): entry is ForgeExternalManifestEntry => entry !== null)
|
|
273
|
+
: [];
|
|
274
|
+
const seen = new Set<string>();
|
|
275
|
+
for (const entry of entries) {
|
|
276
|
+
const key = `${entry.kind}:${entry.name}`;
|
|
277
|
+
if (seen.has(key)) {
|
|
278
|
+
diagnostics.push(externalDiagnostic(
|
|
279
|
+
"error",
|
|
280
|
+
"FORGE_EXTERNAL_ENTRY_DUPLICATE",
|
|
281
|
+
`external service '${String(service.name)}' declares duplicate ${entry.kind} '${entry.name}'`,
|
|
282
|
+
options.file,
|
|
283
|
+
));
|
|
284
|
+
}
|
|
285
|
+
seen.add(key);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
|
|
289
|
+
return { manifest: null, diagnostics };
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return {
|
|
293
|
+
manifest: {
|
|
294
|
+
forgeProtocol: FORGE_EXTERNAL_MANIFEST_PROTOCOL_VERSION,
|
|
295
|
+
language: value.language as ForgeExternalManifest["language"],
|
|
296
|
+
...(isString(value.framework) ? { framework: value.framework } : {}),
|
|
297
|
+
service: {
|
|
298
|
+
name: service.name as string,
|
|
299
|
+
transport: service.transport as ForgeExternalTransportKind,
|
|
300
|
+
...(isString(service.baseUrl) ? { baseUrl: service.baseUrl } : {}),
|
|
301
|
+
...(hasCommand ? { command: service.command as string } : {}),
|
|
302
|
+
...(hasCommandArgs ? { commandArgs: service.commandArgs as string[] } : {}),
|
|
303
|
+
...(isString(service.health) ? { health: service.health } : {}),
|
|
304
|
+
},
|
|
305
|
+
entries,
|
|
306
|
+
...(isObject(value.schemas) ? { schemas: value.schemas } : {}),
|
|
307
|
+
},
|
|
308
|
+
diagnostics,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export function validateExternalManifestRegistry(
|
|
313
|
+
value: unknown,
|
|
314
|
+
options: { file?: string } = {},
|
|
315
|
+
): { registry: ForgeExternalManifestRegistryFile | null; diagnostics: Diagnostic[] } {
|
|
316
|
+
if (!isObject(value)) {
|
|
317
|
+
return {
|
|
318
|
+
registry: null,
|
|
319
|
+
diagnostics: [
|
|
320
|
+
externalDiagnostic(
|
|
321
|
+
"error",
|
|
322
|
+
"FORGE_EXTERNAL_REGISTRY_OBJECT",
|
|
323
|
+
"external manifest registry must be a JSON object",
|
|
324
|
+
options.file,
|
|
325
|
+
),
|
|
326
|
+
],
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
if (value.schemaVersion !== "0.1.0") {
|
|
330
|
+
return {
|
|
331
|
+
registry: null,
|
|
332
|
+
diagnostics: [
|
|
333
|
+
externalDiagnostic(
|
|
334
|
+
"error",
|
|
335
|
+
"FORGE_EXTERNAL_REGISTRY_VERSION",
|
|
336
|
+
"external manifest registry schemaVersion must be '0.1.0'",
|
|
337
|
+
options.file,
|
|
338
|
+
),
|
|
339
|
+
],
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
if (!Array.isArray(value.manifests)) {
|
|
343
|
+
return {
|
|
344
|
+
registry: null,
|
|
345
|
+
diagnostics: [
|
|
346
|
+
externalDiagnostic(
|
|
347
|
+
"error",
|
|
348
|
+
"FORGE_EXTERNAL_REGISTRY_MANIFESTS",
|
|
349
|
+
"external manifest registry must include a manifests array",
|
|
350
|
+
options.file,
|
|
351
|
+
),
|
|
352
|
+
],
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const diagnostics: Diagnostic[] = [];
|
|
357
|
+
const manifests: ForgeExternalManifest[] = [];
|
|
358
|
+
for (const [index, manifestValue] of value.manifests.entries()) {
|
|
359
|
+
const result = validateExternalManifest(manifestValue, {
|
|
360
|
+
file: options.file ? `${options.file}#manifests/${index}` : undefined,
|
|
361
|
+
});
|
|
362
|
+
diagnostics.push(...result.diagnostics);
|
|
363
|
+
if (result.manifest) {
|
|
364
|
+
manifests.push(result.manifest);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return {
|
|
368
|
+
registry: diagnostics.some((diagnostic) => diagnostic.severity === "error")
|
|
369
|
+
? null
|
|
370
|
+
: { schemaVersion: "0.1.0", manifests },
|
|
371
|
+
diagnostics,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
@@ -13,6 +13,7 @@ import { createDiagnostic } from "../diagnostics/create.ts";
|
|
|
13
13
|
|
|
14
14
|
const WEB_ROOT = "web";
|
|
15
15
|
const API_URL_ENV = "NEXT_PUBLIC_FORGE_URL";
|
|
16
|
+
const NUXT_API_URL_ENV = "NUXT_PUBLIC_FORGE_URL";
|
|
16
17
|
const VITE_API_URL_ENV = "VITE_FORGE_URL";
|
|
17
18
|
|
|
18
19
|
function toPosix(path: string): string {
|
|
@@ -43,7 +44,7 @@ function walkFiles(root: string): string[] {
|
|
|
43
44
|
for (const entry of nodeFileSystem.readDir(dir)) {
|
|
44
45
|
const absolute = join(dir, entry.name);
|
|
45
46
|
if (entry.isDirectory) {
|
|
46
|
-
if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist") {
|
|
47
|
+
if (entry.name === "node_modules" || entry.name === ".next" || entry.name === ".nuxt" || entry.name === "dist" || entry.name === ".output") {
|
|
47
48
|
continue;
|
|
48
49
|
}
|
|
49
50
|
walk(absolute);
|
|
@@ -71,6 +72,14 @@ function detectFramework(webRoot: string): FrontendGraph["framework"] {
|
|
|
71
72
|
if (deps.next || nodeFileSystem.exists(join(webRoot, "next.config.ts"))) {
|
|
72
73
|
return "next";
|
|
73
74
|
}
|
|
75
|
+
if (
|
|
76
|
+
deps.nuxt ||
|
|
77
|
+
nodeFileSystem.exists(join(webRoot, "nuxt.config.ts")) ||
|
|
78
|
+
nodeFileSystem.exists(join(webRoot, "nuxt.config.js")) ||
|
|
79
|
+
nodeFileSystem.exists(join(webRoot, "nuxt.config.mjs"))
|
|
80
|
+
) {
|
|
81
|
+
return "nuxt";
|
|
82
|
+
}
|
|
74
83
|
if (deps.vite || nodeFileSystem.exists(join(webRoot, "vite.config.ts"))) {
|
|
75
84
|
return "vite";
|
|
76
85
|
}
|
|
@@ -105,6 +114,27 @@ function routePathForFile(webRoot: string, file: string): string | null {
|
|
|
105
114
|
if (rel === "app/page.tsx" || rel === "app/page.ts" || rel === "app/page.jsx" || rel === "app/page.js") {
|
|
106
115
|
return "/";
|
|
107
116
|
}
|
|
117
|
+
if (rel === "app.vue") {
|
|
118
|
+
return "/";
|
|
119
|
+
}
|
|
120
|
+
if (rel === "pages/index.vue") {
|
|
121
|
+
return "/";
|
|
122
|
+
}
|
|
123
|
+
const vueRoute = rel.match(/^pages\/(.+)\.vue$/);
|
|
124
|
+
if (vueRoute) {
|
|
125
|
+
const route = vueRoute[1]
|
|
126
|
+
.split("/")
|
|
127
|
+
.map((segment) => {
|
|
128
|
+
if (segment === "index") {
|
|
129
|
+
return "";
|
|
130
|
+
}
|
|
131
|
+
const dynamic = segment.match(/^\[([A-Za-z0-9_]+)\]$/);
|
|
132
|
+
return dynamic ? `:${dynamic[1]}` : segment;
|
|
133
|
+
})
|
|
134
|
+
.filter(Boolean)
|
|
135
|
+
.join("/");
|
|
136
|
+
return `/${route}`;
|
|
137
|
+
}
|
|
108
138
|
const match = rel.match(/^app\/(.+)\/page\.(tsx|ts|jsx|js)$/);
|
|
109
139
|
if (match) {
|
|
110
140
|
const route = match[1]
|
|
@@ -117,7 +147,7 @@ function routePathForFile(webRoot: string, file: string): string | null {
|
|
|
117
147
|
}
|
|
118
148
|
|
|
119
149
|
function componentNameForFile(file: string): string {
|
|
120
|
-
return basename(file).replace(/\.(tsx|ts|jsx|js)$/, "");
|
|
150
|
+
return basename(file).replace(/\.(tsx|ts|jsx|js|vue)$/, "");
|
|
121
151
|
}
|
|
122
152
|
|
|
123
153
|
function componentNameForText(file: string, text: string): string {
|
|
@@ -134,6 +164,14 @@ function componentNameForText(file: string, text: string): string {
|
|
|
134
164
|
|
|
135
165
|
function isComponentFile(webRoot: string, file: string, text: string): boolean {
|
|
136
166
|
const rel = toPosix(relative(webRoot, file));
|
|
167
|
+
if (file.endsWith(".vue")) {
|
|
168
|
+
return (
|
|
169
|
+
rel === "app.vue" ||
|
|
170
|
+
rel.startsWith("components/") ||
|
|
171
|
+
rel.startsWith("src/components/") ||
|
|
172
|
+
rel.startsWith("pages/")
|
|
173
|
+
);
|
|
174
|
+
}
|
|
137
175
|
if (!/\.(tsx|jsx)$/.test(file)) {
|
|
138
176
|
return false;
|
|
139
177
|
}
|
|
@@ -206,6 +244,9 @@ function devCommandFor(webRoot: string, framework: FrontendGraph["framework"]):
|
|
|
206
244
|
}
|
|
207
245
|
|
|
208
246
|
function apiEnvFor(framework: FrontendGraph["framework"]): string {
|
|
247
|
+
if (framework === "nuxt") {
|
|
248
|
+
return NUXT_API_URL_ENV;
|
|
249
|
+
}
|
|
209
250
|
return framework === "vite" || framework === "static" ? VITE_API_URL_ENV : API_URL_ENV;
|
|
210
251
|
}
|
|
211
252
|
|
|
@@ -224,7 +265,7 @@ function stringProp(text: string, prop: "userId" | "tenantId" | "role"): string
|
|
|
224
265
|
}
|
|
225
266
|
|
|
226
267
|
function defaultWebPort(framework: FrontendGraph["framework"]): number {
|
|
227
|
-
return framework === "next" ? 3000 : 5173;
|
|
268
|
+
return framework === "next" || framework === "nuxt" ? 3000 : 5173;
|
|
228
269
|
}
|
|
229
270
|
|
|
230
271
|
function componentNamesInText(text: string, components: FrontendComponentInfo[]): string[] {
|
|
@@ -299,7 +340,7 @@ export function buildFrontendGraph(input: {
|
|
|
299
340
|
const defaultApiUrl = `http://127.0.0.1:${input.apiPort ?? 3765}`;
|
|
300
341
|
const devUrl = `http://127.0.0.1:${input.webPort ?? defaultWebPort(framework)}`;
|
|
301
342
|
const files = walkFiles(webRoot);
|
|
302
|
-
const sourceFiles = files.filter((file) => /\.(tsx|ts|jsx|js|html)$/.test(file));
|
|
343
|
+
const sourceFiles = files.filter((file) => /\.(tsx|ts|jsx|js|vue|html)$/.test(file));
|
|
303
344
|
const routes: FrontendRouteInfo[] = [];
|
|
304
345
|
const components: FrontendComponentInfo[] = [];
|
|
305
346
|
const providers: FrontendProviderInfo[] = [];
|
|
@@ -314,7 +355,9 @@ export function buildFrontendGraph(input: {
|
|
|
314
355
|
rel === "web/lib/forge.ts" ||
|
|
315
356
|
rel === "web/lib/forge.tsx" ||
|
|
316
357
|
rel === "web/src/lib/forge.ts" ||
|
|
317
|
-
rel === "web/src/lib/forge.tsx"
|
|
358
|
+
rel === "web/src/lib/forge.tsx" ||
|
|
359
|
+
rel === "web/composables/forge.ts" ||
|
|
360
|
+
rel === "web/plugins/forge.ts";
|
|
318
361
|
textByRel.set(rel, text);
|
|
319
362
|
const uses = detectUses(text, input.clientManifest);
|
|
320
363
|
if (isComponentFile(webRoot, file, text)) {
|
|
@@ -335,11 +378,32 @@ export function buildFrontendGraph(input: {
|
|
|
335
378
|
...(devAuth && stringProp(text, "role") ? { devAuthRole: stringProp(text, "role") } : {}),
|
|
336
379
|
});
|
|
337
380
|
}
|
|
381
|
+
if (
|
|
382
|
+
text.includes("provideForge({") ||
|
|
383
|
+
text.includes("vueApp.use(ForgeVuePlugin") ||
|
|
384
|
+
text.includes("app.use(ForgeVuePlugin")
|
|
385
|
+
) {
|
|
386
|
+
const devAuth =
|
|
387
|
+
text.includes("devAuth") ||
|
|
388
|
+
(text.includes("userId") && text.includes("tenantId") && text.includes("role"));
|
|
389
|
+
providers.push({
|
|
390
|
+
name: framework === "nuxt" ? "ForgeNuxtPlugin" : "ForgeVueProvider",
|
|
391
|
+
file: rel,
|
|
392
|
+
...(text.includes(NUXT_API_URL_ENV) ? { apiUrlEnv: NUXT_API_URL_ENV } : {}),
|
|
393
|
+
...(text.includes(VITE_API_URL_ENV) ? { apiUrlEnv: VITE_API_URL_ENV } : {}),
|
|
394
|
+
devAuth,
|
|
395
|
+
...(devAuth && stringProp(text, "userId") ? { devAuthUserId: stringProp(text, "userId") } : {}),
|
|
396
|
+
...(devAuth && stringProp(text, "tenantId") ? { devAuthTenantId: stringProp(text, "tenantId") } : {}),
|
|
397
|
+
...(devAuth && stringProp(text, "role") ? { devAuthRole: stringProp(text, "role") } : {}),
|
|
398
|
+
});
|
|
399
|
+
}
|
|
338
400
|
if (
|
|
339
401
|
rel === "web/lib/forge.ts" ||
|
|
340
402
|
rel === "web/lib/forge.tsx" ||
|
|
341
403
|
rel === "web/src/lib/forge.ts" ||
|
|
342
|
-
rel === "web/src/lib/forge.tsx"
|
|
404
|
+
rel === "web/src/lib/forge.tsx" ||
|
|
405
|
+
rel === "web/composables/forge.ts" ||
|
|
406
|
+
rel === "web/plugins/forge.ts"
|
|
343
407
|
) {
|
|
344
408
|
bridgeFiles.push(rel);
|
|
345
409
|
}
|
|
@@ -350,7 +414,7 @@ export function buildFrontendGraph(input: {
|
|
|
350
414
|
message: "frontend imports generated files directly; prefer the local web/lib/forge bridge",
|
|
351
415
|
file: rel,
|
|
352
416
|
fixHint: "Import generated client APIs through web/lib/forge.ts so agents and humans have one stable frontend bridge.",
|
|
353
|
-
suggestedCommands: ["forge inspect frontend --json",
|
|
417
|
+
suggestedCommands: ["forge inspect frontend --json", `forge make ui --framework ${framework === "nuxt" ? "nuxt" : "vite"} --dry-run --json`],
|
|
354
418
|
docs: ["src/forge/_generated/frontendGraph.json", "src/forge/_generated/appMap.md"],
|
|
355
419
|
}));
|
|
356
420
|
}
|
|
@@ -401,9 +465,13 @@ export function buildFrontendGraph(input: {
|
|
|
401
465
|
diagnostics.push(createDiagnostic({
|
|
402
466
|
severity: "warning",
|
|
403
467
|
code: "FORGE_FRONTEND_PROVIDER_MISSING",
|
|
404
|
-
message:
|
|
405
|
-
|
|
406
|
-
|
|
468
|
+
message: framework === "nuxt"
|
|
469
|
+
? "Nuxt app does not expose a Forge plugin; generated composables may not be wired"
|
|
470
|
+
: "web app does not expose a ForgeProvider; generated hooks may not be wired",
|
|
471
|
+
fixHint: framework === "nuxt"
|
|
472
|
+
? "Create web/plugins/forge.ts and call provideForge with runtimeConfig.public.forgeUrl and devAuth for local development."
|
|
473
|
+
: "Mount ForgeProvider once in the web app root/provider layer and pass devAuth for local development.",
|
|
474
|
+
suggestedCommands: ["forge inspect frontend --json", `forge make ui --framework ${framework === "nuxt" ? "nuxt" : "vite"} --dry-run --json`],
|
|
407
475
|
docs: ["src/forge/_generated/frontendGraph.json", "AGENTS.md"],
|
|
408
476
|
}));
|
|
409
477
|
}
|
|
@@ -411,9 +479,13 @@ export function buildFrontendGraph(input: {
|
|
|
411
479
|
diagnostics.push(createDiagnostic({
|
|
412
480
|
severity: "warning",
|
|
413
481
|
code: "FORGE_FRONTEND_BRIDGE_MISSING",
|
|
414
|
-
message:
|
|
415
|
-
|
|
416
|
-
|
|
482
|
+
message: framework === "nuxt"
|
|
483
|
+
? "web/composables/forge.ts bridge is missing; agents may use fragile generated import paths"
|
|
484
|
+
: "web/**/lib/forge.ts bridge is missing; agents may use fragile generated import paths",
|
|
485
|
+
fixHint: framework === "nuxt"
|
|
486
|
+
? "Create web/composables/forge.ts and re-export api plus generated Forge Vue composables from src/forge/_generated."
|
|
487
|
+
: "Create web/lib/forge.ts or web/src/lib/forge.ts and re-export api, client, ForgeProvider, and generated hooks from src/forge/_generated.",
|
|
488
|
+
suggestedCommands: [`forge make ui --framework ${framework === "nuxt" ? "nuxt" : "vite"} --dry-run --json`, "forge generate"],
|
|
417
489
|
docs: ["src/forge/_generated/frontendGraph.json", "AGENTS.md"],
|
|
418
490
|
}));
|
|
419
491
|
}
|