@inneranimalmedia/agentsam-sdk 2.6.2 → 2.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTSAM.md +45 -1
- package/README.md +80 -0
- package/apps/README.md +34 -0
- package/apps/cad-creator/README.md +728 -0
- package/apps/cad-creator/shared/cad/package.json +19 -0
- package/apps/cad-creator/shared/cad/src/domain/operations.ts +7 -0
- package/apps/cad-creator/shared/cad/src/domain/project-contract.d.ts +3 -0
- package/apps/cad-creator/shared/cad/src/domain/project-contract.js +75 -0
- package/apps/cad-creator/shared/cad/src/domain/project-tools.d.ts +1 -0
- package/apps/cad-creator/shared/cad/src/domain/project-tools.js +24 -0
- package/apps/cad-creator/shared/cad/src/domain/validation.ts +191 -0
- package/apps/cad-creator/shared/cad/src/index.ts +4 -0
- package/apps/cad-creator/shared/cad/src/robotics/types.ts +232 -0
- package/apps/cad-creator/shared/cad/src/types.ts +507 -0
- package/apps/cad-creator/shared/cad/tsconfig.json +14 -0
- package/docs/AUTORAG.md +58 -0
- package/docs/BRAND_INTELLIGENCE.md +30 -0
- package/docs/CLI_SHELL.md +4 -2
- package/docs/CMS_CONTEXTUAL_COMPOSER.md +38 -0
- package/docs/MERKLE.md +4 -0
- package/docs/PROJECT_CONFIG.md +3 -0
- package/docs/REPOSITORY_KNOWLEDGE.md +2 -0
- package/docs/THEME_REFINERY.md +120 -0
- package/docs/architecture/PROVIDER-TOOLS-AND-COMPACTION.md +60 -0
- package/docs/architecture/STORAGE.md +87 -0
- package/docs/cad-project-tools.md +69 -0
- package/docs/cms-scaffolding-pattern-reference.md +73 -0
- package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS-codex-tui-20260919.md +113 -0
- package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS.md +85 -0
- package/docs/plans/AGENTSAM-MCP-CLIENT-2026-09-19.md +181 -0
- package/docs/plans/ASBD-PORTABLE-WORKGRAPH-UI-DEFERRED.md +34 -0
- package/docs/plans/ASTRA-BRIEF-2026-09-18.md +258 -0
- package/docs/plans/MULTI-AGENT-SPRINTS-2026-09-19.md +373 -0
- package/docs/plans/NEXT-AGENT-HANDOFF.md +167 -0
- package/docs/plans/RECONCILIATION-2026-09-19.md +178 -0
- package/docs/plugins.md +43 -0
- package/docs/tools/README.md +57 -0
- package/docs/tools/agent-and-orchestration.md +49 -0
- package/docs/tools/browser-and-research.md +46 -0
- package/docs/tools/cloudflare-platform.md +32 -0
- package/docs/tools/cms.md +25 -0
- package/docs/tools/communications.md +41 -0
- package/docs/tools/database-and-storage.md +62 -0
- package/docs/tools/design-and-media.md +64 -0
- package/docs/tools/filesystem-and-code.md +55 -0
- package/docs/tools/github.md +56 -0
- package/docs/tools/integrations-and-misc.md +16 -0
- package/docs/tools/memory.md +21 -0
- package/docs/tools/terminal-and-execution.md +29 -0
- package/docs/tools/tickets-and-platform.md +30 -0
- package/migrations/d1/0001_agentsam_plugin_runtime.sql +177 -0
- package/migrations/d1/0002_agentsam_ticket_ownership.sql +8 -0
- package/migrations/d1/0002_dynamic_model_policies.sql +23 -0
- package/migrations/d1/0003_expand_tool_handler_families.sql +18 -0
- package/migrations/d1/0004_project_aware_retrieval_lanes.sql +24 -0
- package/migrations/d1/0005_portable_knowledge_identity.sql +104 -0
- package/migrations/d1/0006_repair_ops_trail_account_scope.sql +14 -0
- package/migrations/d1/0007_repair_ops_trail_agent_run_account.sql +13 -0
- package/migrations/d1/0008_backfill_knowledge_run_legacy_tenant.sql +14 -0
- package/migrations/d1/0009_normalize_cloudflare_plugin_installations.sql +137 -0
- package/migrations/runtime/0001_cli_runtime.sql +67 -0
- package/migrations/runtime/0002_project_sessions.sql +15 -0
- package/migrations/runtime/0003_provider_continuations.sql +8 -0
- package/package.json +92 -12
- package/packages/agentsam-brand/README.md +21 -0
- package/packages/agentsam-brand/package.json +22 -0
- package/packages/agentsam-brand/src/contract.js +59 -0
- package/packages/agentsam-brand/src/extract.js +126 -0
- package/packages/agentsam-brand/src/goap-actions.js +73 -0
- package/packages/agentsam-brand/src/index.js +48 -0
- package/packages/agentsam-brand/src/plan.js +115 -0
- package/packages/agentsam-brand/src/resolve.js +139 -0
- package/packages/agentsam-brand/src/scan.js +250 -0
- package/packages/agentsam-brand/test/brand-scan.test.mjs +106 -0
- package/packages/agentsam-contracts/README.md +23 -0
- package/packages/agentsam-contracts/package.json +32 -0
- package/packages/agentsam-contracts/src/adapter.ts +25 -0
- package/packages/agentsam-contracts/src/agent.ts +35 -0
- package/packages/agentsam-contracts/src/artifacts.ts +33 -0
- package/packages/agentsam-contracts/src/authority.ts +29 -0
- package/packages/agentsam-contracts/src/context.ts +16 -0
- package/packages/agentsam-contracts/src/errors.ts +46 -0
- package/packages/agentsam-contracts/src/events.ts +47 -0
- package/packages/agentsam-contracts/src/execution.ts +50 -0
- package/packages/agentsam-contracts/src/hooks.ts +40 -0
- package/packages/agentsam-contracts/src/identity.ts +16 -0
- package/packages/agentsam-contracts/src/index.ts +14 -0
- package/packages/agentsam-contracts/src/models.ts +9 -0
- package/packages/agentsam-contracts/src/providers.ts +33 -0
- package/packages/agentsam-contracts/src/repository.ts +64 -0
- package/packages/agentsam-contracts/src/tools.ts +98 -0
- package/packages/agentsam-contracts/test/contracts.test.mjs +16 -0
- package/packages/agentsam-contracts/test/errors-catalog.test.mjs +25 -0
- package/packages/agentsam-contracts/test/repository.test.mjs +18 -0
- package/packages/agentsam-contracts/tsconfig.json +12 -0
- package/packages/agentsam-errors/package.json +17 -0
- package/packages/agentsam-errors/src/adapters/anthropic.js +15 -0
- package/packages/agentsam-errors/src/adapters/cad.js +109 -0
- package/packages/agentsam-errors/src/adapters/cloudflare.js +21 -0
- package/packages/agentsam-errors/src/adapters/cursor.js +4 -0
- package/packages/agentsam-errors/src/adapters/device.js +38 -0
- package/packages/agentsam-errors/src/adapters/docker.js +28 -0
- package/packages/agentsam-errors/src/adapters/gcp.js +14 -0
- package/packages/agentsam-errors/src/adapters/github.js +22 -0
- package/packages/agentsam-errors/src/adapters/google.js +17 -0
- package/packages/agentsam-errors/src/adapters/index.js +55 -0
- package/packages/agentsam-errors/src/adapters/internal.js +40 -0
- package/packages/agentsam-errors/src/adapters/oauth.js +24 -0
- package/packages/agentsam-errors/src/adapters/openai.js +17 -0
- package/packages/agentsam-errors/src/adapters/process.js +35 -0
- package/packages/agentsam-errors/src/adapters/provider.js +114 -0
- package/packages/agentsam-errors/src/envelope.js +186 -0
- package/packages/agentsam-errors/src/error.js +24 -0
- package/packages/agentsam-errors/src/fingerprint.js +35 -0
- package/packages/agentsam-errors/src/index.js +10 -0
- package/packages/agentsam-errors/src/normalize.js +30 -0
- package/packages/agentsam-errors/src/redaction.js +52 -0
- package/packages/agentsam-errors/src/render.js +16 -0
- package/packages/agentsam-errors/src/retry.js +10 -0
- package/packages/agentsam-errors/src/transport.js +52 -0
- package/packages/agentsam-errors/src/vocabulary.js +320 -0
- package/packages/agentsam-errors/test/envelope.test.mjs +70 -0
- package/packages/agentsam-errors/test/providers.test.mjs +99 -0
- package/packages/agentsam-errors/test/redaction.test.mjs +21 -0
- package/packages/agentsam-errors/test/runtime-cad-device.test.mjs +76 -0
- package/packages/agentsam-errors/test/transport.test.mjs +46 -0
- package/packages/agentsam-knowledge/package.json +15 -0
- package/packages/agentsam-knowledge/src/autorag/index.js +64 -0
- package/packages/agentsam-knowledge/src/backends/index.js +26 -0
- package/packages/agentsam-knowledge/src/index.js +3 -0
- package/packages/agentsam-knowledge/src/providers/index.js +95 -0
- package/packages/agentsam-knowledge/test/autorag.test.mjs +42 -0
- package/packages/agentsam-nav/README.md +40 -0
- package/packages/agentsam-nav/dist/Nav.d.ts +43 -0
- package/packages/agentsam-nav/dist/NavCollapsible.d.ts +10 -0
- package/packages/agentsam-nav/dist/NavContent.d.ts +2 -0
- package/packages/agentsam-nav/dist/NavFooter.d.ts +2 -0
- package/packages/agentsam-nav/dist/NavGroup.d.ts +3 -0
- package/packages/agentsam-nav/dist/NavHeader.d.ts +2 -0
- package/packages/agentsam-nav/dist/NavMenu.d.ts +22 -0
- package/packages/agentsam-nav/dist/NavProvider.d.ts +35 -0
- package/packages/agentsam-nav/dist/NavTrigger.d.ts +2 -0
- package/packages/agentsam-nav/dist/Surfaces.d.ts +41 -0
- package/packages/agentsam-nav/dist/browser.d.ts +11 -0
- package/packages/agentsam-nav/dist/browser.global.js +132 -0
- package/packages/agentsam-nav/dist/browser.js +613 -0
- package/packages/agentsam-nav/dist/contracts.d.ts +76 -0
- package/packages/agentsam-nav/dist/index.d.ts +11 -0
- package/packages/agentsam-nav/dist/index.js +614 -0
- package/packages/agentsam-nav/dist/legacy.css +83 -0
- package/packages/agentsam-nav/dist/shell.css +113 -0
- package/packages/agentsam-nav/dist/theme.css +113 -0
- package/packages/agentsam-nav/dist/utils.d.ts +1 -0
- package/packages/agentsam-nav/package.json +43 -0
- package/packages/agentsam-queue-control/README.md +107 -0
- package/packages/agentsam-queue-control/package.json +31 -0
- package/packages/agentsam-queue-control/schemas/job-envelope.schema.json +56 -0
- package/packages/agentsam-queue-control/src/adapters/cloudflare.js +152 -0
- package/packages/agentsam-queue-control/src/adapters/memory.js +38 -0
- package/packages/agentsam-queue-control/src/contracts.js +130 -0
- package/packages/agentsam-queue-control/src/control-plane.js +141 -0
- package/packages/agentsam-queue-control/src/dispatch.js +43 -0
- package/packages/agentsam-queue-control/src/index.js +7 -0
- package/packages/agentsam-queue-control/src/policy.js +88 -0
- package/packages/agentsam-queue-control/src/topology.js +66 -0
- package/packages/agentsam-queue-control/test/queue-control.test.mjs +100 -0
- package/packages/agentsam-repository/src/goap.js +718 -0
- package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +670 -0
- package/packages/agentsam-repository/src/index.js +5 -0
- package/packages/agentsam-repository/src/merkle/cloudflare-persistence.js +2 -2
- package/packages/agentsam-repository/src/tickets.js +184 -0
- package/packages/agentsam-repository/src/work-tracking.js +199 -0
- package/packages/agentsam-repository/src/workspace-state.js +176 -0
- package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +152 -0
- package/packages/connectors/cloudflare/src/index.js +297 -15
- package/packages/connectors/cloudflare/src/owner.js +43 -40
- package/packages/connectors/cloudflare/src/routes.js +167 -26
- package/packages/connectors/cloudflare/tests/connector.test.mjs +112 -2
- package/packages/heuristic-theme/README.md +11 -0
- package/packages/heuristic-theme/package.json +25 -0
- package/packages/heuristic-theme/src/index.js +2 -0
- package/packages/heuristic-theme/src/registry.js +36 -0
- package/packages/heuristic-theme/src/theme.js +41 -0
- package/packages/heuristic-theme/test/theme.test.mjs +26 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +64 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +96 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/resources.json +47 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +74 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/ui.json +35 -0
- package/packages/identity/package.json +3 -2
- package/packages/identity/src/adapters/cloudflare-d1/ids.js +4 -0
- package/packages/identity/src/adapters/cloudflare-d1/index.js +39 -1
- package/packages/identity/src/contracts/provider.js +3 -2
- package/packages/identity/src/frontend/auth-portal/pages/login.html +7 -0
- package/packages/identity/src/index.js +2 -0
- package/packages/identity/src/oauth/credentials.js +13 -0
- package/packages/identity/src/oauth/iam-platform.js +5 -5
- package/packages/identity/src/providers/cloudflare/index.js +19 -0
- package/packages/identity/src/providers/cloudflare/mapper.js +21 -0
- package/packages/identity/src/providers/cloudflare/oauth.js +48 -0
- package/packages/identity/src/providers/cloudflare/profile.js +28 -0
- package/packages/identity/src/providers/index.js +18 -2
- package/packages/identity/src/server/identity-service.js +13 -3
- package/packages/identity/src/server/worker-router.js +63 -8
- package/packages/identity/tests/identity-service.test.mjs +15 -0
- package/packages/providers/completeful/README.md +38 -0
- package/packages/providers/completeful/package.json +29 -0
- package/packages/providers/completeful/src/client.js +162 -0
- package/packages/providers/completeful/src/events.js +49 -0
- package/packages/providers/completeful/src/index.js +22 -0
- package/packages/providers/completeful/src/tools.js +579 -0
- package/packages/providers/completeful/src/webhooks.js +55 -0
- package/packages/providers/completeful/test/provider.test.mjs +196 -0
- package/packages/theme-church-site/README.md +10 -0
- package/packages/theme-church-site/package.json +30 -0
- package/packages/theme-church-site/src/harvest.json +14 -0
- package/packages/theme-church-site/src/index.js +84 -0
- package/packages/theme-church-site/test/theme.test.mjs +19 -0
- package/packages/theme-companions-site/README.md +10 -0
- package/packages/theme-companions-site/package.json +30 -0
- package/packages/theme-companions-site/src/harvest.json +12 -0
- package/packages/theme-companions-site/src/index.js +82 -0
- package/packages/theme-companions-site/test/theme.test.mjs +19 -0
- package/packages/theme-floors-site/README.md +10 -0
- package/packages/theme-floors-site/package.json +30 -0
- package/packages/theme-floors-site/src/harvest.json +14 -0
- package/packages/theme-floors-site/src/index.js +82 -0
- package/packages/theme-floors-site/test/theme.test.mjs +19 -0
- package/packages/theme-fuelnfree-site/README.md +10 -0
- package/packages/theme-fuelnfree-site/package.json +30 -0
- package/packages/theme-fuelnfree-site/src/harvest.json +13 -0
- package/packages/theme-fuelnfree-site/src/index.js +81 -0
- package/packages/theme-fuelnfree-site/test/theme.test.mjs +19 -0
- package/packages/theme-handyman-site/README.md +10 -0
- package/packages/theme-handyman-site/package.json +30 -0
- package/packages/theme-handyman-site/src/harvest.json +10 -0
- package/packages/theme-handyman-site/src/index.js +83 -0
- package/packages/theme-handyman-site/test/theme.test.mjs +19 -0
- package/packages/theme-insurance-site/README.md +10 -0
- package/packages/theme-insurance-site/package.json +30 -0
- package/packages/theme-insurance-site/src/harvest.json +10 -0
- package/packages/theme-insurance-site/src/index.js +83 -0
- package/packages/theme-insurance-site/test/theme.test.mjs +19 -0
- package/packages/theme-shinshu-site/README.md +10 -0
- package/packages/theme-shinshu-site/package.json +30 -0
- package/packages/theme-shinshu-site/src/harvest.json +12 -0
- package/packages/theme-shinshu-site/src/index.js +83 -0
- package/packages/theme-shinshu-site/test/theme.test.mjs +19 -0
- package/packages/work-graph/README.md +49 -0
- package/packages/work-graph/package.json +19 -0
- package/packages/work-graph/prototype/README.md +32 -0
- package/packages/work-graph/prototype/data/demo-workgraph.js +47 -0
- package/packages/work-graph/prototype/renderers/timeline-model.js +21 -0
- package/packages/work-graph/prototype/renderers/workgraph-runtime.js +38 -0
- package/packages/work-graph/prototype-gnantt.html +655 -0
- package/packages/work-graph/src/adapters/business/projects.js +23 -0
- package/packages/work-graph/src/adapters/engineering/git.js +22 -0
- package/packages/work-graph/src/adapters/engineering/mcp.js +22 -0
- package/packages/work-graph/src/index.js +76 -0
- package/packages/work-graph/src/renderers/gantt-model.js +11 -0
- package/packages/work-graph/src/renderers/timeline.js +16 -0
- package/packages/work-graph/test/work-graph.test.mjs +37 -0
- package/protocol/README.md +12 -0
- package/protocol/capabilities/cloudflare-cpu-audit-input.schema.json +30 -6
- package/protocol/capabilities/cloudflare-cpu-profile-input.schema.json +18 -4
- package/protocol/capabilities/cloudflare-wrangler-native-input.schema.json +59 -10
- package/protocol/capabilities/knowledge-search-input.schema.json +35 -0
- package/protocol/capabilities/manifest.json +163 -1
- package/protocol/capabilities/repository-audit-input.schema.json +39 -6
- package/protocol/capabilities/repository-snapshot-input.schema.json +15 -3
- package/protocol/capabilities/terminal-exec-input.schema.json +55 -0
- package/protocol/commerce/catalog.v1.json +50 -0
- package/protocol/errors/error-catalog.json +164 -0
- package/protocol/errors/error-envelope.schema.json +544 -0
- package/protocol/features/README.md +57 -0
- package/protocol/features/agentsam.feature.v1.schema.json +290 -0
- package/protocol/features/catalog.json +65 -0
- package/protocol/features/examples/provider-resend.feature.json +17 -0
- package/protocol/go/agentsam-go-runtime.v1.json +17 -0
- package/protocol/knowledge/LIFECYCLE.md +140 -0
- package/protocol/knowledge/README.md +4 -0
- package/protocol/presets/catalog.json +128 -19
- package/protocol/rpc/v1/errors.proto +24 -0
- package/protocol/theme-refinery/d1-reconciliation.md +48 -0
- package/protocol/theme-refinery/product-metadata.schema.json +27 -0
- package/protocol/theme-refinery/receipts/products-registry-batch-20260924.json +318 -0
- package/protocol/theme-refinery/receipts/theme-harvest-20260924.json +472 -0
- package/protocol/theme-refinery/reconciliation-receipt.schema.json +83 -0
- package/services/cad/server.py +249 -2
- package/src/agent/capability-adapter.js +15 -5
- package/src/agent/index.js +2 -1
- package/src/agent/model-turn.js +51 -0
- package/src/agent/responses-runner.js +304 -38
- package/src/capabilities/index.js +1 -0
- package/src/capabilities/terminal-exec.js +78 -0
- package/src/cli.js +117 -9
- package/src/cloudflare/index.js +6 -0
- package/src/cloudflare/runtime-status.js +393 -0
- package/src/cloudflare/wrangler.js +17 -1
- package/src/commands/app.js +106 -0
- package/src/commands/autorag.js +77 -0
- package/src/commands/brand.js +293 -0
- package/src/commands/cad.js +1 -0
- package/src/commands/connections.js +126 -29
- package/src/commands/context-economics.js +8 -0
- package/src/commands/db.js +7 -0
- package/src/commands/env.js +5 -4
- package/src/commands/eval.js +209 -14
- package/src/commands/go.js +365 -0
- package/src/commands/goap.js +176 -0
- package/src/commands/identity-init.js +27 -3
- package/src/commands/identity-protocol.js +195 -0
- package/src/commands/knowledge.js +64 -5
- package/src/commands/mcp.js +341 -0
- package/src/commands/merkle-persist.js +3 -1
- package/src/commands/merkle.js +18 -3
- package/src/commands/models.js +109 -23
- package/src/commands/plugins.js +175 -0
- package/src/commands/preferences.js +28 -8
- package/src/commands/product.js +53 -10
- package/src/commands/providers.js +118 -37
- package/src/commands/resume.js +9 -5
- package/src/commands/runtime-status.js +154 -0
- package/src/commands/shell.js +466 -55
- package/src/commands/status.js +82 -7
- package/src/commands/tunnel.js +228 -195
- package/src/commands/whoami.js +78 -6
- package/src/context/budget.js +6 -0
- package/src/context/index.js +2 -1
- package/src/context/project-card.js +75 -0
- package/src/errors/contract.js +34 -211
- package/src/errors/diagnostic.js +95 -51
- package/src/errors/index.js +6 -13
- package/src/eval/index.js +6 -0
- package/src/eval/live.js +439 -0
- package/src/features/resolve.js +242 -0
- package/src/go/build.js +108 -0
- package/src/go/cloudflare.js +207 -0
- package/src/go/contract.js +139 -0
- package/src/go/discover.js +96 -0
- package/src/go/index.js +13 -0
- package/src/go/receipts.js +77 -0
- package/src/go/registry.js +223 -0
- package/src/go/verify.js +31 -0
- package/src/index.js +100 -1
- package/src/knowledge/config.js +13 -5
- package/src/knowledge/engine.js +23 -8
- package/src/knowledge/index.js +1 -0
- package/src/knowledge/lane-registry.js +46 -0
- package/src/knowledge/providers/gemini.js +48 -8
- package/src/knowledge/service/client.js +13 -1
- package/src/knowledge/service/grpc-codec.js +156 -53
- package/src/knowledge/service/job-engine.js +133 -11
- package/src/knowledge/service/job-worker.js +34 -5
- package/src/knowledge/service/server.js +10 -1
- package/src/knowledge/store-discovery.js +77 -0
- package/src/lib/account-session.js +8 -2
- package/src/lib/agent-instructions.js +3 -0
- package/src/lib/auth.js +7 -3
- package/src/lib/cad/blender.js +42 -3
- package/src/lib/cad/d1-project-store.js +43 -0
- package/src/lib/cad/discovery.js +616 -0
- package/src/lib/cad/docker-executor.js +352 -0
- package/src/lib/cad/freecad.js +253 -0
- package/src/lib/cad/index.js +40 -0
- package/src/lib/cad/openscad.js +198 -0
- package/src/lib/cad/project-cli.d.ts +2 -0
- package/src/lib/cad/project-cli.js +21 -0
- package/src/lib/cad/project-contract.d.ts +3 -0
- package/src/lib/cad/project-contract.js +1 -0
- package/src/lib/cad/project-recipe.js +30 -0
- package/src/lib/cad/project-runtime.d.ts +2 -0
- package/src/lib/cad/project-runtime.js +53 -0
- package/src/lib/cad/project-store.js +25 -0
- package/src/lib/cad/project-workflows.js +31 -0
- package/src/lib/cad-docker.js +21 -2
- package/src/lib/cli-preferences.js +17 -2
- package/src/lib/core-client.js +37 -18
- package/src/lib/deploy/local-studio.js +6 -5
- package/src/lib/dockerize.js +3 -0
- package/src/lib/execution-approvals.js +1 -0
- package/src/lib/identity-scaffold.js +4 -1
- package/src/lib/knowledge-docker.js +9 -1
- package/src/lib/local-sessions.js +124 -34
- package/src/lib/local-status.js +35 -14
- package/src/lib/project-config.js +9 -0
- package/src/lib/provider-credentials.js +73 -11
- package/src/lib/scaffold/resolve-cloudflare-account.js +37 -0
- package/src/lib/scaffold/wizards/cms.js +2 -8
- package/src/lib/scaffold/wizards/worker-api.js +2 -8
- package/src/lib/slash-commands.js +9 -2
- package/src/local/migrations.js +109 -1
- package/src/local/runtime-store.js +31 -5
- package/src/local/sqlite.js +36 -1
- package/src/mcp/authority.js +348 -0
- package/src/mcp/client-adapters.js +431 -0
- package/src/mcp/client.js +172 -0
- package/src/mcp/index.js +47 -0
- package/src/mcp/telemetry.js +103 -0
- package/src/models/catalog.js +329 -51
- package/src/models/discovery.js +24 -4
- package/src/models/index.js +2 -0
- package/src/models/inventory-core.js +182 -0
- package/src/models/policy.js +20 -0
- package/src/plugins/cloudflare.js +103 -0
- package/src/plugins/completeful.js +69 -0
- package/src/plugins/contracts.js +86 -0
- package/src/plugins/index.js +11 -0
- package/src/plugins/registry.js +207 -0
- package/src/plugins/resource-scope.js +45 -0
- package/src/plugins/runtime.js +118 -0
- package/src/plugins/vectorize.js +31 -0
- package/src/progression/engine.js +171 -0
- package/src/progression/index.js +1 -0
- package/src/providers/cloudflare-chat.js +1 -1
- package/src/providers/gemini-generate-content.js +2 -1
- package/src/providers/openai-responses.js +45 -16
- package/src/providers/tool-schema.js +85 -0
- package/src/repository/index.js +29 -0
- package/src/rpc/generated/errors_pb.js +961 -1
- package/src/security/local-vault.js +415 -0
- package/src/security/process.js +20 -4
- package/src/status/actions.js +192 -0
- package/src/tools/hydrate.js +5 -1
- package/src/tools/index.js +7 -0
- package/src/tools/redact.js +64 -0
- package/src/tools/registry.js +83 -0
- package/src/tools/runtime.js +257 -0
- package/src/tools/search.js +21 -8
- package/src/ui/ansi.js +117 -3
- package/src/ui/cli/activity.js +76 -7
- package/src/ui/cli/footer.js +110 -9
- package/src/ui/cli/help.js +11 -4
- package/src/ui/wireframes.js +166 -0
- package/test/account-session.test.mjs +28 -0
- package/test/apps-scaffold-contract.test.mjs +16 -1
- package/test/capabilities.test.mjs +1 -1
- package/test/cli/eval-live.test.mjs +219 -0
- package/test/cli/go.test.mjs +71 -0
- package/test/cli/local-vault-and-provider-setup.test.mjs +268 -0
- package/test/cli/mcp-client.test.mjs +245 -0
- package/test/cli/runtime-ui.test.mjs +69 -2
- package/test/cli/status-actions.test.mjs +88 -0
- package/test/cli/wireframes-go-registry.test.mjs +54 -0
- package/test/cloudflare-connector.test.mjs +3 -6
- package/test/cloudflare-runtime.test.mjs +8 -1
- package/test/context.test.mjs +15 -0
- package/test/error-diagnostics.test.mjs +9 -0
- package/test/fixtures/cad/courtyard-house.json +208 -0
- package/test/go/cloudflare-probe.test.mjs +53 -0
- package/test/integration/app-command.test.mjs +55 -0
- package/test/integration/cad-discovery.test.mjs +158 -0
- package/test/integration/cad-docker-executor.test.mjs +249 -0
- package/test/integration/cad-execution.test.mjs +184 -0
- package/test/integration/cad-project-app.test.mjs +31 -0
- package/test/integration/cad-project-d1.test.mjs +25 -0
- package/test/integration/cad-project-native.test.mjs +24 -0
- package/test/integration/cad-project-workflow.test.mjs +9 -0
- package/test/integration/cad-project.test.mjs +82 -0
- package/test/integration/cli-help.test.mjs +4 -0
- package/test/integration/cms-site-tenancy-contract.test.mjs +256 -0
- package/test/integration/core-client.integration.test.mjs +55 -0
- package/test/integration/error-runtime-rpc.test.mjs +71 -0
- package/test/integration/features-resolve.test.mjs +128 -0
- package/test/integration/install-script.test.mjs +107 -0
- package/test/integration/inventory-core.test.mjs +53 -0
- package/test/integration/plugins-cloudflare.integration.test.mjs +28 -0
- package/test/integration/provider-env-cli.test.mjs +1 -1
- package/test/integration/runtime-migrations.test.mjs +6 -1
- package/test/integration/runtime-status.integration.test.mjs +211 -0
- package/test/integration/scaffold-cloudflare.test.mjs +46 -0
- package/test/integration/storage-architecture.test.mjs +154 -0
- package/test/integration/store-discovery.test.mjs +44 -0
- package/test/integration/terminal-exec.integration.test.mjs +86 -0
- package/test/integration/tool-runtime.test.mjs +124 -0
- package/test/integration/tool-schema.test.mjs +59 -0
- package/test/knowledge-service.test.mjs +4 -0
- package/test/local-sessions.test.mjs +11 -2
- package/test/local-studio-deploy.test.mjs +1 -1
- package/test/model-catalog.test.mjs +28 -1
- package/test/models.test.mjs +159 -5
- package/test/openai-responses.test.mjs +60 -0
- package/test/provider-credentials.test.mjs +15 -5
- package/test/responses-runner.test.mjs +321 -6
- package/test/shell.test.mjs +149 -4
- package/test/smoke.mjs +2 -2
- package/test/tools-search.test.mjs +33 -0
- package/test/unit/website-assets-bindings.test.mjs +60 -0
- package/test/whoami-resume.test.mjs +82 -3
- package/examples/gorilla-shell/README.md +0 -15
- package/src/lib/gorilla-template.js +0 -54
- package/templates/gorilla-shell/App.tsx +0 -639
- package/templates/gorilla-shell/README.md +0 -34
- package/templates/gorilla-shell/index.html +0 -15
- package/templates/gorilla-shell/main.jsx +0 -9
- package/templates/gorilla-shell/package.json +0 -19
- package/templates/gorilla-shell/vite.config.js +0 -21
|
@@ -5,23 +5,83 @@ import { fork } from 'node:child_process';
|
|
|
5
5
|
import { DatabaseSync } from 'node:sqlite';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
7
|
import { fingerprint, validateConfig } from '../config.js';
|
|
8
|
+
import {
|
|
9
|
+
AgentSamError,
|
|
10
|
+
ERROR_CODE,
|
|
11
|
+
ERROR_REASON,
|
|
12
|
+
createErrorEnvelope,
|
|
13
|
+
normalizeError,
|
|
14
|
+
parseError,
|
|
15
|
+
} from '../../errors/index.js';
|
|
8
16
|
|
|
9
17
|
const defaultWorkerPath = fileURLToPath(new URL('./job-worker.js', import.meta.url));
|
|
10
18
|
const TERMINAL_STATUSES = new Set(['completed', 'failed']);
|
|
11
19
|
|
|
20
|
+
function serviceReason(code) {
|
|
21
|
+
switch (code) {
|
|
22
|
+
case ERROR_CODE.UNAUTHENTICATED: return ERROR_REASON.AUTH_INVALID;
|
|
23
|
+
case ERROR_CODE.PERMISSION_DENIED: return ERROR_REASON.PERMISSION_DENIED;
|
|
24
|
+
case ERROR_CODE.NOT_FOUND: return ERROR_REASON.TARGET_NOT_FOUND;
|
|
25
|
+
case ERROR_CODE.ABORTED: return ERROR_REASON.CONFLICT;
|
|
26
|
+
case ERROR_CODE.RESOURCE_EXHAUSTED: return ERROR_REASON.CAPACITY_EXHAUSTED;
|
|
27
|
+
case ERROR_CODE.UNAVAILABLE: return ERROR_REASON.TRANSPORT_UNREACHABLE;
|
|
28
|
+
case ERROR_CODE.DEADLINE_EXCEEDED: return ERROR_REASON.DEADLINE_EXCEEDED;
|
|
29
|
+
case ERROR_CODE.INVALID_ARGUMENT: return ERROR_REASON.INPUT_INVALID;
|
|
30
|
+
default: return ERROR_REASON.INTERNAL;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
12
34
|
export function serviceError(status, message, code) {
|
|
13
|
-
|
|
35
|
+
const canonical = code === 'CONFLICT' ? ERROR_CODE.ABORTED : (Object.values(ERROR_CODE).includes(code) ? code : ERROR_CODE.INTERNAL);
|
|
36
|
+
const envelope = createErrorEnvelope({
|
|
37
|
+
code: canonical,
|
|
38
|
+
reason: serviceReason(canonical),
|
|
39
|
+
message,
|
|
40
|
+
http_status: status,
|
|
41
|
+
retryable: [429, 503, 504].includes(Number(status)),
|
|
42
|
+
source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_engine' },
|
|
43
|
+
resolution_owner: canonical === ERROR_CODE.UNAVAILABLE ? 'agentsam' : undefined,
|
|
44
|
+
domain: 'knowledge',
|
|
45
|
+
stage: 'request',
|
|
46
|
+
});
|
|
47
|
+
return new AgentSamError(envelope);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function decodeFailure(row) {
|
|
51
|
+
if (row?.failure_json) {
|
|
52
|
+
try { return parseError(row.failure_json); }
|
|
53
|
+
catch {
|
|
54
|
+
return createErrorEnvelope({
|
|
55
|
+
reason: ERROR_REASON.INTERNAL_CONTRACT_VIOLATION,
|
|
56
|
+
message: 'Stored knowledge failure could not be decoded.',
|
|
57
|
+
source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_engine' },
|
|
58
|
+
domain: 'knowledge',
|
|
59
|
+
stage: 'persistence',
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!row?.error) return null;
|
|
64
|
+
return createErrorEnvelope({
|
|
65
|
+
reason: ERROR_REASON.EXECUTION_FAILED,
|
|
66
|
+
message: row.error,
|
|
67
|
+
source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'legacy_job_row' },
|
|
68
|
+
domain: 'knowledge',
|
|
69
|
+
stage: 'execute',
|
|
70
|
+
});
|
|
14
71
|
}
|
|
15
72
|
|
|
16
73
|
function decode(row) {
|
|
17
|
-
|
|
74
|
+
if (!row) return null;
|
|
75
|
+
const failure = decodeFailure(row);
|
|
76
|
+
return {
|
|
18
77
|
id: row.id,
|
|
19
78
|
status: row.status,
|
|
20
79
|
attempts: row.attempts,
|
|
21
80
|
created_at: row.created_at,
|
|
22
81
|
updated_at: row.updated_at,
|
|
23
82
|
result: row.result ? JSON.parse(row.result) : null,
|
|
24
|
-
|
|
83
|
+
failure,
|
|
84
|
+
error: failure?.message || row.error || null,
|
|
25
85
|
};
|
|
26
86
|
}
|
|
27
87
|
|
|
@@ -100,10 +160,22 @@ export function createKnowledgeJobEngine({
|
|
|
100
160
|
db.exec(`PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000;
|
|
101
161
|
CREATE TABLE IF NOT EXISTS jobs (id TEXT PRIMARY KEY, idem TEXT UNIQUE, digest TEXT NOT NULL,
|
|
102
162
|
payload TEXT NOT NULL, status TEXT NOT NULL, attempts INTEGER NOT NULL DEFAULT 0,
|
|
103
|
-
created_at TEXT NOT NULL, updated_at TEXT NOT NULL, result TEXT, error TEXT);
|
|
163
|
+
created_at TEXT NOT NULL, updated_at TEXT NOT NULL, result TEXT, error TEXT, failure_json TEXT);
|
|
104
164
|
CREATE INDEX IF NOT EXISTS jobs_pending ON jobs(status, created_at);`);
|
|
165
|
+
const columns = new Set(db.prepare('PRAGMA table_info(jobs)').all().map(row => row.name));
|
|
166
|
+
if (!columns.has('failure_json')) db.exec('ALTER TABLE jobs ADD COLUMN failure_json TEXT');
|
|
105
167
|
fs.chmodSync(jobsFile, 0o600);
|
|
106
|
-
|
|
168
|
+
const interruptedFailure = createErrorEnvelope({
|
|
169
|
+
reason: ERROR_REASON.EXECUTION_FAILED,
|
|
170
|
+
message: 'Interrupted three times; submit a new job after investigation.',
|
|
171
|
+
source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_engine' },
|
|
172
|
+
domain: 'knowledge',
|
|
173
|
+
stage: 'recovery',
|
|
174
|
+
});
|
|
175
|
+
db.prepare("UPDATE jobs SET status=CASE WHEN attempts>=3 THEN 'failed' ELSE 'queued' END, error=CASE WHEN attempts>=3 THEN ? ELSE NULL END, failure_json=CASE WHEN attempts>=3 THEN ? ELSE NULL END WHERE status='running'").run(
|
|
176
|
+
interruptedFailure.message,
|
|
177
|
+
JSON.stringify(interruptedFailure),
|
|
178
|
+
);
|
|
107
179
|
|
|
108
180
|
let child = null;
|
|
109
181
|
let closing = false;
|
|
@@ -120,11 +192,17 @@ export function createKnowledgeJobEngine({
|
|
|
120
192
|
}
|
|
121
193
|
if (TERMINAL_STATUSES.has(job.status)) watchers.delete(job.id);
|
|
122
194
|
};
|
|
123
|
-
const updateStatus = (id, status, { result = null, error = null } = {}) => {
|
|
124
|
-
|
|
195
|
+
const updateStatus = (id, status, { result = null, failure = null, error = null } = {}) => {
|
|
196
|
+
const normalizedFailure = failure
|
|
197
|
+
? normalizeError(failure, { source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_engine' }, domain: 'knowledge', stage: 'execute' })
|
|
198
|
+
: error
|
|
199
|
+
? createErrorEnvelope({ reason: ERROR_REASON.EXECUTION_FAILED, message: error, source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_engine' }, domain: 'knowledge', stage: 'execute' })
|
|
200
|
+
: null;
|
|
201
|
+
db.prepare('UPDATE jobs SET status=?,result=?,error=?,failure_json=?,updated_at=? WHERE id=?').run(
|
|
125
202
|
status,
|
|
126
203
|
result === null ? null : JSON.stringify(result),
|
|
127
|
-
|
|
204
|
+
normalizedFailure?.message || null,
|
|
205
|
+
normalizedFailure ? JSON.stringify(normalizedFailure) : null,
|
|
128
206
|
new Date().toISOString(),
|
|
129
207
|
id,
|
|
130
208
|
);
|
|
@@ -145,15 +223,49 @@ export function createKnowledgeJobEngine({
|
|
|
145
223
|
child = fork(workerPath, [], { execArgv: [], stdio: ['ignore', 'ignore', 'ignore', 'ipc'], env: { ...process.env, GIT_OPTIONAL_LOCKS: '0' } });
|
|
146
224
|
const timer = setTimeout(() => { timedOut = true; child?.kill('SIGKILL'); }, jobTimeoutMs);
|
|
147
225
|
child.once('message', value => { response = value; });
|
|
148
|
-
child.once('error', () => {
|
|
226
|
+
child.once('error', (cause) => {
|
|
227
|
+
response = {
|
|
228
|
+
ok: false,
|
|
229
|
+
failure: createErrorEnvelope({
|
|
230
|
+
reason: ERROR_REASON.INTERNAL_DEPENDENCY_FAILED,
|
|
231
|
+
message: 'Could not start indexing process.',
|
|
232
|
+
source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_worker' },
|
|
233
|
+
domain: 'knowledge',
|
|
234
|
+
stage: 'spawn',
|
|
235
|
+
native: { code: cause?.code || null, exception_type: cause?.name || null, stack: cause?.stack || null },
|
|
236
|
+
}),
|
|
237
|
+
};
|
|
238
|
+
});
|
|
149
239
|
child.once('close', () => {
|
|
150
240
|
clearTimeout(timer);
|
|
151
241
|
child = null;
|
|
152
242
|
if (!closing) {
|
|
153
243
|
const ok = response?.ok && !timedOut;
|
|
244
|
+
let failure = null;
|
|
245
|
+
if (!ok) {
|
|
246
|
+
if (timedOut) {
|
|
247
|
+
failure = createErrorEnvelope({
|
|
248
|
+
reason: ERROR_REASON.EXECUTION_TIMEOUT,
|
|
249
|
+
message: 'Knowledge job exceeded its time limit; narrow the scope and retry.',
|
|
250
|
+
source: { kind: 'runtime', name: 'agentsam-knowledge-worker' },
|
|
251
|
+
domain: 'knowledge',
|
|
252
|
+
stage: 'execute',
|
|
253
|
+
});
|
|
254
|
+
} else if (response?.failure) {
|
|
255
|
+
failure = normalizeError(response.failure, { source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_worker' }, domain: 'knowledge', stage: 'execute' });
|
|
256
|
+
} else {
|
|
257
|
+
failure = createErrorEnvelope({
|
|
258
|
+
reason: ERROR_REASON.EXECUTION_FAILED,
|
|
259
|
+
message: response?.error || 'Indexing process exited unexpectedly.',
|
|
260
|
+
source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_worker' },
|
|
261
|
+
domain: 'knowledge',
|
|
262
|
+
stage: 'execute',
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
154
266
|
updateStatus(row.id, ok ? 'completed' : 'failed', {
|
|
155
267
|
result: ok ? response.result : null,
|
|
156
|
-
|
|
268
|
+
failure,
|
|
157
269
|
});
|
|
158
270
|
}
|
|
159
271
|
pumping = false;
|
|
@@ -162,7 +274,17 @@ export function createKnowledgeJobEngine({
|
|
|
162
274
|
const payload = JSON.parse(row.payload);
|
|
163
275
|
const registered = registry[payload.request.repository];
|
|
164
276
|
if (!registered || registered.config.repository_id !== payload.config.repository_id || fingerprint(registered.config.scope) !== payload.registered_scope || (!allowEmbeddings && ((payload.request.embed && payload.request.operation !== 'plan') || payload.request.semantic))) {
|
|
165
|
-
response = {
|
|
277
|
+
response = {
|
|
278
|
+
ok: false,
|
|
279
|
+
failure: createErrorEnvelope({
|
|
280
|
+
reason: ERROR_REASON.REPOSITORY_CHANGED,
|
|
281
|
+
message: 'Repository registration changed; resubmit this job.',
|
|
282
|
+
source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'repository_registry' },
|
|
283
|
+
domain: 'repository',
|
|
284
|
+
stage: 'execute',
|
|
285
|
+
resource: { type: 'repository', id: payload.config.repository_id || null },
|
|
286
|
+
}),
|
|
287
|
+
};
|
|
166
288
|
child.kill();
|
|
167
289
|
return;
|
|
168
290
|
}
|
|
@@ -3,12 +3,27 @@ import { openSqliteStore } from '../stores/sqlite.js';
|
|
|
3
3
|
import { createGeminiEmbedder } from '../providers/gemini.js';
|
|
4
4
|
import { inventory } from '../source.js';
|
|
5
5
|
import { scopeKey } from '../config.js';
|
|
6
|
+
import {
|
|
7
|
+
AgentSamError,
|
|
8
|
+
ERROR_REASON,
|
|
9
|
+
createErrorEnvelope,
|
|
10
|
+
normalizeError,
|
|
11
|
+
} from '../../errors/index.js';
|
|
6
12
|
|
|
7
13
|
// Parsing and vector ranking run in a child process, keeping HTTP acceptance responsive.
|
|
8
14
|
process.once('message', async ({ root, config, filename, request, maxFiles }) => {
|
|
9
15
|
let store;
|
|
10
16
|
try {
|
|
11
|
-
if (request.operation !== 'search' && inventory(root, config.scope).length > maxFiles) throw new
|
|
17
|
+
if (request.operation !== 'search' && inventory(root, config.scope).length > maxFiles) throw new AgentSamError(createErrorEnvelope({
|
|
18
|
+
reason: ERROR_REASON.INPUT_OUT_OF_RANGE,
|
|
19
|
+
message: `Scope exceeds ${maxFiles} files; choose a smaller include set.`,
|
|
20
|
+
source: { kind: 'user', name: 'knowledge_request' },
|
|
21
|
+
resolution_owner: 'user',
|
|
22
|
+
domain: 'knowledge',
|
|
23
|
+
stage: 'inventory',
|
|
24
|
+
remediation: { action: 'reduce_scope', message: 'Narrow the repository include scope and retry.' },
|
|
25
|
+
resource: { type: 'repository', id: config.repository_id || null },
|
|
26
|
+
}));
|
|
12
27
|
store = await openSqliteStore(filename);
|
|
13
28
|
const embedder = request.operation !== 'plan' && (request.embed || request.semantic) ? createGeminiEmbedder({ apiKey: process.env.GEMINI_API_KEY }) : undefined;
|
|
14
29
|
let result;
|
|
@@ -18,7 +33,15 @@ process.once('message', async ({ root, config, filename, request, maxFiles }) =>
|
|
|
18
33
|
const generation = request.generation_id ? await store.getGeneration(scopeKey(config), request.generation_id) : await store.active(scopeKey(config));
|
|
19
34
|
const under = (file, selection) => selection === '.' || file === selection || file.startsWith(selection + '/');
|
|
20
35
|
if (generation?.files.some(file => !config.scope.include.some(p => under(file.path, p)) || config.scope.exclude.some(p => under(file.path, p)))) {
|
|
21
|
-
throw new
|
|
36
|
+
throw new AgentSamError(createErrorEnvelope({
|
|
37
|
+
reason: ERROR_REASON.PRECONDITION_FAILED,
|
|
38
|
+
message: 'Generation exceeds the requested scope; select a matching scope or reindex.',
|
|
39
|
+
source: { kind: 'user', name: 'knowledge_request' },
|
|
40
|
+
domain: 'knowledge',
|
|
41
|
+
stage: 'search',
|
|
42
|
+
remediation: { action: 'change_configuration', message: 'Select a matching indexed scope or reindex the requested scope.' },
|
|
43
|
+
resource: { type: 'repository', id: config.repository_id || null },
|
|
44
|
+
}));
|
|
22
45
|
}
|
|
23
46
|
result = await retrieve({ store, config, text: request.query, semantic: request.semantic, embedder,
|
|
24
47
|
topK: request.top_k, tokenBudget: request.token_budget, generationId: request.generation_id });
|
|
@@ -27,8 +50,14 @@ process.once('message', async ({ root, config, filename, request, maxFiles }) =>
|
|
|
27
50
|
process.send({ ok: true, result }, () => process.exit(0));
|
|
28
51
|
} catch (error) {
|
|
29
52
|
await store?.close();
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
53
|
+
const failure = normalizeError(error, {
|
|
54
|
+
source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_worker' },
|
|
55
|
+
domain: 'knowledge',
|
|
56
|
+
stage: request.embed || request.semantic ? 'embedding' : request.operation || 'execute',
|
|
57
|
+
message: request.embed || request.semantic
|
|
58
|
+
? 'Embedding job failed; inspect the canonical failure for provider/configuration details.'
|
|
59
|
+
: undefined,
|
|
60
|
+
});
|
|
61
|
+
process.send({ ok: false, failure }, () => process.exit(1));
|
|
33
62
|
}
|
|
34
63
|
});
|
|
@@ -4,6 +4,7 @@ import path from 'node:path';
|
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { createBearerTokenVerifier } from './auth.js';
|
|
6
6
|
import { createKnowledgeJobEngine, serviceError } from './job-engine.js';
|
|
7
|
+
import { normalizeError, toHttpError } from '../../errors/index.js';
|
|
7
8
|
|
|
8
9
|
async function readBody(req) {
|
|
9
10
|
const chunks = [];
|
|
@@ -44,7 +45,15 @@ export async function startKnowledgeHttpServer({ engine, token, verifyToken, por
|
|
|
44
45
|
const { job, created } = engine.submitJob(await readBody(req), { idempotencyKey: req.headers['idempotency-key'] });
|
|
45
46
|
return send(created ? 202 : 200, job);
|
|
46
47
|
} catch (error) {
|
|
47
|
-
if (!res.writableEnded)
|
|
48
|
+
if (!res.writableEnded) {
|
|
49
|
+
const envelope = normalizeError(error, {
|
|
50
|
+
source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'http_server' },
|
|
51
|
+
domain: 'knowledge',
|
|
52
|
+
stage: 'request',
|
|
53
|
+
});
|
|
54
|
+
const httpError = toHttpError(envelope);
|
|
55
|
+
send(httpError.status, httpError.body);
|
|
56
|
+
}
|
|
48
57
|
}
|
|
49
58
|
});
|
|
50
59
|
server.requestTimeout = 15000;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { CONFIG_PATH, readConfig, validateConfig, defaultConfig } from './config.js';
|
|
4
|
+
import { findCliProjectRoot } from '../lib/cli-preferences.js';
|
|
5
|
+
import { runtimeDatabasePath } from '../local/runtime-store.js';
|
|
6
|
+
import { getRepositoryId, portableRepositoryIdFromGit, tryReadProjectConfig } from '../lib/project-config.js';
|
|
7
|
+
|
|
8
|
+
// Configuration evidence only. No connection probes, credential reads, or schema writes.
|
|
9
|
+
export async function discoverProjectStores(cwd, env = process.env) {
|
|
10
|
+
const root = findCliProjectRoot(cwd);
|
|
11
|
+
const config = fs.existsSync(path.join(root, CONFIG_PATH)) ? readConfig(root) : null;
|
|
12
|
+
const candidates = [
|
|
13
|
+
{ id: 'runtime:sqlite', driver: 'sqlite', role: 'runtime', path: runtimeDatabasePath(root), selected: true },
|
|
14
|
+
{ id: 'knowledge:sqlite', driver: 'sqlite', role: 'knowledge', path: path.join(root, '.agentsam/knowledge/index.sqlite'), selected: !config || config.storage.driver === 'sqlite', selectable: true },
|
|
15
|
+
];
|
|
16
|
+
const envNames = new Set(['AGENTSAM_DATABASE_URL', 'DATABASE_URL', 'POSTGRES_URL', config?.storage?.connection_env].filter(Boolean));
|
|
17
|
+
for (const name of envNames) {
|
|
18
|
+
if (!Object.hasOwn(env, name) && name !== config?.storage?.connection_env) continue;
|
|
19
|
+
candidates.push({ id: `knowledge:postgres:${name}`, driver: 'postgres', role: 'knowledge', connection_env: name, configured: Boolean(env[name]), selected: config?.storage?.driver === 'postgres' && config.storage.connection_env === name, selectable: true });
|
|
20
|
+
}
|
|
21
|
+
const warnings = [];
|
|
22
|
+
let visited = 0;
|
|
23
|
+
const skip = new Set(['node_modules', '.git', '.agentsam', '.output', 'dist', 'build', 'vendor', '.wrangler']);
|
|
24
|
+
const configs = [];
|
|
25
|
+
function scan(dir, depth) {
|
|
26
|
+
if (depth > 5 || visited >= 4000) return;
|
|
27
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
28
|
+
if (++visited >= 4000) break;
|
|
29
|
+
if (entry.isSymbolicLink() || skip.has(entry.name)) continue;
|
|
30
|
+
const file = path.join(dir, entry.name);
|
|
31
|
+
if (entry.isDirectory()) scan(file, depth + 1);
|
|
32
|
+
else if (['wrangler.json', 'wrangler.jsonc'].includes(entry.name)) configs.push(file);
|
|
33
|
+
else if (entry.name === 'wrangler.toml') warnings.push(`${path.relative(root, file)}: TOML discovery is not implemented; inspect this configuration explicitly.`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
scan(root, 0);
|
|
37
|
+
if (visited >= 4000) warnings.push('Discovery reached its 4000-entry bound; inspect additional config paths explicitly.');
|
|
38
|
+
if (configs.length) {
|
|
39
|
+
const { parseConfigFileTextToJson } = await import('typescript');
|
|
40
|
+
for (const file of configs) {
|
|
41
|
+
const source = path.relative(root, file);
|
|
42
|
+
if (fs.statSync(file).size > 1024 * 1024) { warnings.push(`${source}: configuration too large`); continue; }
|
|
43
|
+
const parsed = parseConfigFileTextToJson(file, fs.readFileSync(file, 'utf8'));
|
|
44
|
+
if (parsed.error) { warnings.push(`${source}: invalid JSONC`); continue; }
|
|
45
|
+
const add = (cfg, environment = null) => {
|
|
46
|
+
for (const [key, driver, label] of [['d1_databases', 'd1', 'database_name'], ['hyperdrive', 'postgres-hyperdrive', 'id'], ['r2_buckets', 'r2', 'bucket_name']]) {
|
|
47
|
+
for (const binding of Array.isArray(cfg?.[key]) ? cfg[key] : []) {
|
|
48
|
+
candidates.push({ id: `${source}:${environment || 'default'}:${binding.binding}`, driver, role: 'application', binding: binding.binding, name: binding[label], source, environment, selectable: false, status: 'declared; connectivity not verified' });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
add(parsed.config);
|
|
53
|
+
for (const [environment, cfg] of Object.entries(parsed.config?.env || {})) add(cfg, environment);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { root, candidates, warnings, knowledge_config: CONFIG_PATH };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function selectKnowledgeStore(cwd, driver, connectionEnv) {
|
|
60
|
+
const root = findCliProjectRoot(cwd);
|
|
61
|
+
if (!['sqlite', 'postgres'].includes(driver)) throw new Error('knowledge_store_adapter_unavailable: choose sqlite or postgres; D1 application bindings retain their existing authority');
|
|
62
|
+
const filename = path.join(root, CONFIG_PATH);
|
|
63
|
+
let config;
|
|
64
|
+
if (fs.existsSync(filename)) config = readConfig(root);
|
|
65
|
+
else {
|
|
66
|
+
const repositoryId = getRepositoryId(tryReadProjectConfig(root)) || portableRepositoryIdFromGit(root);
|
|
67
|
+
if (!repositoryId) throw new Error('repository_identity_required: run agentsam init . --yes first');
|
|
68
|
+
config = defaultConfig({ repositoryId });
|
|
69
|
+
}
|
|
70
|
+
config.storage = driver === 'sqlite' ? { driver } : { driver, connection_env: connectionEnv || 'AGENTSAM_DATABASE_URL' };
|
|
71
|
+
config = validateConfig(config);
|
|
72
|
+
fs.mkdirSync(path.dirname(filename), { recursive: true, mode: 0o700 });
|
|
73
|
+
const temp = `${filename}.${process.pid}.tmp`;
|
|
74
|
+
fs.writeFileSync(temp, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
|
|
75
|
+
fs.renameSync(temp, filename);
|
|
76
|
+
return { storage: config.storage, config: CONFIG_PATH, next: driver === 'sqlite' ? 'agentsam index run' : 'agentsam index setup-store', note: 'Selection saved. Existing data remains in its original store; no migration or connection probe ran.' };
|
|
77
|
+
}
|
|
@@ -147,8 +147,14 @@ export function resolveBrowserSessionCredential(options = {}) {
|
|
|
147
147
|
*/
|
|
148
148
|
export function resolveAccountAuth(options = {}) {
|
|
149
149
|
const apiKey = resolveAccountApiKey(options);
|
|
150
|
-
if (apiKey.value
|
|
151
|
-
|
|
150
|
+
if (apiKey.value) return apiKey;
|
|
151
|
+
if (clean(options.explicit) && apiKey.error) return apiKey;
|
|
152
|
+
const browser = resolveBrowserSessionCredential(options);
|
|
153
|
+
if (browser.value) {
|
|
154
|
+
return apiKey.error ? { ...browser, fallback_error: apiKey.error } : browser;
|
|
155
|
+
}
|
|
156
|
+
if (browser.error) return browser;
|
|
157
|
+
return apiKey.error ? apiKey : browser;
|
|
152
158
|
}
|
|
153
159
|
|
|
154
160
|
export function describeAccountSession(options = {}) {
|
|
@@ -6,6 +6,9 @@ import { findProjectRules } from './project-rules.js';
|
|
|
6
6
|
export const AGENT_RUNTIME_FILENAME = 'AGENTSAM.md';
|
|
7
7
|
export const AGENT_INSTRUCTION_PRECEDENCE = Object.freeze(['AGENTSAM.md', '.agentsamrules']);
|
|
8
8
|
|
|
9
|
+
/** Provider/editor adapters that must redirect to AGENTSAM.md — never compiled as policy. */
|
|
10
|
+
export const AGENT_INSTRUCTION_COMPAT_SHIMS = Object.freeze(['AGENTS.md', 'CLAUDE.md']);
|
|
11
|
+
|
|
9
12
|
function sha256(value) {
|
|
10
13
|
return `sha256:${createHash('sha256').update(value).digest('hex')}`;
|
|
11
14
|
}
|
package/src/lib/auth.js
CHANGED
|
@@ -137,12 +137,15 @@ export async function refreshAccountSession(options = {}) {
|
|
|
137
137
|
*/
|
|
138
138
|
export async function resolveAccountAuthority(options = {}) {
|
|
139
139
|
const apiKey = resolveAccountApiKey(options);
|
|
140
|
-
if (apiKey.value
|
|
140
|
+
if (apiKey.value) return apiKey;
|
|
141
|
+
if (clean(options.explicit) && apiKey.error) return apiKey;
|
|
141
142
|
|
|
142
143
|
let session = readAccountSession(options);
|
|
143
|
-
if (!session?.access_token)
|
|
144
|
+
if (!session?.access_token) {
|
|
145
|
+
return apiKey.error ? apiKey : { value: '', source: null, kind: null, session: null };
|
|
146
|
+
}
|
|
144
147
|
|
|
145
|
-
if (isBrowserSessionExpired(session, options)) {
|
|
148
|
+
if (options.forceRefresh === true || isBrowserSessionExpired(session, options)) {
|
|
146
149
|
if (!session.refresh_token) {
|
|
147
150
|
return {
|
|
148
151
|
value: '',
|
|
@@ -171,6 +174,7 @@ export async function resolveAccountAuthority(options = {}) {
|
|
|
171
174
|
source: 'agentsam_browser_oauth',
|
|
172
175
|
kind: 'browser_oauth',
|
|
173
176
|
session,
|
|
177
|
+
fallback_error: apiKey.error || null,
|
|
174
178
|
};
|
|
175
179
|
}
|
|
176
180
|
|
package/src/lib/cad/blender.js
CHANGED
|
@@ -4,9 +4,11 @@ import path from 'node:path';
|
|
|
4
4
|
import { createHash } from 'node:crypto';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import { runProcess } from '../../security/process.js';
|
|
7
|
+
import { probeDockerServiceHealth, executeBlenderDocker } from './docker-executor.js';
|
|
7
8
|
|
|
8
9
|
const sdkRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../..');
|
|
9
|
-
|
|
10
|
+
const packagedAdapter = path.join(path.dirname(fileURLToPath(import.meta.url)), 'cad/blender/adapter.py');
|
|
11
|
+
export const BLENDER_ADAPTER_PATH = fs.existsSync(packagedAdapter) ? packagedAdapter : path.join(sdkRoot, 'services/cad/blender/adapter.py');
|
|
10
12
|
export const BLENDER_RESULT_PREFIX = 'AGENTSAM_RESULT=';
|
|
11
13
|
export const BLENDER_EXPORT_FORMATS = Object.freeze(['glb', 'stl', 'obj']);
|
|
12
14
|
export const BLENDER_RECIPE_OPS = Object.freeze([
|
|
@@ -172,9 +174,46 @@ async function invokeBlender({
|
|
|
172
174
|
runProcessImpl = runProcess,
|
|
173
175
|
}) {
|
|
174
176
|
const binary = discoverBlender({ blenderBin });
|
|
175
|
-
if (!binary) throw new Error('Blender is not installed or could not be discovered; use --blender-bin or AGENTSAM_BLENDER_BIN');
|
|
176
|
-
if (!fs.existsSync(BLENDER_ADAPTER_PATH)) throw new Error(`Bundled Blender adapter is missing: ${BLENDER_ADAPTER_PATH}`);
|
|
177
177
|
const timeout = boundedInteger(timeoutSeconds, 120, 1, 600, 'timeout');
|
|
178
|
+
|
|
179
|
+
if (!binary || !fs.existsSync(BLENDER_ADAPTER_PATH)) {
|
|
180
|
+
try {
|
|
181
|
+
const dockerHealth = await probeDockerServiceHealth();
|
|
182
|
+
if (dockerHealth.available && dockerHealth.tools?.blender?.installed) {
|
|
183
|
+
// Forward the full operation request (recipe/scene/camera/width/height/
|
|
184
|
+
// format/objects/collection/apply_modifiers as applicable) — the
|
|
185
|
+
// docker service has no access to `request.output`'s local path, so
|
|
186
|
+
// strip it and let the container pick its own temp output path.
|
|
187
|
+
const { output: _localOutput, ...requestRest } = request || {};
|
|
188
|
+
const inputBase64 = input && fs.existsSync(input) ? fs.readFileSync(input).toString('base64') : null;
|
|
189
|
+
|
|
190
|
+
const dockerRes = await executeBlenderDocker({
|
|
191
|
+
operation,
|
|
192
|
+
request: requestRest,
|
|
193
|
+
inputBase64,
|
|
194
|
+
format: requestRest.format
|
|
195
|
+
|| (operation === 'build' ? 'blend' : operation === 'render_preview' ? 'png' : 'glb'),
|
|
196
|
+
filename: request.output ? path.basename(request.output) : undefined,
|
|
197
|
+
timeoutMs: timeout * 1000,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
if (request.output && dockerRes.artifactBase64) {
|
|
201
|
+
const outputPath = path.resolve(cwd, request.output);
|
|
202
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
203
|
+
fs.writeFileSync(outputPath, Buffer.from(dockerRes.artifactBase64, 'base64'));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
result: dockerRes.result || { ok: true, blender_version: dockerHealth.tools.blender.version },
|
|
208
|
+
binary: `docker://${dockerHealth.service || 'agentsam-cad'}/blender`,
|
|
209
|
+
duration_ms: dockerRes.durationMs,
|
|
210
|
+
execution_lane: 'docker_service',
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
} catch {}
|
|
214
|
+
|
|
215
|
+
throw new Error('Blender is not installed or could not be discovered; use --blender-bin, AGENTSAM_BLENDER_BIN, or launch AgentSam CAD Docker service');
|
|
216
|
+
}
|
|
178
217
|
const requestDir = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-blender-'));
|
|
179
218
|
const requestPath = path.join(requestDir, 'request.json');
|
|
180
219
|
fs.writeFileSync(requestPath, JSON.stringify({ schema_version: 1, ...request }, null, 2), { mode: 0o600 });
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {randomUUID} from 'node:crypto';
|
|
2
|
+
import {requireValidProject} from './project-contract.js';
|
|
3
|
+
import {projectHash} from './project-store.js';
|
|
4
|
+
// Reuses blueprint documents + immutable R2 scene snapshots. No new tables.
|
|
5
|
+
// scope is supplied by the authenticated host, never by tool arguments.
|
|
6
|
+
export class D1ProjectStore {
|
|
7
|
+
constructor({db,objects,bucket,scope}) {
|
|
8
|
+
if(!scope?.account_id||!scope?.workspace_id||!scope?.tenant_id||!bucket)throw new Error('authenticated_design_scope_required');
|
|
9
|
+
this.db=db;this.objects=objects;this.bucket=bucket;this.scope=scope;
|
|
10
|
+
}
|
|
11
|
+
async read(id,revision){
|
|
12
|
+
const s=this.scope;
|
|
13
|
+
const row=await this.db.prepare("SELECT * FROM designstudio_design_blueprints WHERE id=? AND tenant_id=? AND workspace_id=? AND json_extract(intent_json,'$.account_id')=?").bind(id,s.tenant_id,s.workspace_id,s.account_id).first();
|
|
14
|
+
if(!row)throw new Error('project_not_found');
|
|
15
|
+
const current=JSON.parse(row.generation_config_json||'{}').project_revision;
|
|
16
|
+
if(revision==null||revision===current){const p=JSON.parse(row.sketch_json);return {project:p,revision:current,content_hash:projectHash(p)};}
|
|
17
|
+
const snapshot=await this.db.prepare("SELECT r2_key FROM scene_snapshots WHERE project_id=? AND user_id=? AND workspace_id=? AND tenant_id=? AND version=? AND project_type='CAD_PROJECT'").bind(id,s.account_id,s.workspace_id,s.tenant_id,revision).first();
|
|
18
|
+
if(!snapshot)throw new Error('revision_not_found');
|
|
19
|
+
const object=await this.objects.get(snapshot.r2_key);if(!object)throw new Error('revision_object_missing');
|
|
20
|
+
const saved=JSON.parse(await object.text());requireValidProject(saved.project);if(saved.content_hash!==projectHash(saved.project))throw new Error('revision_digest_mismatch');return saved;
|
|
21
|
+
}
|
|
22
|
+
async save(project,expectedRevision,message='Saved project'){
|
|
23
|
+
requireValidProject(project);
|
|
24
|
+
if(!Number.isSafeInteger(expectedRevision)||expectedRevision<0)throw new Error('expected_revision_required');
|
|
25
|
+
const s=this.scope,revision=expectedRevision+1,now=Math.floor(Date.now()/1000),id='scene_'+randomUUID().replaceAll('-','');
|
|
26
|
+
const p={...structuredClone(project),version:revision,updatedAt:Date.now()};
|
|
27
|
+
const saved={project:p,revision,content_hash:projectHash(p),message,created_at:now};
|
|
28
|
+
const key='design-projects/'+encodeURIComponent(s.account_id)+'/'+encodeURIComponent(p.id)+'/'+revision+'/'+saved.content_hash+'.json';
|
|
29
|
+
await this.objects.put(key,JSON.stringify(saved),{httpMetadata:{contentType:'application/json'}});
|
|
30
|
+
const statements=[];
|
|
31
|
+
if(expectedRevision===0){
|
|
32
|
+
statements.push(this.db.prepare("INSERT INTO designstudio_design_blueprints (id,tenant_id,workspace_id,title,intent_json,sketch_json,generation_config_json,status) VALUES (?,?,?,?,?,?,?,'structured')").bind(p.id,s.tenant_id,s.workspace_id,p.name,JSON.stringify({account_id:s.account_id,contract:'cad.project.v1'}),JSON.stringify(p),JSON.stringify({project_revision:revision,content_hash:saved.content_hash})));
|
|
33
|
+
}else{
|
|
34
|
+
statements.push(this.db.prepare("UPDATE designstudio_design_blueprints SET title=?,sketch_json=?,generation_config_json=json_set(generation_config_json,'$.project_revision',?,'$.content_hash',?),updated_at=datetime('now') WHERE id=? AND tenant_id=? AND workspace_id=? AND json_extract(intent_json,'$.account_id')=? AND json_extract(generation_config_json,'$.project_revision')=?").bind(p.name,JSON.stringify(p),revision,saved.content_hash,p.id,s.tenant_id,s.workspace_id,s.account_id,expectedRevision));
|
|
35
|
+
}
|
|
36
|
+
// D1 batch is transactional; changes() guards the snapshot against a failed CAS.
|
|
37
|
+
statements.push(this.db.prepare("INSERT INTO scene_snapshots (id,workspace_id,user_id,tenant_id,name,project_type,entity_count,r2_key,r2_bucket,project_id,version,description,created_at,updated_at) SELECT ?,?,?,?,?,'CAD_PROJECT',?,?,?,?,?,?,?,? WHERE changes()=1").bind(id,s.workspace_id,s.account_id,s.tenant_id,p.name,p.walls.length+p.rooms.length+p.doors.length+p.windows.length,key,this.bucket,p.id,revision,message,now,now));
|
|
38
|
+
let results;try{results=await this.db.batch(statements);}catch(e){throw new Error('project_save_failed:'+e.message);}
|
|
39
|
+
if(results[0]?.meta?.changes!==1)throw new Error('revision_conflict');
|
|
40
|
+
return saved;
|
|
41
|
+
}
|
|
42
|
+
async restore(id,revision,expectedRevision){const row=await this.read(id,revision);return this.save(row.project,expectedRevision,'Restored revision '+revision);}
|
|
43
|
+
}
|