@atmem/architect 0.0.0-stage → 0.2.0-alpha.4.1
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/CONSTITUTION.md +144 -0
- package/README.md +33 -2
- package/agent-skills/discovery/SKILL.md +48 -0
- package/agent-skills/discovery/topics.json +139 -0
- package/agent-skills/generation-capabilities.json +760 -0
- package/agent-skills/service-lifecycle.json +21 -0
- package/agent-skills/specialists/architecture/SKILL.md +15 -0
- package/agent-skills/specialists/aws/SKILL.md +17 -0
- package/agent-skills/specialists/azure/SKILL.md +7 -0
- package/agent-skills/specialists/composition/SKILL.md +17 -0
- package/agent-skills/specialists/devops/SKILL.md +10 -0
- package/agent-skills/specialists/finops/SKILL.md +7 -0
- package/agent-skills/specialists/gcp/SKILL.md +7 -0
- package/agent-skills/specialists/ibm/SKILL.md +7 -0
- package/agent-skills/specialists/manifest.json +13 -0
- package/agent-skills/specialists/pulumi/SKILL.md +7 -0
- package/agent-skills/specialists/security/SKILL.md +7 -0
- package/agent-skills/specialists/terraform/SKILL.md +14 -0
- package/agent-skills/upstream/aws/LICENSE +175 -0
- package/agent-skills/upstream/aws/SKILL.md +125 -0
- package/agent-skills/upstream/azure/LICENSE +21 -0
- package/agent-skills/upstream/azure/SKILL.md +387 -0
- package/agent-skills/upstream/gcp/LICENSE +202 -0
- package/agent-skills/upstream/gcp/SKILL.md +159 -0
- package/agent-skills/upstream/manifest.json +57 -0
- package/agent-skills/upstream/pulumi/LICENSE +201 -0
- package/agent-skills/upstream/pulumi/SKILL.md +501 -0
- package/agent-skills/upstream/terraform/LICENSE +373 -0
- package/agent-skills/upstream/terraform/SKILL.md +316 -0
- package/agent-skills/workflows/workflows.json +601 -0
- package/cli/architect.mjs +3 -0
- package/cli/runtime.mjs +115 -0
- package/dist/assets/html2canvas.esm-QH1iLAAe.js +22 -0
- package/dist/assets/index-B97MkVMs.css +1 -0
- package/dist/assets/index-qtCM2D7O.js +21271 -0
- package/dist/assets/index.es-C6C0sneB.js +18 -0
- package/dist/assets/purify.es-CAi2OJFm.js +3 -0
- package/dist/assets/visual-export-DjbjgQbA.js +173 -0
- package/dist/favicon.svg +2 -0
- package/dist/fonts/DM-Sans-OFL.txt +93 -0
- package/dist/fonts/Manrope-OFL.txt +93 -0
- package/dist/fonts/NotoSans-Regular.ttf +0 -0
- package/dist/fonts/OFL.txt +94 -0
- package/dist/fonts/dm-sans-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/manrope-latin-wght-normal.woff2 +0 -0
- package/dist/index.html +4 -0
- package/dist/licenses/aws-architect-LICENSE.txt +17 -0
- package/dist/licenses/aws-mcp-LICENSE.txt +175 -0
- package/dist/licenses/aws-mcp-NOTICE.txt +1 -0
- package/dist/licenses/cloud-emulation-notices.txt +36619 -0
- package/dist/licenses/dependency-notices.txt +6379 -0
- package/dist/licenses/emulation-notices.txt +717 -0
- package/dist/licenses/github-copilot-sdk-LICENSE.txt +21 -0
- package/dist/licenses/memory-dependency-notices.txt +3319 -0
- package/dist/licenses/openarchflow-LICENSE.txt +21 -0
- package/dist/licenses/python-dependency-notices.txt +11951 -0
- package/docs/upstream-lock.json +26 -0
- package/knowledge/engineering-practices.json +536 -0
- package/package.json +30 -4
- package/packaging/uv-release-lock.json +54 -0
- package/public/licenses/aws-architect-LICENSE.txt +17 -0
- package/public/licenses/aws-mcp-LICENSE.txt +175 -0
- package/public/licenses/aws-mcp-NOTICE.txt +1 -0
- package/public/licenses/cloud-emulation-notices.txt +36619 -0
- package/public/licenses/dependency-notices.txt +6379 -0
- package/public/licenses/emulation-notices.txt +717 -0
- package/public/licenses/github-copilot-sdk-LICENSE.txt +21 -0
- package/public/licenses/memory-dependency-notices.txt +3319 -0
- package/public/licenses/openarchflow-LICENSE.txt +21 -0
- package/public/licenses/python-dependency-notices.txt +11951 -0
- package/scripts/terraform-render.mjs +8 -0
- package/server/__init__.py +0 -0
- package/server/abstraction.py +28 -0
- package/server/agent_runtime.py +153 -0
- package/server/app.py +257 -0
- package/server/architect.py +112 -0
- package/server/architecture_activity.py +67 -0
- package/server/attachments.py +101 -0
- package/server/cloud-emulation-requirements.txt +29 -0
- package/server/codex_app_server.py +219 -0
- package/server/codex_engineering_backend.py +266 -0
- package/server/codex_worker_policy.py +170 -0
- package/server/contracts.py +315 -0
- package/server/copilot_worker.py +16 -0
- package/server/dependency_mirror.py +54 -0
- package/server/design_patch.py +43 -0
- package/server/emulation-requirements.txt +8 -0
- package/server/emulation_adapters.py +20 -0
- package/server/emulation_routes.py +98 -0
- package/server/emulation_worker.py +351 -0
- package/server/engineering_artifacts.py +215 -0
- package/server/engineering_assets/application-runtime.json +4372 -0
- package/server/engineering_assets/architecture_work.schema.json +79 -0
- package/server/engineering_assets/materialize_runtime.py +62 -0
- package/server/engineering_assets/prepare_tools.py +96 -0
- package/server/engineering_assets/sql_validation.py +59 -0
- package/server/engineering_contexts.py +120 -0
- package/server/engineering_delivery.py +210 -0
- package/server/engineering_finalization.py +210 -0
- package/server/engineering_handoff.py +163 -0
- package/server/engineering_jobs.py +206 -0
- package/server/engineering_knowledge.py +75 -0
- package/server/engineering_reconciliation.py +159 -0
- package/server/engineering_routes.py +469 -0
- package/server/engineering_sessions.py +273 -0
- package/server/engineering_tools.py +166 -0
- package/server/generation_lint.py +18 -0
- package/server/local_providers.py +181 -0
- package/server/local_validation.py +236 -0
- package/server/memory-requirements.lock +181 -0
- package/server/memory-requirements.txt +6 -0
- package/server/memory_routes.py +82 -0
- package/server/memory_service.py +273 -0
- package/server/memory_worker.py +66 -0
- package/server/openai_voice.py +80 -0
- package/server/packaged_app.py +9 -0
- package/server/pricing.py +84 -0
- package/server/process_control_observation.py +31 -0
- package/server/prompts.py +123 -0
- package/server/public_faq_emulation_worker.py +44 -0
- package/server/requirements.lock +1618 -0
- package/server/requirements.txt +68 -0
- package/server/runtime_dependency_locks.py +27 -0
- package/server/runtime_evidence.py +93 -0
- package/server/settings.py +14 -0
- package/server/skills.py +103 -0
- package/server/storage_emulation_worker.py +160 -0
- package/server/structured_emulation_worker.py +48 -0
- package/server/terraform_routes.py +118 -0
- package/server/upstream/__init__.py +0 -0
- package/server/upstream/agent/__init__.py +1 -0
- package/server/upstream/agent/aws_architect.py +600 -0
- package/server/upstream/agent/config/__init__.py +1 -0
- package/server/upstream/agent/config/agent_config.py +82 -0
- package/server/upstream/agent/config/prompts.py +138 -0
- package/server/upstream/agent/rate_limiter.py +62 -0
- package/server/upstream/utils/__init__.py +1 -0
- package/server/upstream/utils/file_writer.py +43 -0
- package/server/validation_applicability.py +85 -0
- package/server/validation_jobs.py +252 -0
- package/server/validation_workers.py +48 -0
- package/server/voice_routes.py +91 -0
- package/server/voice_worker.py +26 -0
- package/specs/028-convergence-evaluation/evidence/20261110-ibm-invoice-native/registry-structured/qualification.json +72 -0
- package/specs/028-convergence-evaluation/evidence/20261110-invoice-runtime/durable-current/receipt.json +61 -0
- package/specs/029-general-purpose-engine/evidence/20261111-runtime-dependencies/sdk/receipt.json +22 -0
- package/src/ArchitectureActivity.jsx +54 -0
- package/src/ArchitectureWorkPanel.jsx +46 -0
- package/src/ArtifactChecks.jsx +49 -0
- package/src/BlockRequirements.jsx +13 -0
- package/src/BrainActivity.jsx +11 -0
- package/src/ChatMessage.jsx +19 -0
- package/src/ChatResizeHandle.jsx +6 -0
- package/src/CodePreview.jsx +8 -0
- package/src/ComponentReview.jsx +31 -0
- package/src/DeliveryViews.jsx +59 -0
- package/src/EmulationPanel.jsx +44 -0
- package/src/EngagementViews.jsx +385 -0
- package/src/EngineeringPanel.jsx +151 -0
- package/src/ImplementationDelivery.jsx +55 -0
- package/src/JourneyViews.jsx +400 -0
- package/src/MemoryPanel.jsx +46 -0
- package/src/OpenAIVoicePanel.jsx +65 -0
- package/src/OutputsView.jsx +65 -0
- package/src/TerraformView.jsx +57 -0
- package/src/WorkbenchDialogs.jsx +532 -0
- package/src/activity-presentation.mjs +28 -0
- package/src/ai-qualification-scenarios.mjs +31 -0
- package/src/approval-application-files.mjs +32 -0
- package/src/approval-applications.mjs +82 -0
- package/src/approval-spec-kit.mjs +30 -0
- package/src/architecture-activity.css +28 -0
- package/src/architecture-activity.mjs +63 -0
- package/src/architecture-work.mjs +176 -0
- package/src/artifact-work.mjs +103 -0
- package/src/async-documents.mjs +191 -0
- package/src/atflow.css +1140 -0
- package/src/atforma.css +748 -0
- package/src/atmem-tokens.css +79 -0
- package/src/aws-preflight.mjs +60 -0
- package/src/aws-public-faq.mjs +102 -0
- package/src/aws-validation-scenarios.mjs +10 -0
- package/src/aws-validation.mjs +48 -0
- package/src/azure-plan-mocks.mjs +25 -0
- package/src/azure-structured.mjs +133 -0
- package/src/bedrock-summary.mjs +152 -0
- package/src/bounded-rag.mjs +60 -0
- package/src/brand.css +9 -0
- package/src/canvas-view.mjs +28 -0
- package/src/capability-composition.mjs +44 -0
- package/src/chat-attachments.mjs +13 -0
- package/src/cloud-provider-locks.mjs +9 -0
- package/src/cloud-storage-scenarios.mjs +2 -0
- package/src/component-review.mjs +55 -0
- package/src/composition-spec-kit.mjs +30 -0
- package/src/consultation-context.mjs +15 -0
- package/src/consultation.mjs +52 -0
- package/src/container-contracts.mjs +5 -0
- package/src/container-inspection.mjs +75 -0
- package/src/container-runtime.mjs +30 -0
- package/src/container-security-inspection.mjs +49 -0
- package/src/container-terraform.mjs +109 -0
- package/src/conversation.mjs +17 -0
- package/src/core.mjs +863 -0
- package/src/cross-cloud-storage.mjs +100 -0
- package/src/delivery-capabilities.mjs +25 -0
- package/src/delivery.mjs +58 -0
- package/src/deployment-ownership.mjs +10 -0
- package/src/deployment-region.mjs +11 -0
- package/src/derive.mjs +31 -0
- package/src/design-build-flow.mjs +10 -0
- package/src/diagram-attention.mjs +24 -0
- package/src/discovery.mjs +359 -0
- package/src/document.mjs +170 -0
- package/src/emulation-feedback.mjs +61 -0
- package/src/emulation-guidance.mjs +37 -0
- package/src/engagement.mjs +274 -0
- package/src/engineering-client.mjs +73 -0
- package/src/engineering-defaults.mjs +17 -0
- package/src/engineering.css +31 -0
- package/src/enterprise-application.mjs +76 -0
- package/src/enterprise-aws-host-infrastructure.mjs +62 -0
- package/src/enterprise-aws-host-tests.mjs +15 -0
- package/src/enterprise-aws-infrastructure-tests.mjs +38 -0
- package/src/enterprise-aws-infrastructure.mjs +138 -0
- package/src/enterprise-google-infrastructure.mjs +84 -0
- package/src/enterprise-google-tests.mjs +25 -0
- package/src/estimate.mjs +188 -0
- package/src/existing-references.mjs +18 -0
- package/src/external-identities.mjs +17 -0
- package/src/faq-lambda-build.mjs +28 -0
- package/src/gcp-structured.mjs +104 -0
- package/src/generation-provider.mjs +7 -0
- package/src/generation-quality.mjs +69 -0
- package/src/handoff.mjs +141 -0
- package/src/ibm-registry.mjs +12 -0
- package/src/ibm-structured.mjs +103 -0
- package/src/identifiers.mjs +15 -0
- package/src/implementation-map.mjs +14 -0
- package/src/implementation-outcome.mjs +8 -0
- package/src/incomplete-terraform.mjs +9 -0
- package/src/integrations.ts +137 -0
- package/src/interface-contracts.mjs +30 -0
- package/src/invoice-application.mjs +66 -0
- package/src/invoice-aws-operations.mjs +136 -0
- package/src/invoice-aws.mjs +143 -0
- package/src/invoice-azure-operations.mjs +147 -0
- package/src/invoice-azure.mjs +134 -0
- package/src/invoice-builder.mjs +35 -0
- package/src/invoice-dependencies.mjs +43 -0
- package/src/invoice-gcp-operations.mjs +178 -0
- package/src/invoice-gcp.mjs +104 -0
- package/src/invoice-ibm-operations.mjs +278 -0
- package/src/invoice-ibm.mjs +142 -0
- package/src/invoice-operations.mjs +143 -0
- package/src/invoice-plan.mjs +45 -0
- package/src/invoice-region.mjs +6 -0
- package/src/invoice-spec-kit.mjs +61 -0
- package/src/invoice-state.mjs +7 -0
- package/src/invoice-terraform.mjs +29 -0
- package/src/invoice-tests.mjs +122 -0
- package/src/journey-workspace.css +72 -0
- package/src/journey.mjs +87 -0
- package/src/levels.mjs +145 -0
- package/src/local-agent.mjs +184 -0
- package/src/main.jsx +2458 -0
- package/src/model-policy-preflight.mjs +34 -0
- package/src/openai-voice.mjs +102 -0
- package/src/output-bundle.mjs +11 -0
- package/src/ownership-inspection.mjs +28 -0
- package/src/pack.mjs +201 -0
- package/src/pricing.mjs +31 -0
- package/src/production-state.mjs +8 -0
- package/src/project-copy.mjs +10 -0
- package/src/project-file.mjs +160 -0
- package/src/project-links.mjs +3 -0
- package/src/protected-state.mjs +43 -0
- package/src/public-faq-builder.mjs +19 -0
- package/src/public-faq-clouds.mjs +251 -0
- package/src/public-faq.mjs +122 -0
- package/src/pulumi.mjs +123 -0
- package/src/python-container.mjs +25 -0
- package/src/python-runtime.mjs +50 -0
- package/src/rag-handler.mjs +43 -0
- package/src/rag-web-assets.mjs +52 -0
- package/src/rag-web.mjs +68 -0
- package/src/records.mjs +177 -0
- package/src/resources.mjs +163 -0
- package/src/review.mjs +252 -0
- package/src/runtime/EnterpriseDocument.java +89 -0
- package/src/runtime/approved_http_destination.py +72 -0
- package/src/runtime/aws-lambda-qualification-lock.json +7 -0
- package/src/runtime/aws-python-lock.json +82 -0
- package/src/runtime/aws-web-python-lock.json +887 -0
- package/src/runtime/aws_json_model.py +42 -0
- package/src/runtime/azure-python-lock.json +863 -0
- package/src/runtime/azure-sources.json +8 -0
- package/src/runtime/azure-test-lock.json +23 -0
- package/src/runtime/azure_acceptance.py +192 -0
- package/src/runtime/azure_structured.py +153 -0
- package/src/runtime/bounded_rag.py +126 -0
- package/src/runtime/catalog_admin.py +70 -0
- package/src/runtime/cloud-sql-proxy-lock.json +8 -0
- package/src/runtime/cloud-sql-proxy-security-review.json +30 -0
- package/src/runtime/connector_cli.py +50 -0
- package/src/runtime/connector_sync.py +70 -0
- package/src/runtime/durable-python-lock.json +247 -0
- package/src/runtime/durable_workflow.py +325 -0
- package/src/runtime/enterprise-application-manifest.json +110 -0
- package/src/runtime/enterprise-application-sources.json +266 -0
- package/src/runtime/enterprise-auth-python-lock.json +592 -0
- package/src/runtime/enterprise-aws-host-bootstrap-source.json +1 -0
- package/src/runtime/enterprise-aws-host-probe-source.json +1 -0
- package/src/runtime/enterprise-aws-task-template.json +235 -0
- package/src/runtime/enterprise-document-lock.json +18 -0
- package/src/runtime/enterprise-document.Dockerfile +15 -0
- package/src/runtime/enterprise-runtime-aws-python-lock.json +1115 -0
- package/src/runtime/enterprise-runtime-azure-python-lock.json +1106 -0
- package/src/runtime/enterprise-runtime-gcp-python-lock.json +1060 -0
- package/src/runtime/enterprise-runtime-ibm-python-lock.json +1096 -0
- package/src/runtime/enterprise-runtime-python-lock.json +1058 -0
- package/src/runtime/enterprise-runtime.Dockerfile +15 -0
- package/src/runtime/enterprise-web-app.js +1 -0
- package/src/runtime/enterprise-web-entry.js +105 -0
- package/src/runtime/enterprise-web-lock.json +29 -0
- package/src/runtime/enterprise-web-notices.txt +229 -0
- package/src/runtime/enterprise-web.css +4 -0
- package/src/runtime/enterprise-web.html +8 -0
- package/src/runtime/enterprise_audit.py +91 -0
- package/src/runtime/enterprise_audit_schema.sql +25 -0
- package/src/runtime/enterprise_auth_schema.sql +67 -0
- package/src/runtime/enterprise_auth_store.py +241 -0
- package/src/runtime/enterprise_aws_host_bootstrap.py +120 -0
- package/src/runtime/enterprise_aws_host_probe.py +105 -0
- package/src/runtime/enterprise_aws_hosts.py +136 -0
- package/src/runtime/enterprise_aws_jobs.py +300 -0
- package/src/runtime/enterprise_aws_objects.py +93 -0
- package/src/runtime/enterprise_aws_transfer.py +83 -0
- package/src/runtime/enterprise_azure_batch_api.py +128 -0
- package/src/runtime/enterprise_azure_host.py +599 -0
- package/src/runtime/enterprise_azure_jobs.py +294 -0
- package/src/runtime/enterprise_azure_objects.py +234 -0
- package/src/runtime/enterprise_azure_pool.py +161 -0
- package/src/runtime/enterprise_azure_transfer.py +122 -0
- package/src/runtime/enterprise_configuration.py +136 -0
- package/src/runtime/enterprise_document.py +116 -0
- package/src/runtime/enterprise_document_cli.py +32 -0
- package/src/runtime/enterprise_document_contract.py +54 -0
- package/src/runtime/enterprise_document_job.py +109 -0
- package/src/runtime/enterprise_document_jobs.py +122 -0
- package/src/runtime/enterprise_document_jobs_schema.sql +23 -0
- package/src/runtime/enterprise_extraction_cache.py +186 -0
- package/src/runtime/enterprise_extraction_schema.sql +17 -0
- package/src/runtime/enterprise_google_jobs.py +275 -0
- package/src/runtime/enterprise_google_transfer.py +85 -0
- package/src/runtime/enterprise_http.py +212 -0
- package/src/runtime/enterprise_identity.py +52 -0
- package/src/runtime/enterprise_knowledge.py +152 -0
- package/src/runtime/enterprise_models.py +94 -0
- package/src/runtime/enterprise_native.py +181 -0
- package/src/runtime/enterprise_oauth.py +132 -0
- package/src/runtime/enterprise_operator.py +160 -0
- package/src/runtime/enterprise_parser_service.py +136 -0
- package/src/runtime/enterprise_parser_transport.py +68 -0
- package/src/runtime/enterprise_queries.py +255 -0
- package/src/runtime/enterprise_queries_schema.sql +27 -0
- package/src/runtime/enterprise_query_service.py +111 -0
- package/src/runtime/enterprise_secrets.py +110 -0
- package/src/runtime/enterprise_sessions.py +95 -0
- package/src/runtime/enterprise_sources.py +260 -0
- package/src/runtime/enterprise_web.py +39 -0
- package/src/runtime/enterprise_worker.py +68 -0
- package/src/runtime/export_contract_acceptance.py +18 -0
- package/src/runtime/faq-output-contract.json +40 -0
- package/src/runtime/faq-web-app.js +41 -0
- package/src/runtime/faq-web.css +1 -0
- package/src/runtime/faq-web.html +6 -0
- package/src/runtime/gcp-sources.json +9 -0
- package/src/runtime/gcp_acceptance.py +110 -0
- package/src/runtime/gcp_structured.py +150 -0
- package/src/runtime/http_acceptance.py +39 -0
- package/src/runtime/iap-web-app.js +36 -0
- package/src/runtime/iap-web-source.json +1 -0
- package/src/runtime/ibm-python-lock.json +856 -0
- package/src/runtime/ibm-sources.json +9 -0
- package/src/runtime/ibm_acceptance.py +133 -0
- package/src/runtime/ibm_structured.py +113 -0
- package/src/runtime/invoice-azapi-provider-lock.json +7 -0
- package/src/runtime/invoice-ibm-provider-lock.json +7 -0
- package/src/runtime/invoice-parser-lock.json +1199 -0
- package/src/runtime/invoice-parser-python-lock.json +56 -0
- package/src/runtime/invoice-parser.Dockerfile +190 -0
- package/src/runtime/invoice-sources.json +58 -0
- package/src/runtime/invoice-test-sources.json +24 -0
- package/src/runtime/invoice-web.css +2 -0
- package/src/runtime/invoice-web.html +12 -0
- package/src/runtime/invoice-web.js +112 -0
- package/src/runtime/invoice_configuration.py +17 -0
- package/src/runtime/invoice_document.py +95 -0
- package/src/runtime/invoice_extraction.py +96 -0
- package/src/runtime/invoice_http.py +129 -0
- package/src/runtime/invoice_identity.py +5 -0
- package/src/runtime/invoice_maintenance.py +40 -0
- package/src/runtime/invoice_native.py +77 -0
- package/src/runtime/invoice_object_store.py +153 -0
- package/src/runtime/invoice_operations.py +108 -0
- package/src/runtime/invoice_operator.py +79 -0
- package/src/runtime/invoice_operator_core.py +39 -0
- package/src/runtime/invoice_operator_job.py +147 -0
- package/src/runtime/invoice_parser_cli.py +17 -0
- package/src/runtime/invoice_parser_identity.py +39 -0
- package/src/runtime/invoice_parser_service.py +89 -0
- package/src/runtime/invoice_parser_transport.py +89 -0
- package/src/runtime/invoice_processing.py +24 -0
- package/src/runtime/invoice_retention.py +16 -0
- package/src/runtime/invoice_runtime_secrets.py +43 -0
- package/src/runtime/invoice_stage.py +80 -0
- package/src/runtime/invoice_web.py +39 -0
- package/src/runtime/invoice_worker.py +50 -0
- package/src/runtime/lambda_faq.py +5 -0
- package/src/runtime/parser-requirements.lock +4 -0
- package/src/runtime/policy_review.py +18 -0
- package/src/runtime/postgres-qualification-lock.json +21 -0
- package/src/runtime/public-faq-sources.json +22 -0
- package/src/runtime/public_catalog_admin.py +122 -0
- package/src/runtime/public_catalog_store.py +125 -0
- package/src/runtime/public_faq.py +144 -0
- package/src/runtime/public_faq_app.py +49 -0
- package/src/runtime/python-container-lock.json +18 -0
- package/src/runtime/rag-sources.json +10 -0
- package/src/runtime/rag_acceptance.py +60 -0
- package/src/runtime/rag_aws_adapter.py +95 -0
- package/src/runtime/rds-ca-source.json +9 -0
- package/src/runtime/rds-global-ca.pem +2888 -0
- package/src/runtime/state-contract-check-source.json +4 -0
- package/src/runtime/state_contract_check.py +338 -0
- package/src/runtime/structured-source.json +1 -0
- package/src/runtime/structured-web-app.js +71 -0
- package/src/runtime/structured-web-source.json +1 -0
- package/src/runtime/structured_http.py +105 -0
- package/src/runtime/structured_output.py +48 -0
- package/src/runtime/web-python-lock.json +802 -0
- package/src/runtime/web_user_admin.py +44 -0
- package/src/runtime/workflow_application.py +62 -0
- package/src/runtime/workflow_bindings.py +128 -0
- package/src/runtime/workflow_configuration.py +40 -0
- package/src/runtime/workflow_connection.py +105 -0
- package/src/runtime/workflow_contract.py +54 -0
- package/src/runtime/workflow_database.py +94 -0
- package/src/runtime/workflow_errors.py +6 -0
- package/src/runtime/workflow_http.py +178 -0
- package/src/runtime/workflow_identity.py +69 -0
- package/src/runtime/workflow_payload.py +118 -0
- package/src/runtime/workflow_process_stage.py +88 -0
- package/src/runtime/workflow_profile.py +91 -0
- package/src/runtime/workflow_review.py +106 -0
- package/src/runtime/workflow_role_bootstrap.py +104 -0
- package/src/runtime/workflow_schema.sql +72 -0
- package/src/runtime/workflow_worker.py +142 -0
- package/src/runtime-settings.mjs +15 -0
- package/src/s3-access.mjs +14 -0
- package/src/source-contracts.mjs +17 -0
- package/src/spec-kit.mjs +186 -0
- package/src/state-custody.mjs +32 -0
- package/src/state-inspection.mjs +45 -0
- package/src/state-spec-kit.mjs +13 -0
- package/src/storage-tests.mjs +25 -0
- package/src/structured-api.mjs +133 -0
- package/src/structured-contract.mjs +19 -0
- package/src/structured-operation-policy.mjs +2 -0
- package/src/structured-web.mjs +17 -0
- package/src/style.css +1 -0
- package/src/system-description.mjs +26 -0
- package/src/terraform-admission.mjs +66 -0
- package/src/terraform-composition.mjs +83 -0
- package/src/terraform-expressions.mjs +46 -0
- package/src/terraform-validation-coverage.mjs +11 -0
- package/src/terraform.mjs +128 -0
- package/src/text-statistics.mjs +51 -0
- package/src/upstream/openarchflow/format-payload.ts +26 -0
- package/src/upstream/openarchflow/import/mermaid.ts +205 -0
- package/src/upstream/openarchflow/import/sql-ddl.ts +109 -0
- package/src/upstream/openarchflow/layout.ts +54 -0
- package/src/upstream/openarchflow/providers/aws.ts +196 -0
- package/src/upstream/openarchflow/providers/azure.ts +126 -0
- package/src/upstream/openarchflow/providers/cloudnative.ts +71 -0
- package/src/upstream/openarchflow/providers/generic.ts +227 -0
- package/src/upstream/openarchflow/providers/integration.ts +22 -0
- package/src/upstream/openarchflow/providers/types.ts +2 -0
- package/src/upstream/openarchflow/templates.ts +937 -0
- package/src/upstream-catalog.mjs +10 -0
- package/src/useChatScroll.jsx +36 -0
- package/src/useEmulation.jsx +36 -0
- package/src/validation-receipt.mjs +10 -0
- package/src/visual-export.mjs +92 -0
- package/src/voice-conversation.mjs +117 -0
- package/src/work-intake.mjs +24 -0
- package/src/workflow-runtime-inventory.mjs +3 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
from .settings import setting, home as product_home
|
|
2
|
+
"""AtMem AI Architect's authenticated single-user scope policy over the real AtMem core SDK.
|
|
3
|
+
|
|
4
|
+
Application queue/receipts live in state.sqlite; memory and supersession live in AtMem.
|
|
5
|
+
No unfiltered dashboard, shared ~/.atmem store, or model-selected subject is exposed.
|
|
6
|
+
"""
|
|
7
|
+
import hashlib
|
|
8
|
+
import json
|
|
9
|
+
import os
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
import re
|
|
12
|
+
import sqlite3
|
|
13
|
+
import subprocess
|
|
14
|
+
import threading
|
|
15
|
+
import uuid
|
|
16
|
+
from contextlib import contextmanager
|
|
17
|
+
from datetime import datetime, timezone
|
|
18
|
+
|
|
19
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
20
|
+
SECRET_KEY = re.compile(r'^(password|secret|api_?key|access_?key|token|client_?secret)$', re.I)
|
|
21
|
+
SECRET_VALUE = re.compile(r'AKIA[0-9A-Z]{16}|sk-(?:ant-)?[A-Za-z0-9_-]{20,}|ghp_[A-Za-z0-9]{36}|AIza[\w-]{35}|-----BEGIN .*PRIVATE KEY-----')
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def safe(value):
|
|
25
|
+
if isinstance(value, str):
|
|
26
|
+
return not SECRET_VALUE.search(value)
|
|
27
|
+
if isinstance(value, list):
|
|
28
|
+
return all(safe(v) for v in value)
|
|
29
|
+
if isinstance(value, dict):
|
|
30
|
+
return all(not (SECRET_KEY.match(k) and v) and safe(v) for k, v in value.items())
|
|
31
|
+
return True
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def digest(value):
|
|
35
|
+
return hashlib.sha256(json.dumps(value, sort_keys=True, ensure_ascii=False).encode()).hexdigest()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def timestamp():
|
|
39
|
+
return datetime.now(timezone.utc).isoformat()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class MemoryService:
|
|
43
|
+
def __init__(self, home=None, worker=None):
|
|
44
|
+
self.home = Path(home or product_home()) / 'memory'
|
|
45
|
+
self.home.mkdir(parents=True, exist_ok=True, mode=0o700)
|
|
46
|
+
self.worker = str(worker or setting('MEMORY_PYTHON') or ROOT / '.memory-venv' / ('Scripts/python.exe' if os.name == 'nt' else 'bin/python'))
|
|
47
|
+
self.lock = threading.RLock()
|
|
48
|
+
self.error = None
|
|
49
|
+
with self.db() as db:
|
|
50
|
+
db.executescript('''
|
|
51
|
+
CREATE TABLE IF NOT EXISTS identity (id TEXT PRIMARY KEY);
|
|
52
|
+
CREATE TABLE IF NOT EXISTS settings (project TEXT PRIMARY KEY, enabled INTEGER NOT NULL DEFAULT 1);
|
|
53
|
+
CREATE TABLE IF NOT EXISTS snapshots (project TEXT PRIMARY KEY, revision INTEGER, entities TEXT, digest TEXT);
|
|
54
|
+
CREATE TABLE IF NOT EXISTS queue (seq INTEGER PRIMARY KEY AUTOINCREMENT, event_id TEXT UNIQUE, project TEXT, scope TEXT, key TEXT, text TEXT, source TEXT, state TEXT, created TEXT);
|
|
55
|
+
CREATE TABLE IF NOT EXISTS activity (id TEXT PRIMARY KEY, project TEXT, created TEXT, payload TEXT);
|
|
56
|
+
CREATE TABLE IF NOT EXISTS skill_settings (id TEXT PRIMARY KEY, enabled INTEGER);
|
|
57
|
+
''')
|
|
58
|
+
row = db.execute('SELECT id FROM identity').fetchone()
|
|
59
|
+
if 'reason' not in {r[1] for r in db.execute('PRAGMA table_info(queue)')}:
|
|
60
|
+
db.execute("ALTER TABLE queue ADD COLUMN reason TEXT DEFAULT ''")
|
|
61
|
+
self.owner = row[0] if row else str(uuid.uuid4())
|
|
62
|
+
if not row:
|
|
63
|
+
db.execute('INSERT INTO identity VALUES (?)', (self.owner,))
|
|
64
|
+
|
|
65
|
+
@contextmanager
|
|
66
|
+
def db(self):
|
|
67
|
+
db = sqlite3.connect(self.home / 'state.sqlite', timeout=15)
|
|
68
|
+
db.execute('PRAGMA secure_delete=ON')
|
|
69
|
+
try:
|
|
70
|
+
with db:
|
|
71
|
+
yield db
|
|
72
|
+
finally:
|
|
73
|
+
db.close()
|
|
74
|
+
|
|
75
|
+
def project(self, project):
|
|
76
|
+
if not isinstance(project, str) or not re.fullmatch(r'[A-Za-z0-9-]{8,64}', project):
|
|
77
|
+
raise ValueError('Invalid project identity')
|
|
78
|
+
return project
|
|
79
|
+
|
|
80
|
+
def subject(self, scope, project):
|
|
81
|
+
return 'atforma-' + digest([self.owner, scope, project if scope == 'project' else 'shared'])[:40]
|
|
82
|
+
|
|
83
|
+
def enabled(self, project):
|
|
84
|
+
with self.db() as db:
|
|
85
|
+
row = db.execute('SELECT enabled FROM settings WHERE project=?', (project,)).fetchone()
|
|
86
|
+
return not row or bool(row[0])
|
|
87
|
+
|
|
88
|
+
def configure(self, project, enabled):
|
|
89
|
+
self.project(project)
|
|
90
|
+
with self.lock, self.db() as db:
|
|
91
|
+
db.execute('INSERT OR REPLACE INTO settings VALUES (?,?)', (project, int(enabled)))
|
|
92
|
+
if not enabled:
|
|
93
|
+
db.execute("UPDATE queue SET state='cancelled' WHERE project=? AND state='pending'", (project,))
|
|
94
|
+
return {'enabled': enabled}
|
|
95
|
+
|
|
96
|
+
def call(self, operations):
|
|
97
|
+
result = subprocess.run([self.worker, '-I', str(ROOT / 'server/memory_worker.py')],
|
|
98
|
+
input=json.dumps({'database': str(self.home / 'memories.db'), 'operations': operations}),
|
|
99
|
+
text=True, capture_output=True, timeout=25, cwd=str(self.home))
|
|
100
|
+
try:
|
|
101
|
+
payload = json.loads(result.stdout)
|
|
102
|
+
except (ValueError, TypeError):
|
|
103
|
+
raise RuntimeError('AtMem runtime unavailable; run npm run setup:memory') from None
|
|
104
|
+
if result.returncode or 'error' in payload:
|
|
105
|
+
raise RuntimeError('AtMem rejected the operation (' + payload.get('error', 'worker failed') + ')')
|
|
106
|
+
self.error = None
|
|
107
|
+
return payload['results']
|
|
108
|
+
|
|
109
|
+
def enqueue(self, project, scope, key, text, event_id=None, source=''):
|
|
110
|
+
if not safe(text) or len(text) > 1900:
|
|
111
|
+
raise ValueError('Memory content is too long or looks like a credential')
|
|
112
|
+
event_id = event_id or digest([project, scope, key, text])
|
|
113
|
+
with self.db() as db:
|
|
114
|
+
db.execute("INSERT OR IGNORE INTO queue(event_id,project,scope,key,text,source,state,created) VALUES (?,?,?,?,?,?,'pending',?)", (event_id, project, scope, key, text, source, timestamp()))
|
|
115
|
+
|
|
116
|
+
def flush(self):
|
|
117
|
+
with self.lock:
|
|
118
|
+
with self.db() as db:
|
|
119
|
+
rows = db.execute("SELECT seq,event_id,project,scope,key,text,source FROM queue WHERE state='pending' ORDER BY seq LIMIT 500").fetchall()
|
|
120
|
+
if not rows:
|
|
121
|
+
return True
|
|
122
|
+
try:
|
|
123
|
+
# The worker durably receipts each event so a partial batch can replay safely.
|
|
124
|
+
results = self.call([{'action': 'remember', 'subject': self.subject(scope, project), 'key': key, 'text': text, 'eventId': event, 'source': source} for seq, event, project, scope, key, text, source in rows])
|
|
125
|
+
with self.db() as db:
|
|
126
|
+
for row, result in zip(rows, results):
|
|
127
|
+
db.execute("UPDATE queue SET state=?,reason=?,text='',source='' WHERE seq=?", ('rejected' if result.get('refused') else 'synced', json.dumps(result.get('refused',[])), row[0]))
|
|
128
|
+
return True
|
|
129
|
+
except (OSError, RuntimeError, subprocess.TimeoutExpired):
|
|
130
|
+
self.error = 'AtMem unavailable — using this project only; eligible changes queued'
|
|
131
|
+
return False
|
|
132
|
+
|
|
133
|
+
@staticmethod
|
|
134
|
+
def entities(file):
|
|
135
|
+
values = {}
|
|
136
|
+
design = file.get('design') or {}
|
|
137
|
+
# The editable project already holds the diagram, comments and conversation brief.
|
|
138
|
+
# Only durable, confirmed facts belong in long-term memory.
|
|
139
|
+
for category in ('requirements', 'assumptions', 'openQuestions'):
|
|
140
|
+
for item in file.get(category, [])[:300]:
|
|
141
|
+
if category != 'requirements' or item.get('source') != 'user' or item.get('priority') != 'must' or str(item.get('id','')).startswith('drv-'):
|
|
142
|
+
continue
|
|
143
|
+
key = str(item.get('id', ''))
|
|
144
|
+
content = item.get('statement') or item.get('question')
|
|
145
|
+
if key and content:
|
|
146
|
+
values[f'{category}.{key}'] = f'{category} [{key}]: {content}; status: {item.get("status", "recorded")}'[:1800]
|
|
147
|
+
for item in file.get('discovery', {}).get('facts', [])[:300]:
|
|
148
|
+
if isinstance(item, dict) and item.get('name') == 'budget.per_month' and not item.get('conflictsWith'):
|
|
149
|
+
name = str(item['name'])
|
|
150
|
+
values['fact.' + name] = f'Project fact {name}: {item.get("value")} {item.get("unit", "")}; stated {item.get("madeAt", "unknown")}' + ('; unresolved conflict: confirm with user' if item.get('conflictsWith') else '')
|
|
151
|
+
decisions = file.get('decisions', [])
|
|
152
|
+
for item in decisions[:200]:
|
|
153
|
+
if item.get('status') != 'Accepted':
|
|
154
|
+
continue
|
|
155
|
+
subject = str(item.get('subject') or item.get('id') or 'decision')
|
|
156
|
+
if subject.startswith('design.'):
|
|
157
|
+
continue
|
|
158
|
+
values['decision.' + subject] = f'Project decision {subject}: {item.get("decision") or item.get("title", "")}; status: {item.get("status", "Proposed")}; reason: {item.get("reason") or item.get("rationale") or "not recorded"}'[:1800]
|
|
159
|
+
return values
|
|
160
|
+
|
|
161
|
+
def sync(self, project, file):
|
|
162
|
+
self.project(project)
|
|
163
|
+
if not isinstance(file, dict) or file.get('format') not in {'atmem.ai-architect.project','atforma.project'} or file.get('meta', {}).get('id') != project or not safe(file):
|
|
164
|
+
raise ValueError('Invalid project snapshot or credential-bearing data')
|
|
165
|
+
revision = file.get('meta', {}).get('revision')
|
|
166
|
+
if not isinstance(revision, int) or revision < 1:
|
|
167
|
+
raise ValueError('Invalid project revision')
|
|
168
|
+
with self.lock:
|
|
169
|
+
if not self.enabled(project):
|
|
170
|
+
return {'enabled': False, 'status': 'disabled'}
|
|
171
|
+
entities = self.entities(file)
|
|
172
|
+
with self.db() as db:
|
|
173
|
+
old = db.execute('SELECT revision,entities,digest FROM snapshots WHERE project=?', (project,)).fetchone()
|
|
174
|
+
if old and revision < old[0]:
|
|
175
|
+
return {'status': 'conflict', 'detail': 'Older project revision; memory was not changed'}
|
|
176
|
+
previous = json.loads(old[1]) if old else {}
|
|
177
|
+
change_id = str(uuid.uuid4())
|
|
178
|
+
with self.db() as db:
|
|
179
|
+
# Snapshot update and outbox insertion are one transaction: no lost change on crash.
|
|
180
|
+
for key in previous.keys() | entities.keys():
|
|
181
|
+
text = entities.get(key, f'{key} was removed from this project; do not treat the earlier value as current.')
|
|
182
|
+
if previous.get(key) == entities.get(key):
|
|
183
|
+
continue
|
|
184
|
+
db.execute("INSERT INTO queue(event_id,project,scope,key,text,source,state,created) VALUES (?,?,?,?,?,?,'pending',?)", (digest([change_id,key]), project, 'project', key, text, 'project snapshot r' + str(revision), timestamp()))
|
|
185
|
+
db.execute('INSERT OR REPLACE INTO snapshots VALUES (?,?,?,?)', (project, revision, json.dumps(entities), digest(file)))
|
|
186
|
+
self.flush()
|
|
187
|
+
return self.status(project)
|
|
188
|
+
|
|
189
|
+
def status(self, project):
|
|
190
|
+
with self.db() as db:
|
|
191
|
+
counts = dict(db.execute('SELECT state,count(*) FROM queue WHERE project=? GROUP BY state', (project,)).fetchall())
|
|
192
|
+
return {'enabled': self.enabled(project), 'status': 'disabled' if not self.enabled(project) else 'unavailable' if self.error else 'ready', 'pending': counts.get('pending', 0), 'rejected': counts.get('rejected', 0), 'engine': 'AtMem 2.3.10 core SDK', 'policy': 'AtMem AI Architect single-user scope and opt-out policy', 'detail': self.error}
|
|
193
|
+
|
|
194
|
+
def profile(self, project, field, value):
|
|
195
|
+
if field not in {'explanation', 'experience', 'iac', 'preferences'} or not value.strip() or len(value) > 1000:
|
|
196
|
+
raise ValueError('Choose a profile field and enter up to 1,000 characters')
|
|
197
|
+
with self.lock:
|
|
198
|
+
if not self.enabled(project):
|
|
199
|
+
raise ValueError('Memory is disabled for this project')
|
|
200
|
+
# User presses Remember; these are confirmed preferences, not model inferences.
|
|
201
|
+
self.enqueue(project, 'user', 'profile.' + field, f'User-confirmed {field}: {value.strip()}', event_id=str(uuid.uuid4()))
|
|
202
|
+
self.flush()
|
|
203
|
+
return self.status(project)
|
|
204
|
+
|
|
205
|
+
def inspect(self, project):
|
|
206
|
+
self.project(project)
|
|
207
|
+
with self.lock:
|
|
208
|
+
if self.enabled(project):
|
|
209
|
+
self.flush()
|
|
210
|
+
subjects = [self.subject('user', project), self.subject('project', project), self.subject('knowledge', project)]
|
|
211
|
+
try:
|
|
212
|
+
results = self.call([{'action': 'list', 'subject': s} for s in subjects])
|
|
213
|
+
records = [[{k: r.get(k) for k in ('id','content','status','fact_key','created_at','supersedes_id')} for r in rows[-200:] if r.get('status') != 'tombstoned'] for rows in results]
|
|
214
|
+
except (OSError, RuntimeError, subprocess.TimeoutExpired):
|
|
215
|
+
self.error = 'AtMem unavailable — using this project only; eligible changes queued'
|
|
216
|
+
records = [[], [], []]
|
|
217
|
+
with self.db() as db:
|
|
218
|
+
activity = [{'id': r[0], 'createdAt': r[1], **json.loads(r[2])} for r in db.execute('SELECT id,created,payload FROM activity WHERE project=? ORDER BY created DESC LIMIT 20', (project,))]
|
|
219
|
+
events = [{'key':r[0],'status':r[1],'reason':r[2],'createdAt':r[3]} for r in db.execute("SELECT key,state,reason,created FROM queue WHERE project=? AND state IN ('pending','rejected') ORDER BY seq DESC LIMIT 20",(project,))]
|
|
220
|
+
return {**self.status(project), 'profile': records[0], 'project': records[1], 'knowledge': records[2], 'activity': activity, 'events':events}
|
|
221
|
+
|
|
222
|
+
def forget(self, project, scope, record_id):
|
|
223
|
+
if scope not in {'user', 'project'}:
|
|
224
|
+
raise ValueError('Invalid memory scope')
|
|
225
|
+
with self.lock:
|
|
226
|
+
result = self.call([{'action': 'forget', 'subject': self.subject(scope, project), 'recordId': record_id}])[0]
|
|
227
|
+
key = result.pop('key')
|
|
228
|
+
with self.db() as db:
|
|
229
|
+
# Remove plaintext outbox copies too, and cancel replay of this exact key.
|
|
230
|
+
if scope == 'user':
|
|
231
|
+
db.execute('DELETE FROM queue WHERE scope=? AND key=?', (scope, key))
|
|
232
|
+
else:
|
|
233
|
+
db.execute('DELETE FROM queue WHERE project=? AND scope=? AND key=?', (project, scope, key))
|
|
234
|
+
return result
|
|
235
|
+
|
|
236
|
+
def recall(self, project, query):
|
|
237
|
+
self.project(project)
|
|
238
|
+
with self.lock:
|
|
239
|
+
if not self.enabled(project):
|
|
240
|
+
return [], self.status(project)
|
|
241
|
+
if not self.flush():
|
|
242
|
+
return [], self.status(project)
|
|
243
|
+
try:
|
|
244
|
+
rows = self.call([{'action': 'recall', 'subject': self.subject(s, project), 'query': query, 'limit': 6} for s in ('user', 'project')])
|
|
245
|
+
context = [{'scope': scope, 'id': r['id'], 'text': r['content'], 'sourceDate': r['created_at'], 'key': r.get('fact_key')} for scope, records in zip(('user','project'), rows) for r in records]
|
|
246
|
+
return context, self.status(project)
|
|
247
|
+
except (OSError, RuntimeError, subprocess.TimeoutExpired):
|
|
248
|
+
self.error = 'AtMem unavailable — using this project only; eligible changes queued'
|
|
249
|
+
return [], self.status(project)
|
|
250
|
+
|
|
251
|
+
def record_turn(self, project, payload):
|
|
252
|
+
ident = str(uuid.uuid4())
|
|
253
|
+
with self.lock, self.db() as db:
|
|
254
|
+
db.execute('INSERT INTO activity VALUES (?,?,?,?)', (ident, project, timestamp(), json.dumps(payload)))
|
|
255
|
+
db.execute('DELETE FROM activity WHERE project=? AND id NOT IN (SELECT id FROM activity WHERE project=? ORDER BY created DESC LIMIT 100)', (project, project))
|
|
256
|
+
if self.enabled(project) and payload.get('recordIds'):
|
|
257
|
+
try:
|
|
258
|
+
self.call([{'action': 'log', 'subject': self.subject('project', project), 'eventType': 'atforma.turn', 'payload': payload}])
|
|
259
|
+
except (OSError, RuntimeError, subprocess.TimeoutExpired):
|
|
260
|
+
pass
|
|
261
|
+
return ident
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
_instance = None
|
|
265
|
+
_instance_home = None
|
|
266
|
+
_guard = threading.Lock()
|
|
267
|
+
def service():
|
|
268
|
+
global _instance, _instance_home
|
|
269
|
+
home = str(product_home())
|
|
270
|
+
with _guard:
|
|
271
|
+
if _instance is None or _instance_home != home:
|
|
272
|
+
_instance, _instance_home = MemoryService(home), home
|
|
273
|
+
return _instance
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Isolated pinned AtMem SDK process. JSON over stdio; no model/cloud tools."""
|
|
2
|
+
import json
|
|
3
|
+
import sys
|
|
4
|
+
import sqlite3
|
|
5
|
+
from importlib.metadata import version
|
|
6
|
+
from atmem import Memory
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def run(payload):
|
|
10
|
+
if version('atmem') != '2.3.10':
|
|
11
|
+
raise RuntimeError('AtMem AI Architect requires the tested AtMem 2.3.10 runtime')
|
|
12
|
+
memory = Memory(payload['database'], auto_vectors=False)
|
|
13
|
+
receipts = sqlite3.connect(payload['database'] + '.receipts.sqlite')
|
|
14
|
+
receipts.execute('CREATE TABLE IF NOT EXISTS receipts (id TEXT PRIMARY KEY, result TEXT)')
|
|
15
|
+
results = []
|
|
16
|
+
try:
|
|
17
|
+
for op in payload['operations']:
|
|
18
|
+
subject = op['subject']
|
|
19
|
+
action = op['action']
|
|
20
|
+
if action == 'remember':
|
|
21
|
+
previous = receipts.execute('SELECT result FROM receipts WHERE id=?', (op['eventId'],)).fetchone()
|
|
22
|
+
if previous:
|
|
23
|
+
results.append(json.loads(previous[0]))
|
|
24
|
+
continue
|
|
25
|
+
value = memory.remember(subject, message=op['text'], source_type='user_message',
|
|
26
|
+
interpreted_fact=op['text'], interpreted_fact_key=op['key'], actor='atforma',
|
|
27
|
+
raw={'interpreter': 'atforma-project-event-v1', 'event_id': op['eventId'], 'source_url': op.get('source', '')})
|
|
28
|
+
receipt = {'refused': value.get('refused', []), 'ids': [r['id'] for r in value.get('records', [])] + value.get('duplicate_ids', [])}
|
|
29
|
+
receipts.execute('INSERT INTO receipts VALUES (?,?)', (op['eventId'], json.dumps(receipt)))
|
|
30
|
+
receipts.commit()
|
|
31
|
+
results.append(receipt)
|
|
32
|
+
elif action == 'recall':
|
|
33
|
+
results.append(memory.recall(subject, op['query'], limit=op.get('limit', 6)))
|
|
34
|
+
elif action == 'list':
|
|
35
|
+
results.append(memory.list(subject, include_inactive=True))
|
|
36
|
+
elif action == 'forget':
|
|
37
|
+
# Forget the entire keyed preference history so old values cannot resurface.
|
|
38
|
+
records = memory.list(subject, include_inactive=True)
|
|
39
|
+
record = next((r for r in records if r['id'] == op['recordId'] and r['status'] != 'tombstoned'), None)
|
|
40
|
+
if record is None:
|
|
41
|
+
raise ValueError('Memory record is not available in this scope')
|
|
42
|
+
deletion_receipts = []
|
|
43
|
+
for r in records:
|
|
44
|
+
if r.get('fact_key') == record.get('fact_key') and r['status'] != 'tombstoned':
|
|
45
|
+
deletion_receipts.append(memory.forget_record(subject, r['id'])['receipt'])
|
|
46
|
+
results.append({'deleted': True, 'receipts': deletion_receipts, 'key': record.get('fact_key')})
|
|
47
|
+
elif action == 'audit':
|
|
48
|
+
report = memory.audit(subject)
|
|
49
|
+
results.append({'valid': report['audit_chain_valid'], 'events': report['audit_log'][-40:]})
|
|
50
|
+
elif action == 'log':
|
|
51
|
+
results.append(memory.log_action(subject, op['eventType'], op['payload'], actor='atforma'))
|
|
52
|
+
else:
|
|
53
|
+
raise ValueError('Unknown memory operation')
|
|
54
|
+
return {'version': version('atmem'), 'results': results}
|
|
55
|
+
finally:
|
|
56
|
+
memory.close()
|
|
57
|
+
receipts.close()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
if __name__ == '__main__':
|
|
61
|
+
try:
|
|
62
|
+
print(json.dumps(run(json.load(sys.stdin))))
|
|
63
|
+
except Exception as exc:
|
|
64
|
+
# No text/credentials from an exception cross this process boundary.
|
|
65
|
+
print(json.dumps({'error': type(exc).__name__}))
|
|
66
|
+
sys.exit(1)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""OpenAI audio transport credentials; never substitutes the selected Architect."""
|
|
2
|
+
import os
|
|
3
|
+
import time
|
|
4
|
+
import httpx
|
|
5
|
+
from fastapi import APIRouter, HTTPException
|
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
7
|
+
|
|
8
|
+
router = APIRouter()
|
|
9
|
+
MODEL = 'gpt-realtime-2.1-mini'
|
|
10
|
+
TRANSCRIPTION_MODEL = 'gpt-transcribe'
|
|
11
|
+
VOICE = 'marin'
|
|
12
|
+
TOKEN_URL = 'https://api.openai.com/v1/realtime/client_secrets'
|
|
13
|
+
_voice_key = None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def api_key():
|
|
17
|
+
# Dedicated voice credential first, then the existing server OpenAI key.
|
|
18
|
+
# Never a native-login token, project file or extracted CLI credential.
|
|
19
|
+
from .app import ARCHITECT
|
|
20
|
+
return _voice_key or ARCHITECT.keys.get('openai') or os.getenv('OPENAI_API_KEY')
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def configuration():
|
|
24
|
+
return {'model': MODEL, 'type': 'realtime', 'output_modalities': ['audio'],
|
|
25
|
+
'instructions': 'You are the audio interface for a separate Architect. Read only the supplied written reply aloud naturally. Do not answer architecture questions yourself, add decisions, use tools or claim to have performed work.',
|
|
26
|
+
'tools': [],
|
|
27
|
+
'audio': {'input': {'transcription': {'model': TRANSCRIPTION_MODEL},
|
|
28
|
+
'turn_detection': {'type': 'server_vad', 'create_response': False,
|
|
29
|
+
'interrupt_response': False}},
|
|
30
|
+
'output': {'voice': VOICE}}}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class VoiceRequest(BaseModel):
|
|
34
|
+
model_config = ConfigDict(extra='forbid')
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class VoiceCredentialRequest(VoiceRequest):
|
|
38
|
+
key: str = Field(max_length=5000, strict=True)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@router.post('/api/voice/openai/credentials')
|
|
42
|
+
async def configure_key(payload: VoiceCredentialRequest):
|
|
43
|
+
global _voice_key
|
|
44
|
+
_voice_key = payload.key.strip() or None
|
|
45
|
+
return {'configuredInMemory': bool(_voice_key)}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@router.get('/api/voice/openai/status')
|
|
49
|
+
async def status():
|
|
50
|
+
return {'available': bool(api_key()), 'engine': 'openai-realtime', 'model': MODEL,
|
|
51
|
+
'voice': VOICE, 'audioDestination': 'OpenAI', 'audioStoredByArchitect': False}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@router.post('/api/voice/openai/session')
|
|
55
|
+
async def create_session(payload: VoiceRequest):
|
|
56
|
+
key = api_key()
|
|
57
|
+
if not key:
|
|
58
|
+
raise HTTPException(503, 'OpenAI voice needs an OpenAI API key on the Architect server. Configure it in the voice panel; your selected Architect model stays unchanged.')
|
|
59
|
+
try:
|
|
60
|
+
async with httpx.AsyncClient(timeout=15, follow_redirects=False) as client:
|
|
61
|
+
response = await client.post(TOKEN_URL, headers={'Authorization': 'Bearer '+key},
|
|
62
|
+
json={'expires_after': {'anchor': 'created_at', 'seconds': 60}, 'session': configuration()})
|
|
63
|
+
if response.status_code == 429:
|
|
64
|
+
raise HTTPException(429, 'OpenAI voice is rate limited. Retry after a short wait.')
|
|
65
|
+
if response.status_code in {401, 403}:
|
|
66
|
+
raise HTTPException(503, 'The OpenAI API key could not start voice. Check its permissions and account access.')
|
|
67
|
+
if response.status_code != 200:
|
|
68
|
+
raise HTTPException(502, 'OpenAI voice could not start. Check API access and retry; no local voice fallback was selected.')
|
|
69
|
+
value = response.json()
|
|
70
|
+
if (not isinstance(value, dict) or not isinstance(value.get('value'), str)
|
|
71
|
+
or not value['value'].startswith('ek_') or len(value['value']) > 4096
|
|
72
|
+
or type(value.get('expires_at')) not in {int, float}
|
|
73
|
+
or not time.time() < value['expires_at'] <= time.time()+120):
|
|
74
|
+
raise ValueError('Invalid ephemeral credential response')
|
|
75
|
+
return {'value': value['value'], 'expires_at': value['expires_at'], 'model': MODEL, 'voice': VOICE}
|
|
76
|
+
except HTTPException:
|
|
77
|
+
raise
|
|
78
|
+
except Exception:
|
|
79
|
+
# Never expose upstream bodies, credentials or HTTP transport diagnostics.
|
|
80
|
+
raise HTTPException(502, 'OpenAI voice connection failed. Check API access and retry.') from None
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Serve the compiled UI and the authenticated loopback API from one process."""
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from fastapi.staticfiles import StaticFiles
|
|
4
|
+
from .app import app
|
|
5
|
+
|
|
6
|
+
frontend=Path(__file__).resolve().parents[1]/'dist'
|
|
7
|
+
if not (frontend/'index.html').is_file():
|
|
8
|
+
raise RuntimeError('The installed package has no compiled UI. Reinstall the complete Architect package.')
|
|
9
|
+
app.mount('/',StaticFiles(directory=frontend,html=True),name='architect-ui')
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Bounded public AWS price-list lookup, never model-generated price numbers."""
|
|
2
|
+
from datetime import datetime, timezone
|
|
3
|
+
import json
|
|
4
|
+
import re
|
|
5
|
+
import urllib.request
|
|
6
|
+
from functools import lru_cache
|
|
7
|
+
import time
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def parse_s3(data, region, url):
|
|
11
|
+
matches=[]
|
|
12
|
+
for sku, product in data.get('products',{}).items():
|
|
13
|
+
attrs=product.get('attributes',{})
|
|
14
|
+
if product.get('productFamily') != 'Storage' or attrs.get('volumeType') != 'Standard' or attrs.get('regionCode') != region or attrs.get('locationType') != 'AWS Region': continue
|
|
15
|
+
for term in data.get('terms',{}).get('OnDemand',{}).get(sku,{}).values():
|
|
16
|
+
for rate in term.get('priceDimensions',{}).values():
|
|
17
|
+
if rate.get('unit')=='GB-Mo' and rate.get('beginRange')=='0' and rate.get('endRange')=='51200':
|
|
18
|
+
price=float(rate.get('pricePerUnit',{}).get('USD','nan'))
|
|
19
|
+
if price >= 0 and price < 10:
|
|
20
|
+
matches.append({'price':price,'currency':'USD','unit':'GB-month','region':region,'service':'Amazon S3 Standard / '+sku,'source':'AWS public Price List','url':url,'date':datetime.now(timezone.utc).date().isoformat(),'publicationDate':data.get('publicationDate'),'description':rate.get('description'),'tierLimit':51200,'coverage':'S3 Standard storage, first 50 TB/month only; excludes requests, transfer, taxes and discounts'})
|
|
21
|
+
if len(matches)!=1: raise ValueError('Could not uniquely identify S3 Standard storage pricing for this region')
|
|
22
|
+
return matches[0]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@lru_cache(maxsize=32)
|
|
26
|
+
def _fetch(region, hour):
|
|
27
|
+
url=f'https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonS3/current/{region}/index.json'
|
|
28
|
+
with urllib.request.urlopen(urllib.request.Request(url,headers={'User-Agent':'AtMem AI Architect/0.2'}),timeout=12) as response:
|
|
29
|
+
raw=response.read(12_000_001)
|
|
30
|
+
if len(raw)>12_000_000: raise ValueError('Price list exceeds the supported size')
|
|
31
|
+
return parse_s3(json.loads(raw),region,url)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def aws_s3(region):
|
|
35
|
+
if not re.fullmatch(r'[a-z]{2}-(?:gov-)?[a-z]+-\d',region):
|
|
36
|
+
raise ValueError('Select an explicit AWS region such as ap-southeast-2 before fetching pricing')
|
|
37
|
+
return dict(_fetch(region,int(time.time()//3600)))
|
|
38
|
+
|
|
39
|
+
PROVIDER_PAGES = {
|
|
40
|
+
'aws':'https://aws.amazon.com/s3/pricing/',
|
|
41
|
+
'azure':'https://azure.microsoft.com/pricing/details/storage/blobs/',
|
|
42
|
+
'gcp':'https://cloud.google.com/storage/pricing',
|
|
43
|
+
'ibm':'https://www.ibm.com/products/cloud-object-storage/pricing',
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@lru_cache(maxsize=32)
|
|
47
|
+
def _azure_storage(region,hour):
|
|
48
|
+
from urllib.parse import urlencode
|
|
49
|
+
if not re.fullmatch(r'[a-z0-9]{3,40}',region):raise ValueError('Select an Azure region code')
|
|
50
|
+
query="serviceName eq 'Storage' and armRegionName eq '"+region+"' and meterName eq 'Hot LRS Data Stored' and priceType eq 'Consumption' and productName eq 'Blob Storage'"
|
|
51
|
+
url='https://prices.azure.com/api/retail/prices?'+urlencode({'$filter':query})
|
|
52
|
+
with urllib.request.urlopen(url,timeout=12) as response:data=json.loads(response.read(2_000_000))
|
|
53
|
+
matches=[r for r in data.get('Items',[]) if r.get('armRegionName')==region and r.get('productName')=='Blob Storage' and r.get('meterName')=='Hot LRS Data Stored' and r.get('tierMinimumUnits')==0 and r.get('currencyCode')=='USD' and r.get('unitOfMeasure')=='1 GB/Month']
|
|
54
|
+
if len(matches)!=1:raise ValueError('No unique matching Azure meter')
|
|
55
|
+
r=matches[0]
|
|
56
|
+
return {'available':True,'provider':'azure','price':r['retailPrice'],'currency':'USD','unit':'GB-month','region':region,'service':'Azure Blob Storage Hot LRS / '+r['skuId'],'source':'Azure Retail Prices API','url':url,'date':datetime.now(timezone.utc).date().isoformat(),'tierLimit':51200,'coverage':'Hot LRS base storage tier only; operations, transfer, redundancy alternatives, taxes and discounts excluded'}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def storage_quote(provider,region):
|
|
60
|
+
if provider not in PROVIDER_PAGES:raise ValueError('Choose AWS, Azure, Google Cloud or IBM')
|
|
61
|
+
if provider=='aws':return {**aws_s3(region),'provider':'aws','available':True}
|
|
62
|
+
if provider=='azure':return dict(_azure_storage(region,int(time.time()//3600)))
|
|
63
|
+
if provider=='gcp':
|
|
64
|
+
import os
|
|
65
|
+
key=os.getenv('GOOGLE_CLOUD_BILLING_API_KEY')
|
|
66
|
+
if key and re.fullmatch(r'[a-z]+-[a-z]+\d',region):
|
|
67
|
+
# Official catalogue; caller supplies the standard API key in server environment only.
|
|
68
|
+
url='https://cloudbilling.googleapis.com/v1/services/95FF-2EF5-5EA1/skus?currencyCode=USD'
|
|
69
|
+
request=urllib.request.Request(url,headers={'X-Goog-Api-Key':key})
|
|
70
|
+
with urllib.request.urlopen(request,timeout=12) as response:data=json.loads(response.read(8_000_000))
|
|
71
|
+
candidates=[]
|
|
72
|
+
for sku in data.get('skus',[]):
|
|
73
|
+
description=sku.get('description','')
|
|
74
|
+
if region not in sku.get('serviceRegions',[]) or 'Standard Storage' not in description or 'Dual' in description or 'Multi' in description:continue
|
|
75
|
+
for info in sku.get('pricingInfo',[])[:1]:
|
|
76
|
+
expression=info.get('pricingExpression',{})
|
|
77
|
+
if expression.get('usageUnit')!='GiBy.mo':continue
|
|
78
|
+
rates=expression.get('tieredRates',[])
|
|
79
|
+
if len(rates)!=1 or rates[0].get('startUsageAmount',0)!=0:continue
|
|
80
|
+
price=rates[0]['unitPrice'];value=float(price.get('units',0))+float(price.get('nanos',0))/1e9
|
|
81
|
+
candidates.append({'available':True,'provider':'gcp','price':value,'currency':'USD','unit':'GiB-month','region':region,'service':'Google Cloud Storage Standard / '+sku['skuId'],'source':'Google Cloud Billing Catalog','url':'https://cloud.google.com/skus/?currency=USD','date':datetime.now(timezone.utc).date().isoformat(),'coverage':'Standard storage only; operations, replication and transfer excluded'})
|
|
82
|
+
if len(candidates)==1:return candidates[0]
|
|
83
|
+
return {'available':False,'provider':'gcp','region':region,'sourceUrl':PROVIDER_PAGES[provider],'reason':'An exact regional storage SKU needs a configured Google Cloud Billing Catalog API key or a sourced quote. A generic/default-region web price will not be substituted.','nextQuestion':'Which Google Cloud region and storage class should we price?'}
|
|
84
|
+
return {'available':False,'provider':'ibm','region':region,'sourceUrl':PROVIDER_PAGES[provider],'reason':'IBM pricing depends on region, storage class and plan. No verified regional quote is configured; no AWS or invented rate is substituted.','nextQuestion':'Which IBM region and storage class or existing IBM quote should we use?'}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Trusted empty-source probe fragment; observations never grant capabilities.
|
|
2
|
+
|
|
3
|
+
Only libc prctl is used, not ISA-specific syscall numbers. RET_ALLOW stacks onto
|
|
4
|
+
the existing outer policy; it cannot remove that policy or restore privileges.
|
|
5
|
+
"""
|
|
6
|
+
PYTHON_PROCESS_CONTROLS = r'''
|
|
7
|
+
import ctypes,hashlib,platform,uuid
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
class Filter(ctypes.Structure):
|
|
10
|
+
_fields_=[('code',ctypes.c_ushort),('jt',ctypes.c_ubyte),('jf',ctypes.c_ubyte),('k',ctypes.c_uint32)]
|
|
11
|
+
class Program(ctypes.Structure):
|
|
12
|
+
_fields_=[('len',ctypes.c_ushort),('filter',ctypes.POINTER(Filter))]
|
|
13
|
+
libc=ctypes.CDLL(None,use_errno=True)
|
|
14
|
+
libc.prctl.argtypes=[ctypes.c_int,ctypes.c_ulong,ctypes.c_ulong,ctypes.c_ulong,ctypes.c_ulong]
|
|
15
|
+
libc.prctl.restype=ctypes.c_int
|
|
16
|
+
def observe_prctl(option,value):
|
|
17
|
+
ctypes.set_errno(0);code=libc.prctl(option,value,0,0,0);error=ctypes.get_errno()
|
|
18
|
+
return {'supported':code==0 and error==0,'returnCode':code,'errno':error}
|
|
19
|
+
controls={'noNewPrivileges':observe_prctl(38,1)}
|
|
20
|
+
filters=(Filter*1)(Filter(6,0,0,0x7fff0000));program=Program(1,filters)
|
|
21
|
+
# Do not try the dependent operation without its prerequisite. Null is unknown.
|
|
22
|
+
controls['seccompFilter']=None
|
|
23
|
+
if controls['noNewPrivileges']['supported']:
|
|
24
|
+
ctypes.set_errno(0);code=libc.prctl(22,2,ctypes.addressof(program),0,0);error=ctypes.get_errno()
|
|
25
|
+
controls['seccompFilter']={'supported':code==0 and error==0,'returnCode':code,'errno':error}
|
|
26
|
+
boot=Path('/proc/sys/kernel/random/boot_id').read_text().strip()
|
|
27
|
+
if str(uuid.UUID(boot))!=boot:raise ValueError('Unrecognized kernel boot identity')
|
|
28
|
+
result['processControls']=controls
|
|
29
|
+
result['executionContext']={'processMachine':platform.machine(),'kernelRelease':platform.release(),
|
|
30
|
+
'kernelBootSha256':hashlib.sha256(boot.encode()).hexdigest(),'uid':os.getuid()}
|
|
31
|
+
'''
|