forgeos 0.1.0-alpha.6 → 0.1.0-alpha.60
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 +10 -0
- package/AGENTS.md +142 -90
- package/CHANGELOG.md +735 -8
- package/LICENSE +21 -0
- package/README.md +65 -6
- 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-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/bin/forge.mjs +18 -0
- package/docs/cair-protocol.md +103 -0
- package/docs/changelog.md +968 -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/package.json +28 -1
- package/schemas/forge-manifest.schema.json +57 -0
- package/scripts/field-test-forgeos.mjs +1012 -0
- package/src/forge/_generated/releaseManifest.json +1 -2
- package/src/forge/_generated/releaseManifest.ts +3 -3
- package/src/forge/agent-adapters/index.ts +1584 -125
- package/src/forge/agent-adapters/types.ts +224 -1
- package/src/forge/agent-memory/bridge.ts +1333 -0
- package/src/forge/agent-memory/context-pack.ts +277 -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 +204 -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 +16 -1
- package/src/forge/cli/auth.ts +357 -10
- package/src/forge/cli/authmd.ts +441 -0
- package/src/forge/cli/baseline.ts +112 -0
- package/src/forge/cli/build.ts +20 -4
- package/src/forge/cli/changed.ts +437 -0
- package/src/forge/cli/codex-app-server.ts +877 -0
- package/src/forge/cli/commands.ts +1798 -20
- package/src/forge/cli/db.ts +209 -2
- package/src/forge/cli/deploy.ts +1288 -0
- package/src/forge/cli/deps.ts +150 -23
- package/src/forge/cli/dev.ts +1137 -53
- package/src/forge/cli/docs.ts +265 -0
- package/src/forge/cli/doctor.ts +297 -0
- package/src/forge/cli/field-test.ts +566 -0
- package/src/forge/cli/handoff.ts +336 -0
- package/src/forge/cli/index.ts +1 -0
- package/src/forge/cli/last-run.ts +84 -0
- package/src/forge/cli/main.ts +128 -3
- package/src/forge/cli/new.ts +153 -13
- package/src/forge/cli/next-actions.ts +23 -0
- package/src/forge/cli/output.ts +398 -6
- package/src/forge/cli/parse.ts +1147 -38
- package/src/forge/cli/progress.ts +51 -0
- package/src/forge/cli/query.ts +32 -0
- package/src/forge/cli/release.ts +35 -11
- package/src/forge/cli/run.ts +42 -0
- package/src/forge/cli/secrets.ts +131 -1
- package/src/forge/cli/seed.ts +581 -0
- package/src/forge/cli/self-host.ts +56 -14
- package/src/forge/cli/studio.ts +2218 -0
- package/src/forge/cli/verify.ts +1455 -32
- package/src/forge/cli/windows.ts +23 -0
- package/src/forge/cli/workos.ts +3315 -0
- package/src/forge/compiler/agent-contract/build.ts +728 -64
- package/src/forge/compiler/agent-contract/types.ts +45 -2
- package/src/forge/compiler/ai-registry/parse.ts +71 -2
- package/src/forge/compiler/api-surface/build.ts +47 -0
- package/src/forge/compiler/app-graph/build.ts +112 -9
- package/src/forge/compiler/app-graph/extract.ts +107 -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 +295 -13
- package/src/forge/compiler/data-graph/build.ts +29 -1
- package/src/forge/compiler/data-graph/parse.ts +20 -4
- package/src/forge/compiler/data-graph/sql/ddl.ts +144 -31
- 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/diagnostics/codes.ts +38 -0
- package/src/forge/compiler/diagnostics/create.ts +28 -2
- 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 +9 -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 +142 -14
- package/src/forge/compiler/integration/add.ts +991 -33
- package/src/forge/compiler/integration/plan.ts +43 -12
- package/src/forge/compiler/integration/render.ts +29 -0
- package/src/forge/compiler/integration/snapshot.ts +2 -0
- package/src/forge/compiler/integration/templates/convex.ts +70 -0
- package/src/forge/compiler/integration/templates/index.ts +1 -0
- package/src/forge/compiler/integration/templates/render.ts +38 -0
- package/src/forge/compiler/integration/templates/types.ts +3 -0
- package/src/forge/compiler/integration/templates/workos.ts +1439 -0
- package/src/forge/compiler/make-registry/build.ts +8 -9
- package/src/forge/compiler/orchestrator/fast-check.ts +4 -0
- package/src/forge/compiler/orchestrator/generate-lock.ts +14 -3
- package/src/forge/compiler/orchestrator/manifest.ts +1 -1
- package/src/forge/compiler/orchestrator/plan-profile.ts +23 -0
- package/src/forge/compiler/orchestrator/plan.ts +249 -10
- package/src/forge/compiler/orchestrator/profile.ts +65 -0
- package/src/forge/compiler/orchestrator/run.ts +101 -33
- package/src/forge/compiler/orchestrator/serialize.ts +33 -8
- package/src/forge/compiler/orchestrator/types.ts +1 -1
- package/src/forge/compiler/package-graph/compiler.ts +3 -1
- package/src/forge/compiler/package-graph/constants.ts +1 -1
- 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/package-manager/version.ts +36 -12
- package/src/forge/compiler/package-upgrades/planner.ts +155 -18
- package/src/forge/compiler/package-upgrades/types.ts +2 -0
- package/src/forge/compiler/policy-registry/build.ts +47 -2
- package/src/forge/compiler/policy-registry/parse.ts +32 -2
- package/src/forge/compiler/recipes/definitions.ts +63 -0
- package/src/forge/compiler/recipes/index.ts +2 -0
- package/src/forge/compiler/recipes/profiles.ts +81 -0
- package/src/forge/compiler/recipes/registry.ts +6 -0
- package/src/forge/compiler/test-graph/build.ts +11 -3
- package/src/forge/compiler/types/app-graph.ts +8 -2
- package/src/forge/compiler/types/cli.ts +76 -1
- package/src/forge/compiler/types/dev-manifest.ts +4 -0
- package/src/forge/compiler/types/emit.ts +2 -0
- package/src/forge/compiler/types/frontend-graph.ts +2 -2
- package/src/forge/compiler/types/integration.ts +1 -0
- package/src/forge/compiler/types/package-graph.ts +6 -0
- package/src/forge/compiler/types/policy-registry.ts +3 -1
- package/src/forge/delta/classifier.ts +52 -0
- package/src/forge/delta/explain.ts +238 -0
- package/src/forge/delta/git-observer.ts +43 -0
- package/src/forge/delta/ids.ts +44 -0
- package/src/forge/delta/index.ts +25 -0
- package/src/forge/delta/recorder.ts +540 -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 +1202 -0
- package/src/forge/delta/store.ts +3284 -0
- package/src/forge/delta/timeline.ts +178 -0
- package/src/forge/dev/server.ts +1061 -22
- package/src/forge/dev/types.ts +15 -1
- package/src/forge/dev/watch.ts +17 -7
- package/src/forge/dev-console/cycle.ts +280 -33
- package/src/forge/dev-console/types.ts +47 -1
- package/src/forge/impact/index.ts +204 -9
- package/src/forge/impact/types.ts +33 -1
- package/src/forge/intent/index.ts +35 -16
- package/src/forge/make/fields.ts +26 -0
- package/src/forge/make/index.ts +42 -6
- package/src/forge/make/templates.ts +211 -4
- package/src/forge/make/types.ts +2 -1
- package/src/forge/policy.ts +1 -1
- package/src/forge/react/index.ts +160 -2
- 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/auth/config.ts +17 -0
- package/src/forge/runtime/auth/evaluate.ts +15 -2
- package/src/forge/runtime/auth/resolve.ts +61 -6
- package/src/forge/runtime/auth/types.ts +1 -0
- package/src/forge/runtime/db/factory.ts +1 -3
- package/src/forge/runtime/db/generated-client.ts +13 -2
- package/src/forge/runtime/db/memory-adapter.ts +139 -32
- package/src/forge/runtime/db/pglite-adapter.ts +263 -2
- package/src/forge/runtime/executor.ts +129 -16
- package/src/forge/runtime/external/bridge.ts +663 -0
- package/src/forge/runtime/runner/run-entry.ts +16 -7
- package/src/forge/runtime/telemetry/buffer.ts +4 -1
- package/src/forge/runtime/telemetry/scrubber.ts +35 -5
- package/src/forge/runtime/webhooks/security.ts +12 -7
- package/src/forge/server.ts +71 -7
- package/src/forge/ui/index.ts +831 -19
- package/src/forge/ui/types.ts +3 -1
- package/src/forge/version.ts +1 -1
- package/src/forge/vue/index.ts +422 -0
- package/src/forge/workspace/baseline.ts +112 -0
- package/src/forge/workspace/change-summary.ts +250 -0
- package/src/forge/workspace/forge-cli.ts +42 -0
- package/src/forge/workspace/git-summary.ts +391 -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 +13 -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 +20 -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/agent-workroom/web/vite.config.ts +36 -0
- package/templates/b2b-support-web/package.json +1 -0
- package/templates/b2b-support-web/web/app/page.tsx +2 -2
- package/templates/b2b-support-web/web/lib/forge.ts +9 -2
- package/templates/b2b-support-web/web/next.config.ts +24 -0
- package/templates/minimal-web/package.json +1 -1
- package/templates/minimal-web/web/index.html +1 -0
- package/templates/minimal-web/web/src/App.tsx +12 -6
- package/templates/minimal-web/web/src/lib/forge.ts +9 -2
- package/templates/minimal-web/web/src/styles.css +34 -0
- package/templates/minimal-web/web/vite.config.ts +36 -0
- package/templates/nuxt-web/.vscode/settings.json +14 -0
- package/templates/nuxt-web/README.md +30 -0
- package/templates/nuxt-web/forge.config.ts +3 -0
- package/templates/nuxt-web/package.json +33 -0
- package/templates/nuxt-web/src/actions/logNoteCreated.ts +11 -0
- package/templates/nuxt-web/src/commands/createNote.ts +26 -0
- package/templates/nuxt-web/src/forge/schema.ts +12 -0
- package/templates/nuxt-web/src/policies.ts +6 -0
- package/templates/nuxt-web/src/queries/listNotes.ts +8 -0
- package/templates/nuxt-web/src/queries/liveNotes.ts +8 -0
- package/templates/nuxt-web/tsconfig.json +17 -0
- package/templates/nuxt-web/web/app.vue +67 -0
- package/templates/nuxt-web/web/components/LiveNotes.vue +89 -0
- package/templates/nuxt-web/web/components/NoteComposer.vue +100 -0
- package/templates/nuxt-web/web/composables/forge.ts +13 -0
- package/templates/nuxt-web/web/composables/useNotes.ts +24 -0
- package/templates/nuxt-web/web/nuxt.config.ts +11 -0
- package/templates/nuxt-web/web/package.json +18 -0
- package/templates/nuxt-web/web/plugins/forge.client.ts +10 -0
- package/templates/nuxt-web/web/plugins/forge.server.ts +10 -0
- package/templates/nuxt-web/web/server/api/forge-health.get.ts +7 -0
- package/templates/nuxt-web/web/tsconfig.json +6 -0
- package/templates/vendor-access/.vscode/settings.json +14 -0
- package/templates/vendor-access/README.md +30 -0
- package/templates/vendor-access/forge.config.ts +3 -0
- package/templates/vendor-access/package.json +34 -0
- package/templates/vendor-access/src/commands/addEvidence.ts +42 -0
- package/templates/vendor-access/src/commands/approveAccessRequest.ts +43 -0
- package/templates/vendor-access/src/commands/createAccessRequest.ts +49 -0
- package/templates/vendor-access/src/commands/seedVendorAccessDemo.ts +200 -0
- package/templates/vendor-access/src/forge/schema.ts +74 -0
- package/templates/vendor-access/src/policies.ts +11 -0
- package/templates/vendor-access/src/queries/listVendorAccessDashboard.ts +24 -0
- package/templates/vendor-access/src/queries/liveVendorAccessDashboard.ts +24 -0
- package/templates/vendor-access/tsconfig.json +17 -0
- package/templates/vendor-access/web/index.html +13 -0
- package/templates/vendor-access/web/package.json +21 -0
- package/templates/vendor-access/web/src/App.tsx +573 -0
- package/templates/vendor-access/web/src/lib/forge.ts +20 -0
- package/templates/vendor-access/web/src/main.tsx +205 -0
- package/templates/vendor-access/web/src/styles.css +682 -0
- package/templates/vendor-access/web/tsconfig.json +18 -0
- package/templates/vendor-access/web/vite.config.ts +36 -0
- 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 -7829
- package/src/forge/_generated/agentQuickstart.md +0 -34
- package/src/forge/_generated/agentTools.json +0 -2
- package/src/forge/_generated/agentTools.md +0 -16
- package/src/forge/_generated/agentTools.ts +0 -12
- package/src/forge/_generated/aiContext.ts +0 -125
- package/src/forge/_generated/aiModels.json +0 -2
- package/src/forge/_generated/aiModels.ts +0 -51
- 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 -31
- 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 -14937
- package/src/forge/_generated/appMap.md +0 -55
- 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 -62
- 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 -68
- 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 -177
- package/src/forge/_generated/makeTemplates.json +0 -2
- package/src/forge/_generated/makeTemplates.ts +0 -66
- package/src/forge/_generated/mockMap.json +0 -2
- package/src/forge/_generated/mockMap.ts +0 -7
- package/src/forge/_generated/operationPlaybooks.md +0 -167
- package/src/forge/_generated/packageGraph.json +0 -2
- package/src/forge/_generated/packageGraph.ts +0 -249334
- 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 -334130
- package/src/forge/_generated/runtimeRegistry.ts +0 -2
- package/src/forge/_generated/runtimeRules.md +0 -91
- 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 -3452
- 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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ForgeOS contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# ForgeOS
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The contract layer for agentic software development. ForgeOS turns application source into deterministic runtime contracts, generated clients, safety checks, and machine-readable context that humans and AI coding agents can use safely.
|
|
4
4
|
|
|
5
|
-
**Status:** private/public alpha MVP, implemented through
|
|
5
|
+
**Status:** private/public alpha MVP, implemented through H49. ForgeOS already includes the compiler, local runtime, frontend SDK, production auth, RLS compiler, liveQuery, self-host artifacts, generated agent contract, guided dev loop, repair/review/test tooling, AST-aware codemods, package intelligence, native AI tools/agents, DeltaDB work memory, external agent memory ingestion, brownfield import analysis, npm alpha publishing, and Read the Docs public docs. Public release hardening is still focused on deeper semantic codemods, broader field reports, and more production mileage.
|
|
6
6
|
|
|
7
7
|
Public docs live at [forgeos.readthedocs.io](https://forgeos.readthedocs.io/). The repo builds them with `.readthedocs.yaml`, `mkdocs.yml`, and `docs/index.md`.
|
|
8
8
|
|
|
9
9
|
Start with [Why ForgeOS](https://forgeos.readthedocs.io/en/latest/why-forgeos/) to understand the agent-native design.
|
|
10
10
|
|
|
11
|
+
For the short version, read [The Five-Minute ForgeOS Model](https://forgeos.readthedocs.io/en/latest/five-minute-model/), [Alpha Golden Path](https://forgeos.readthedocs.io/en/latest/golden-path/), and [Stable Alpha Surface](https://forgeos.readthedocs.io/en/latest/stable-alpha/). The important distinction is that external coding agents are the primary ForgeOS workflow; integrated AI SDK features are available for apps that need in-product AI, but they are not the main development loop.
|
|
12
|
+
|
|
11
13
|
## Agent-First Quickstart
|
|
12
14
|
|
|
13
15
|
```bash
|
|
@@ -91,6 +93,39 @@ npm run field:test -- --package-managers npm --templates minimal-web --forge-spe
|
|
|
91
93
|
|
|
92
94
|
The scheduled/manual `Field Tests` workflow expands that coverage across Linux, macOS, Windows, Node 22, Node 24, and npm/pnpm/yarn/bun.
|
|
93
95
|
|
|
96
|
+
## External Runtimes And Adapters
|
|
97
|
+
|
|
98
|
+
ForgeOS can import services written outside TypeScript through the Forge Protocol.
|
|
99
|
+
External runtimes publish a `forge.manifest.json` that describes commands, queries,
|
|
100
|
+
transport, policies, risk metadata, tenant scope, and schemas. Forge then emits
|
|
101
|
+
the same machine-readable app/API/agent artifacts and exposes runtime bridge
|
|
102
|
+
endpoints for those entries.
|
|
103
|
+
|
|
104
|
+
The Go example starts a manifest-backed service:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
cd examples/go-billing
|
|
108
|
+
go run . --manifest --base-url http://127.0.0.1:8787 > forge.manifest.json
|
|
109
|
+
go run . --addr 127.0.0.1:8787 --base-url http://127.0.0.1:8787
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
In a Forge app:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
forge manifest validate ./forge.manifest.json --json
|
|
116
|
+
forge manifest import ./forge.manifest.json --json
|
|
117
|
+
forge generate
|
|
118
|
+
forge run billing.createInvoice --args '{"title":"Invoice"}' --user-id u1 --tenant-id tenant-a --role admin
|
|
119
|
+
forge query billing.listInvoices --args '{}' --user-id u1 --tenant-id tenant-a --role admin
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
For Java, see [`adapters/java`](adapters/java/README.md),
|
|
123
|
+
[`adapters/java-spring-boot-starter`](adapters/java-spring-boot-starter/README.md),
|
|
124
|
+
and [`examples/java-billing`](examples/java-billing/README.md).
|
|
125
|
+
|
|
126
|
+
See [`docs/forge-protocol.md`](docs/forge-protocol.md), [`schemas/forge-manifest.schema.json`](schemas/forge-manifest.schema.json),
|
|
127
|
+
and [`adapters/go`](adapters/go/README.md).
|
|
128
|
+
|
|
94
129
|
## What ForgeOS Generates
|
|
95
130
|
|
|
96
131
|
```txt
|
|
@@ -143,11 +178,14 @@ forge.lock
|
|
|
143
178
|
| AI | Vercel AI SDK v6 engine, provider registry, `ctx.ai`, `ctx.agent.run`, `aiTool`, `agent`, `/ai/agents/run` JSON automation, `/ai/agents/chat` UIMessage streaming, `forge ai trace`, structural and model-level redteam probes, mock mode, telemetry without prompt/output retention by default |
|
|
144
179
|
| Frontend | generated client SDK, React/Next hooks, template app, liveQuery client support |
|
|
145
180
|
| LiveQuery | durable invalidation log, reconnect/resume semantics, production hardening checks |
|
|
181
|
+
| DeltaDB | ambient local recorder plus inferred work sessions and semantic timelines for Forge commands, dev file saves, generated artifacts, runtime calls, policies, proofs, diagnostics, `forge timeline`, `forge explain`, and optional `forge session` correction |
|
|
182
|
+
| Agent memory | opt-in Codex and Claude Code hooks, Cursor MCP/rules setup, normalized external agent events, redacted local memory, and `forge mcp serve` |
|
|
183
|
+
| Brownfield import | static TypeScript/JavaScript app inventory with routes, frontend calls, env usage, candidate entries, risk report, migration plan, and hidden-by-default imported agent contract |
|
|
146
184
|
| Self-host | compose/deploy artifacts and self-host checks |
|
|
147
185
|
| Agent contract | `AGENTS.md`, `agentContract.json`, app maps, runtime rules, playbooks, inspect/doctor |
|
|
148
186
|
| Authoring | `forge make`, feature blueprints, safe refactor plans, package upgrade plans |
|
|
149
187
|
| Testing/repair | impact-based test planner, repair loop, structured review, UI/browser test bridge |
|
|
150
|
-
| Adapters |
|
|
188
|
+
| Adapters | Forge Protocol manifest import plus Go, Java, and Spring Boot adapter support for executable external commands and queries |
|
|
151
189
|
| Intent router | `forge do` maps objectives like fix, verify, connect UI, and add feature into plans, files, risks, and next commands |
|
|
152
190
|
| Full-stack map | `frontendGraph` + `capabilityMap` connect routes, components, hooks, runtime entries, tables, policies, and gaps |
|
|
153
191
|
| Dev loop | `forge dev` prints API/Web URLs, phase health, capability coverage, cache status, diagnostics, and next action |
|
|
@@ -168,6 +206,16 @@ forge dev
|
|
|
168
206
|
forge inspect all --json
|
|
169
207
|
forge inspect framework --json
|
|
170
208
|
forge inspect capabilities --json
|
|
209
|
+
forge delta status
|
|
210
|
+
forge timeline
|
|
211
|
+
forge timeline --session current
|
|
212
|
+
forge explain <thing>
|
|
213
|
+
forge explain session current
|
|
214
|
+
forge session list
|
|
215
|
+
forge agent memory --json
|
|
216
|
+
forge mcp serve
|
|
217
|
+
forge import analyze --json
|
|
218
|
+
forge inspect imported --json
|
|
171
219
|
forge doctor
|
|
172
220
|
forge verify --standard
|
|
173
221
|
forge verify --strict
|
|
@@ -189,8 +237,10 @@ Common command groups:
|
|
|
189
237
|
| `forge check --json` | Validate guardrails and emit diagnostics with fix hints |
|
|
190
238
|
| `forge verify --smoke` | Fast local gate: generated drift, Forge checks, typecheck when present, no tests/lint |
|
|
191
239
|
| `forge verify --standard` | Agent development gate: generated drift, Forge/security checks, typecheck, and impact-selected tests |
|
|
192
|
-
| `forge verify --strict` | Full handoff/CI gate: generated drift, Forge/security checks, typecheck, full
|
|
240
|
+
| `forge verify --strict` | Full handoff/CI gate: generated drift, Forge/security checks, typecheck, full TestGraph in bounded parallel/isolated chunks, lint |
|
|
193
241
|
| `forge verify --script-timeout-ms <ms>` | Run package scripts with a predictable timeout and machine-readable timeout diagnostics |
|
|
242
|
+
| `forge verify --test-jobs <n>` | Tune strict TestGraph chunk parallelism; `FORGE_VERIFY_TEST_JOBS` is also supported |
|
|
243
|
+
| `forge verify --strict --test-plan --json` | Print the strict TestGraph scheduler plan without running tests |
|
|
194
244
|
| `forge do "<objective>" --json` | Guided intent router: choose the right workflow, files, risks, and next action |
|
|
195
245
|
| `forge inspect <target> --json` | Inspect generated app/data/runtime/policy/client/agent/UI surfaces |
|
|
196
246
|
| `forge inspect framework --json` | Inspect ForgeOS framework modules, CLI commands, templates, examples, tests, and preferred entrypoints |
|
|
@@ -210,7 +260,10 @@ Common command groups:
|
|
|
210
260
|
| `forge ui` | Browser/UI smoke, scenario, route, snapshot, doctor, and reports |
|
|
211
261
|
| `forge deps` | Package upgrade planning and application |
|
|
212
262
|
| `forge release` | Release/source-map bridge and symbolication |
|
|
213
|
-
| `forge agent`, `forge agent-contract` | Agent-facing contract
|
|
263
|
+
| `forge agent`, `forge agent-contract` | Agent-facing contract, adapter exports, context, install, ingest, and memory commands |
|
|
264
|
+
| `forge mcp serve` | MCP server for external agents to read Forge context, memory, timeline, and inspect surfaces |
|
|
265
|
+
| `forge import analyze`, `forge import inspect` | Brownfield TypeScript/JavaScript app inventory and reviewed migration planning |
|
|
266
|
+
| `forge inspect imported --json` | Inspect `.forge/import` analysis artifacts |
|
|
214
267
|
| `forge self-host` | Self-host packaging and checks |
|
|
215
268
|
|
|
216
269
|
Refactor codemods are AST-aware where safety matters most:
|
|
@@ -360,7 +413,7 @@ Configure npm Trusted Publisher for package `forgeos`:
|
|
|
360
413
|
| Environment | blank |
|
|
361
414
|
| Allowed action | `npm publish` |
|
|
362
415
|
|
|
363
|
-
Do not add `NPM_TOKEN` for normal
|
|
416
|
+
Do not add `NPM_TOKEN` for normal alpha publishes. Alpha releases publish with the `alpha` dist-tag through npm OIDC Trusted Publisher so prerelease builds do not become `latest` accidentally. Configure `NPM_TOKEN` only when maintainers intentionally want the workflow to promote `latest` with `npm dist-tag add forgeos@<version> latest`; otherwise that step is skipped and `latest` may lag behind `alpha` during hardening. Use `release:publish-local-alpha -- --dry-run` only to validate the staged tarball locally; real npm publishing should go through `release:publish-alpha`, which dispatches `publish.yml` and uses npm OIDC Trusted Publisher. The workflow checks whether the package version already exists before installing dependencies or running tests, then uses `id-token: write`, Node 24/npm 11+, and provenance for the actual publish. `npm run release:smoke` runs `npm pack`, creates a fresh app with the packed tarball, installs dependencies, runs `forge dev --once --json`, and verifies the app smoke path.
|
|
364
417
|
|
|
365
418
|
## Milestone History
|
|
366
419
|
|
|
@@ -408,6 +461,12 @@ H40 Windows/runtime hardening
|
|
|
408
461
|
H41 Node-compatible CLI/runtime
|
|
409
462
|
H42 Verify observability and quieter app workspaces
|
|
410
463
|
H43 Native AI tools and agent loop
|
|
464
|
+
H44 Ambient DeltaDB recorder
|
|
465
|
+
H45 Automatic work-session inference
|
|
466
|
+
H46 Automatic change grouping
|
|
467
|
+
H47 Semantic timeline
|
|
468
|
+
H48 Agent Memory Bridge
|
|
469
|
+
H49 Brownfield import analysis
|
|
411
470
|
```
|
|
412
471
|
|
|
413
472
|
## Remaining Hardening Before Public Release
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Forge Go Adapter
|
|
2
|
+
|
|
3
|
+
`adapters/go` is the minimal Go SDK for external Forge runtimes. It registers
|
|
4
|
+
commands and queries, emits `forge.manifest.json`, and exposes a Forge-compatible
|
|
5
|
+
HTTP handler.
|
|
6
|
+
|
|
7
|
+
```go
|
|
8
|
+
app := forge.New("billing", forge.BaseURL("http://127.0.0.1:8787"))
|
|
9
|
+
|
|
10
|
+
app.Command("createInvoice", forge.Handle(createInvoice),
|
|
11
|
+
forge.Policy("billing.manage"),
|
|
12
|
+
forge.TenantScoped(true),
|
|
13
|
+
forge.NeedsApproval(true),
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
app.Query("listInvoices", forge.Handle(listInvoices),
|
|
17
|
+
forge.Policy("billing.manage"),
|
|
18
|
+
forge.TenantScoped(true),
|
|
19
|
+
)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The HTTP handler accepts Forge runtime envelopes on `/commands/:name` and
|
|
23
|
+
`/queries/:name`, then returns `{ "ok": true, "result": ... }` envelopes.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
package forge
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"errors"
|
|
6
|
+
"net/http"
|
|
7
|
+
"strings"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
func (registry *Registry) HTTPHandler() http.Handler {
|
|
11
|
+
mux := http.NewServeMux()
|
|
12
|
+
mux.HandleFunc(registry.service.Health, registry.handleHealth)
|
|
13
|
+
mux.HandleFunc("/manifest", registry.handleManifest)
|
|
14
|
+
mux.HandleFunc("/commands/", registry.handleRuntime(KindCommand, "/commands/"))
|
|
15
|
+
mux.HandleFunc("/queries/", registry.handleRuntime(KindQuery, "/queries/"))
|
|
16
|
+
return mux
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
func (registry *Registry) handleHealth(response http.ResponseWriter, request *http.Request) {
|
|
20
|
+
writeJSON(response, http.StatusOK, map[string]any{
|
|
21
|
+
"ok": true,
|
|
22
|
+
"service": registry.service.Name,
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
func (registry *Registry) handleManifest(response http.ResponseWriter, request *http.Request) {
|
|
27
|
+
baseURL := request.URL.Query().Get("baseUrl")
|
|
28
|
+
if baseURL == "" {
|
|
29
|
+
baseURL = registry.service.BaseURL
|
|
30
|
+
}
|
|
31
|
+
writeJSON(response, http.StatusOK, registry.Manifest(baseURL))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
func (registry *Registry) handleRuntime(kind EntryKind, prefix string) http.HandlerFunc {
|
|
35
|
+
return func(response http.ResponseWriter, request *http.Request) {
|
|
36
|
+
name := strings.TrimPrefix(request.URL.Path, prefix)
|
|
37
|
+
registered, ok := registry.lookup[lookupKey(kind, name)]
|
|
38
|
+
if !ok {
|
|
39
|
+
writeError(response, http.StatusNotFound, "", "FORGE_GO_ENTRY_NOT_FOUND", "external entry not found")
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
if request.Method != http.MethodPost && request.Method != http.MethodGet {
|
|
43
|
+
writeError(response, http.StatusMethodNotAllowed, "", "FORGE_GO_METHOD_NOT_ALLOWED", "external entry only accepts GET or POST")
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
envelope, err := readRequestEnvelope(request)
|
|
48
|
+
traceID := traceIDFrom(request, envelope)
|
|
49
|
+
if err != nil {
|
|
50
|
+
writeError(response, http.StatusBadRequest, traceID, "FORGE_GO_BAD_REQUEST", err.Error())
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
if envelope.Forge.Service == "" {
|
|
54
|
+
envelope.Forge.Service = registry.service.Name
|
|
55
|
+
}
|
|
56
|
+
if envelope.Forge.Entry == "" {
|
|
57
|
+
envelope.Forge.Entry = name
|
|
58
|
+
}
|
|
59
|
+
if envelope.Forge.Kind == "" {
|
|
60
|
+
envelope.Forge.Kind = string(kind)
|
|
61
|
+
}
|
|
62
|
+
if envelope.Forge.TraceID == "" {
|
|
63
|
+
envelope.Forge.TraceID = traceID
|
|
64
|
+
}
|
|
65
|
+
if envelope.Auth.Kind == "" {
|
|
66
|
+
envelope.Auth = authFromHeaders(request.Header)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
call := &Context{
|
|
70
|
+
Auth: envelope.Auth,
|
|
71
|
+
Forge: envelope.Forge,
|
|
72
|
+
Headers: request.Header,
|
|
73
|
+
}
|
|
74
|
+
result, err := registered.handler(request.Context(), call, envelope.Args)
|
|
75
|
+
if err != nil {
|
|
76
|
+
writeError(response, http.StatusInternalServerError, envelope.Forge.TraceID, "FORGE_GO_HANDLER_FAILED", err.Error())
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
writeJSON(response, http.StatusOK, ResponseEnvelope{
|
|
80
|
+
OK: true,
|
|
81
|
+
Result: result,
|
|
82
|
+
TraceID: envelope.Forge.TraceID,
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
func readRequestEnvelope(request *http.Request) (RequestEnvelope, error) {
|
|
88
|
+
if request.Method == http.MethodGet {
|
|
89
|
+
args := request.URL.Query().Get("args")
|
|
90
|
+
if args == "" {
|
|
91
|
+
args = "{}"
|
|
92
|
+
}
|
|
93
|
+
return RequestEnvelope{Args: json.RawMessage(args)}, nil
|
|
94
|
+
}
|
|
95
|
+
defer request.Body.Close()
|
|
96
|
+
var envelope RequestEnvelope
|
|
97
|
+
decoder := json.NewDecoder(request.Body)
|
|
98
|
+
if err := decoder.Decode(&envelope); err != nil {
|
|
99
|
+
return envelope, err
|
|
100
|
+
}
|
|
101
|
+
if len(envelope.Args) == 0 {
|
|
102
|
+
envelope.Args = json.RawMessage("{}")
|
|
103
|
+
}
|
|
104
|
+
if !json.Valid(envelope.Args) {
|
|
105
|
+
return envelope, errors.New("request args must be valid JSON")
|
|
106
|
+
}
|
|
107
|
+
return envelope, nil
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
func authFromHeaders(headers http.Header) Auth {
|
|
111
|
+
auth := Auth{Kind: headers.Get("x-forge-auth-kind")}
|
|
112
|
+
if auth.Kind == "" {
|
|
113
|
+
auth.Kind = "anonymous"
|
|
114
|
+
}
|
|
115
|
+
auth.UserID = headers.Get("x-forge-user-id")
|
|
116
|
+
auth.TenantID = headers.Get("x-forge-tenant-id")
|
|
117
|
+
auth.Role = headers.Get("x-forge-role")
|
|
118
|
+
return auth
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
func traceIDFrom(request *http.Request, envelope RequestEnvelope) string {
|
|
122
|
+
if envelope.Forge.TraceID != "" {
|
|
123
|
+
return envelope.Forge.TraceID
|
|
124
|
+
}
|
|
125
|
+
return request.Header.Get("x-forge-trace-id")
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
func writeError(response http.ResponseWriter, status int, traceID string, code string, message string) {
|
|
129
|
+
writeJSON(response, status, ResponseEnvelope{
|
|
130
|
+
OK: false,
|
|
131
|
+
Diagnostics: []Diagnostic{{
|
|
132
|
+
Severity: "error",
|
|
133
|
+
Code: code,
|
|
134
|
+
Message: message,
|
|
135
|
+
Docs: []string{"docs/forge-protocol.md"},
|
|
136
|
+
}},
|
|
137
|
+
Error: &ErrorInfo{
|
|
138
|
+
Code: code,
|
|
139
|
+
Message: message,
|
|
140
|
+
},
|
|
141
|
+
TraceID: traceID,
|
|
142
|
+
})
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
func writeJSON(response http.ResponseWriter, status int, body any) {
|
|
146
|
+
response.Header().Set("content-type", "application/json")
|
|
147
|
+
response.WriteHeader(status)
|
|
148
|
+
_ = json.NewEncoder(response).Encode(body)
|
|
149
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
package forge
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"io"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
type Registry struct {
|
|
9
|
+
service Service
|
|
10
|
+
framework string
|
|
11
|
+
schemas map[string]any
|
|
12
|
+
entries []registeredEntry
|
|
13
|
+
lookup map[string]registeredEntry
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type registeredEntry struct {
|
|
17
|
+
entry Entry
|
|
18
|
+
handler HandlerFunc
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type RegistryOption func(*Registry)
|
|
22
|
+
type EntryOption func(*Entry)
|
|
23
|
+
|
|
24
|
+
func New(serviceName string, options ...RegistryOption) *Registry {
|
|
25
|
+
registry := &Registry{
|
|
26
|
+
service: Service{
|
|
27
|
+
Name: serviceName,
|
|
28
|
+
Transport: "http",
|
|
29
|
+
Health: "/health",
|
|
30
|
+
},
|
|
31
|
+
framework: "net/http",
|
|
32
|
+
schemas: map[string]any{},
|
|
33
|
+
lookup: map[string]registeredEntry{},
|
|
34
|
+
}
|
|
35
|
+
for _, option := range options {
|
|
36
|
+
option(registry)
|
|
37
|
+
}
|
|
38
|
+
return registry
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
func Framework(value string) RegistryOption {
|
|
42
|
+
return func(registry *Registry) {
|
|
43
|
+
registry.framework = value
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func BaseURL(value string) RegistryOption {
|
|
48
|
+
return func(registry *Registry) {
|
|
49
|
+
registry.service.BaseURL = value
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
func Health(path string) RegistryOption {
|
|
54
|
+
return func(registry *Registry) {
|
|
55
|
+
registry.service.Health = path
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
func SchemaRef(name string, schema any) RegistryOption {
|
|
60
|
+
return func(registry *Registry) {
|
|
61
|
+
registry.schemas[name] = schema
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
func (registry *Registry) Command(name string, handler HandlerFunc, options ...EntryOption) {
|
|
66
|
+
entry := Entry{
|
|
67
|
+
Name: name,
|
|
68
|
+
Kind: KindCommand,
|
|
69
|
+
Path: "/commands/" + name,
|
|
70
|
+
Method: "POST",
|
|
71
|
+
Transaction: TransactionExternalManaged,
|
|
72
|
+
Risk: RiskWrite,
|
|
73
|
+
}
|
|
74
|
+
registry.add(entry, handler, options...)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
func (registry *Registry) Query(name string, handler HandlerFunc, options ...EntryOption) {
|
|
78
|
+
entry := Entry{
|
|
79
|
+
Name: name,
|
|
80
|
+
Kind: KindQuery,
|
|
81
|
+
Path: "/queries/" + name,
|
|
82
|
+
Method: "POST",
|
|
83
|
+
Transaction: TransactionReadOnly,
|
|
84
|
+
Risk: RiskRead,
|
|
85
|
+
}
|
|
86
|
+
registry.add(entry, handler, options...)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
func (registry *Registry) add(entry Entry, handler HandlerFunc, options ...EntryOption) {
|
|
90
|
+
for _, option := range options {
|
|
91
|
+
option(&entry)
|
|
92
|
+
}
|
|
93
|
+
registered := registeredEntry{entry: entry, handler: handler}
|
|
94
|
+
registry.entries = append(registry.entries, registered)
|
|
95
|
+
registry.lookup[lookupKey(entry.Kind, entry.Name)] = registered
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
func Description(value string) EntryOption {
|
|
99
|
+
return func(entry *Entry) {
|
|
100
|
+
entry.Description = value
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
func Path(value string) EntryOption {
|
|
105
|
+
return func(entry *Entry) {
|
|
106
|
+
entry.Path = value
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
func Method(value string) EntryOption {
|
|
111
|
+
return func(entry *Entry) {
|
|
112
|
+
entry.Method = value
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
func InputSchema(schema any) EntryOption {
|
|
117
|
+
return func(entry *Entry) {
|
|
118
|
+
entry.InputSchema = schema
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
func OutputSchema(schema any) EntryOption {
|
|
123
|
+
return func(entry *Entry) {
|
|
124
|
+
entry.OutputSchema = schema
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
func Policy(value string) EntryOption {
|
|
129
|
+
return func(entry *Entry) {
|
|
130
|
+
entry.Policy = value
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
func TenantScoped(value bool) EntryOption {
|
|
135
|
+
return func(entry *Entry) {
|
|
136
|
+
entry.TenantScoped = value
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
func TransactionMode(value Transaction) EntryOption {
|
|
141
|
+
return func(entry *Entry) {
|
|
142
|
+
entry.Transaction = value
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
func EntryRisk(value Risk) EntryOption {
|
|
147
|
+
return func(entry *Entry) {
|
|
148
|
+
entry.Risk = value
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
func NeedsApproval(value bool) EntryOption {
|
|
153
|
+
return func(entry *Entry) {
|
|
154
|
+
entry.NeedsApproval = &value
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
func Effects(values ...string) EntryOption {
|
|
159
|
+
return func(entry *Entry) {
|
|
160
|
+
entry.Effects = append([]string{}, values...)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
func ReadOnly() EntryOption {
|
|
165
|
+
return func(entry *Entry) {
|
|
166
|
+
entry.Transaction = TransactionReadOnly
|
|
167
|
+
entry.Risk = RiskRead
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
func (registry *Registry) Manifest(baseURL string) Manifest {
|
|
172
|
+
service := registry.service
|
|
173
|
+
if baseURL != "" {
|
|
174
|
+
service.BaseURL = baseURL
|
|
175
|
+
}
|
|
176
|
+
entries := make([]Entry, 0, len(registry.entries))
|
|
177
|
+
for _, registered := range registry.entries {
|
|
178
|
+
entries = append(entries, registered.entry)
|
|
179
|
+
}
|
|
180
|
+
manifest := Manifest{
|
|
181
|
+
ForgeProtocol: ProtocolVersion,
|
|
182
|
+
Language: "go",
|
|
183
|
+
Framework: registry.framework,
|
|
184
|
+
Service: service,
|
|
185
|
+
Entries: entries,
|
|
186
|
+
}
|
|
187
|
+
if len(registry.schemas) > 0 {
|
|
188
|
+
manifest.Schemas = registry.schemas
|
|
189
|
+
}
|
|
190
|
+
return manifest
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
func (registry *Registry) MarshalManifest(baseURL string) ([]byte, error) {
|
|
194
|
+
return json.MarshalIndent(registry.Manifest(baseURL), "", " ")
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
func (registry *Registry) WriteManifest(writer io.Writer, baseURL string) error {
|
|
198
|
+
encoded, err := registry.MarshalManifest(baseURL)
|
|
199
|
+
if err != nil {
|
|
200
|
+
return err
|
|
201
|
+
}
|
|
202
|
+
if _, err := writer.Write(encoded); err != nil {
|
|
203
|
+
return err
|
|
204
|
+
}
|
|
205
|
+
_, err = writer.Write([]byte("\n"))
|
|
206
|
+
return err
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
func Object(properties map[string]any, required ...string) Schema {
|
|
210
|
+
schema := Schema{
|
|
211
|
+
"type": "object",
|
|
212
|
+
"properties": properties,
|
|
213
|
+
}
|
|
214
|
+
if len(required) > 0 {
|
|
215
|
+
schema["required"] = required
|
|
216
|
+
}
|
|
217
|
+
return schema
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
func String() Schema {
|
|
221
|
+
return Schema{"type": "string"}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
func Boolean() Schema {
|
|
225
|
+
return Schema{"type": "boolean"}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
func Array(items any) Schema {
|
|
229
|
+
return Schema{"type": "array", "items": items}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
func lookupKey(kind EntryKind, name string) string {
|
|
233
|
+
return string(kind) + ":" + name
|
|
234
|
+
}
|