@inneranimalmedia/agentsam-sdk 2.6.1 → 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/AUTH_IDENTITY_CONTRACT.md +25 -27
- 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/SDK_WORKER.md +4 -3
- 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 +4 -3
- 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/auth-config.js +23 -40
- 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/auth-config.test.mjs +14 -23
- 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 +129 -31
- 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/account-auth.js +1 -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/deploy.js +2 -2
- 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 +389 -0
- package/src/commands/resume.js +9 -5
- package/src/commands/runtime-status.js +154 -0
- package/src/commands/shell.js +469 -54
- package/src/commands/status.js +82 -7
- package/src/commands/tunnel.js +228 -195
- package/src/commands/whoami.js +115 -22
- 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 -50
- 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 +100 -25
- package/src/lib/agent-instructions.js +3 -0
- package/src/lib/auth.js +318 -51
- 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 +97 -33
- package/src/lib/deploy/local-studio.js +6 -5
- package/src/lib/detect-context.js +14 -16
- 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 +233 -55
- 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 +10 -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 +59 -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 +14 -5
- package/src/ui/wireframes.js +166 -0
- package/test/account-session.test.mjs +76 -11
- package/test/apps-scaffold-contract.test.mjs +58 -0
- 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/sdk-worker-contract.test.mjs +5 -1
- package/test/shell.test.mjs +149 -4
- package/test/smoke.mjs +4 -3
- package/test/tools-search.test.mjs +33 -0
- package/test/unit/website-assets-bindings.test.mjs +60 -0
- package/test/whoami-resume.test.mjs +87 -7
- package/examples/gorilla-shell/README.md +0 -15
- package/src/lib/gorilla-template.js +0 -54
- package/src/lib/prompt-byok.js +0 -57
- package/src/lib/save-sdk-token.js +0 -19
- 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
|
@@ -13,6 +13,10 @@ function packageJson(...parts) {
|
|
|
13
13
|
return JSON.parse(fs.readFileSync(at(...parts, 'package.json'), 'utf8'));
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
function read(...parts) {
|
|
17
|
+
return fs.readFileSync(at(...parts), 'utf8');
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
test('product apps are self-contained npm workspace roots with one lockfile', () => {
|
|
17
21
|
for (const app of productApps) {
|
|
18
22
|
const base = ['apps', app];
|
|
@@ -54,3 +58,57 @@ test('Local Studio retired donor-era duplicate deployment configs', () => {
|
|
|
54
58
|
assert.equal(exists('apps', 'local-studio', 'backend', file), false, `retire ${file}`);
|
|
55
59
|
}
|
|
56
60
|
});
|
|
61
|
+
|
|
62
|
+
test('CAD creator app package is curated for third-party installation', () => {
|
|
63
|
+
const pkg = packageJson('apps', 'cad-creator');
|
|
64
|
+
const manifest = JSON.parse(read('apps', 'cad-creator', 'agentsam.app.json'));
|
|
65
|
+
|
|
66
|
+
assert.equal(pkg.name, '@inneranimalmedia/agentsam-sdk-cad-creator');
|
|
67
|
+
assert.notEqual(pkg.private, true);
|
|
68
|
+
assert.equal(pkg.bin['agentsam-cad-creator'], 'bin/agentsam-cad-creator.mjs');
|
|
69
|
+
assert.equal(pkg.publishConfig.access, 'public');
|
|
70
|
+
assert.ok(pkg.files.includes('frontend/dist/'));
|
|
71
|
+
assert.ok(pkg.files.includes('backend/dist/'));
|
|
72
|
+
assert.ok(pkg.files.includes('backend/worker/'));
|
|
73
|
+
assert.equal(pkg.files.some((entry) => entry.startsWith('reference')), false);
|
|
74
|
+
assert.equal(pkg.files.some((entry) => entry.includes('.wrangler/state')), false);
|
|
75
|
+
|
|
76
|
+
assert.equal(manifest.schema, 'agentsam.app.v1');
|
|
77
|
+
assert.equal(manifest.id, 'cad-creator');
|
|
78
|
+
assert.equal(manifest.package, pkg.name);
|
|
79
|
+
assert.equal(manifest.runtime.local_preview, 'ready');
|
|
80
|
+
assert.equal(manifest.runtime.source_scaffold, 'ready');
|
|
81
|
+
assert.equal(manifest.runtime.cloudflare, 'scaffold');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('client-cms-editor app manifest points to authoritative package name', () => {
|
|
85
|
+
const pkg = packageJson('apps', 'client-cms-editor');
|
|
86
|
+
const manifest = JSON.parse(read('apps', 'client-cms-editor', 'agentsam.app.json'));
|
|
87
|
+
|
|
88
|
+
assert.equal(pkg.name, '@inneranimalmedia/client-cms-editor');
|
|
89
|
+
assert.equal(manifest.schema, 'agentsam.app.v1');
|
|
90
|
+
assert.equal(manifest.id, 'client-cms-editor');
|
|
91
|
+
assert.equal(manifest.package, pkg.name);
|
|
92
|
+
assert.equal(manifest.runtime.local_preview, 'ready');
|
|
93
|
+
assert.equal(manifest.runtime.source_scaffold, 'ready');
|
|
94
|
+
assert.equal(manifest.runtime.cloudflare, 'ready');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('CAD creator keeps the robotics runtime lazy and the perception key server-side', () => {
|
|
98
|
+
const app = exists('apps', 'cad-creator', 'frontend', 'src', 'app', 'CadCreatorApp.tsx')
|
|
99
|
+
? read('apps', 'cad-creator', 'frontend', 'src', 'app', 'CadCreatorApp.tsx')
|
|
100
|
+
: read('apps', 'cad-creator', 'frontend', 'src', 'App.tsx');
|
|
101
|
+
const lazy = read('apps', 'cad-creator', 'frontend', 'src', 'workspaces', 'robotics', 'lazy.tsx');
|
|
102
|
+
const httpProvider = read('apps', 'cad-creator', 'frontend', 'src', 'lib', 'robotics', 'perception', 'http-provider.ts');
|
|
103
|
+
const perception = read('apps', 'cad-creator', 'backend', 'src', 'robotics', 'perception.ts');
|
|
104
|
+
const worker = read('apps', 'cad-creator', 'backend', 'worker', 'index.js');
|
|
105
|
+
|
|
106
|
+
assert.doesNotMatch(app, /from ['\"]\.\/workspaces\/robotics\/RoboticsWorkspace['\"]/);
|
|
107
|
+
assert.doesNotMatch(app, /MujocoSimulationProvider/);
|
|
108
|
+
assert.match(app, /LazyRoboticsWorkspace/);
|
|
109
|
+
assert.match(lazy, /import\(['\"]\.\/RoboticsWorkspace['\"]\)/);
|
|
110
|
+
assert.match(httpProvider, /\/api\/robotics\/perception\/detect/);
|
|
111
|
+
assert.doesNotMatch(httpProvider, /GEMINI_API_KEY|GOOGLE_API_KEY/);
|
|
112
|
+
assert.match(perception, /env\.GEMINI_API_KEY/);
|
|
113
|
+
assert.match(worker, /\/api\/robotics\/perception\/detect/);
|
|
114
|
+
});
|
|
@@ -109,7 +109,7 @@ test('product UX creates a preset project, adds a feature, and inspects before f
|
|
|
109
109
|
assert.equal(config.schema_version, 2);
|
|
110
110
|
assert.equal(config.project.name, 'demo');
|
|
111
111
|
assert.equal(config.product.preset, 'cms');
|
|
112
|
-
assert.deepEqual(config.product.features, ['cms', 'knowledge']);
|
|
112
|
+
assert.deepEqual(config.product.features, ['cms', 'knowledge', 'brand', 'theme']);
|
|
113
113
|
assert.ok(config.product.capabilities.includes('repository.snapshot'));
|
|
114
114
|
assert.match(config.repository.id, /^local:[0-9a-f-]{36}$/);
|
|
115
115
|
assert.equal(config.defaults.runtime, 'local');
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
finishLiveEvalRun,
|
|
9
|
+
getLiveEvalStatus,
|
|
10
|
+
startLiveEvalRun,
|
|
11
|
+
} from '../../src/eval/index.js';
|
|
12
|
+
import { recordToolReceipt } from '../../src/mcp/index.js';
|
|
13
|
+
import { runEval } from '../../src/commands/eval.js';
|
|
14
|
+
|
|
15
|
+
function tempHome() {
|
|
16
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-live-eval-test-'));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
test('live eval lifecycle: start, track receipts, get status, finish', async () => {
|
|
20
|
+
const home = tempHome();
|
|
21
|
+
|
|
22
|
+
// Initially inactive
|
|
23
|
+
const initialStatus = getLiveEvalStatus({ home });
|
|
24
|
+
assert.equal(initialStatus.active, false);
|
|
25
|
+
|
|
26
|
+
// Start live eval run
|
|
27
|
+
const run = startLiveEvalRun(
|
|
28
|
+
{
|
|
29
|
+
suite: 'sdk-real-work-20260919',
|
|
30
|
+
case: 'cad-shell-unification',
|
|
31
|
+
model: 'Muse Spark 1.3',
|
|
32
|
+
provider: 'cursor',
|
|
33
|
+
client: 'cursor',
|
|
34
|
+
reasoning: 'high',
|
|
35
|
+
},
|
|
36
|
+
{ home }
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
assert.ok(run.run_id.startsWith('evr_'));
|
|
40
|
+
assert.equal(run.suite_id, 'sdk-real-work-20260919');
|
|
41
|
+
assert.equal(run.case_id, 'cad-shell-unification');
|
|
42
|
+
assert.equal(run.model, 'Muse Spark 1.3');
|
|
43
|
+
|
|
44
|
+
// Verify starting again fails
|
|
45
|
+
assert.throws(() => startLiveEvalRun({}, { home }), /live_eval_run_already_active/);
|
|
46
|
+
|
|
47
|
+
// Record tool calls into the live session
|
|
48
|
+
recordToolReceipt({ tool_key: 'github_read', source_client: 'cursor', duration_ms: 50 }, { home });
|
|
49
|
+
recordToolReceipt({ tool_key: 'mcp:d1_query', source_client: 'cursor_mcp', duration_ms: 12 }, { home });
|
|
50
|
+
recordToolReceipt({ tool_key: 'terminal_exec', source_client: 'agentsam', duration_ms: 300 }, { home });
|
|
51
|
+
|
|
52
|
+
// Status check reflects active state and tool receipts
|
|
53
|
+
const activeStatus = getLiveEvalStatus({ home });
|
|
54
|
+
assert.equal(activeStatus.active, true);
|
|
55
|
+
assert.equal(activeStatus.receipts_summary.tool_call_count, 3);
|
|
56
|
+
assert.equal(activeStatus.receipts_summary.mcp_call_count, 1);
|
|
57
|
+
|
|
58
|
+
// Finish run
|
|
59
|
+
const result = await finishLiveEvalRun({ home, gate: 'PASS' });
|
|
60
|
+
assert.equal(result.evalRunRow.id, run.run_id);
|
|
61
|
+
assert.equal(result.evalRunRow.passed, 1);
|
|
62
|
+
assert.equal(result.evalRunRow.tool_calls_attempted, 3);
|
|
63
|
+
assert.equal(result.evalRunRow.tool_calls_succeeded, 3);
|
|
64
|
+
assert.equal(result.modelObservationRow.id, `obs_${run.run_id}`);
|
|
65
|
+
assert.equal(result.modelObservationRow.passed, 1);
|
|
66
|
+
|
|
67
|
+
// After finish, status is inactive again
|
|
68
|
+
const postStatus = getLiveEvalStatus({ home });
|
|
69
|
+
assert.equal(postStatus.active, false);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('agentsam eval live CLI commands work end-to-end', async () => {
|
|
73
|
+
const home = tempHome();
|
|
74
|
+
const logs = [];
|
|
75
|
+
const write = (str) => logs.push(str);
|
|
76
|
+
|
|
77
|
+
// CLI start
|
|
78
|
+
const startResult = await runEval(
|
|
79
|
+
['live', 'start', '--case', 'errors-v1-reconciliation', '--model', 'Muse Spark 1.3', '--json'],
|
|
80
|
+
{ home, write }
|
|
81
|
+
);
|
|
82
|
+
assert.ok(startResult.run_id.startsWith('evr_'));
|
|
83
|
+
|
|
84
|
+
// Record receipt
|
|
85
|
+
recordToolReceipt({ tool_key: 'mcp:eval_query', source_client: 'cursor_mcp', duration_ms: 40 }, { home });
|
|
86
|
+
|
|
87
|
+
// CLI status
|
|
88
|
+
const statusResult = await runEval(['live', 'status', '--json'], { home, write });
|
|
89
|
+
assert.equal(statusResult.active, true);
|
|
90
|
+
assert.equal(statusResult.receipts_summary.tool_call_count, 1);
|
|
91
|
+
|
|
92
|
+
// CLI finish
|
|
93
|
+
const finishResult = await runEval(['live', 'finish', '--gate', 'PASS', '--json'], { home, write });
|
|
94
|
+
assert.equal(finishResult.evalRunRow.passed, 1);
|
|
95
|
+
assert.equal(finishResult.summary.gate_status, 'PASS');
|
|
96
|
+
|
|
97
|
+
// Verify non-JSON output formats cleanly
|
|
98
|
+
const emptyStatus = await runEval(['live', 'status'], { home, write });
|
|
99
|
+
assert.equal(emptyStatus.active, false);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('finishLiveEvalRun archives run locally, generates SQL for both tables, and respects configurable tenant/database', async () => {
|
|
103
|
+
const home = tempHome();
|
|
104
|
+
const run = startLiveEvalRun(
|
|
105
|
+
{
|
|
106
|
+
case: 'cad-render-eval',
|
|
107
|
+
model: 'Muse Spark 1.3',
|
|
108
|
+
tenant: 'test-tenant',
|
|
109
|
+
workspace: 'cad-workspace',
|
|
110
|
+
user: 'test-user',
|
|
111
|
+
database: 'test-database',
|
|
112
|
+
},
|
|
113
|
+
{ home }
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
assert.equal(run.tenant_id, 'test-tenant');
|
|
117
|
+
assert.equal(run.workspace_id, 'cad-workspace');
|
|
118
|
+
assert.equal(run.user_id, 'test-user');
|
|
119
|
+
assert.equal(run.database, 'test-database');
|
|
120
|
+
|
|
121
|
+
const result = await finishLiveEvalRun({ home, gate: 'PASS' });
|
|
122
|
+
|
|
123
|
+
// 1. Dual record construction
|
|
124
|
+
assert.equal(result.evalRunRow.tenant_id, 'test-tenant');
|
|
125
|
+
assert.equal(result.modelObservationRow.tenant_id, 'test-tenant');
|
|
126
|
+
assert.equal(result.modelObservationRow.workspace_id, 'cad-workspace');
|
|
127
|
+
assert.equal(result.modelObservationRow.user_id, 'test-user');
|
|
128
|
+
assert.equal(result.modelObservationRow.status, 'completed');
|
|
129
|
+
assert.equal(result.modelObservationRow.passed, 1);
|
|
130
|
+
assert.equal(result.modelObservationRow.expected_markers_total, 1);
|
|
131
|
+
assert.equal(typeof result.modelObservationRow.output_chars, 'number');
|
|
132
|
+
|
|
133
|
+
// 2. Both tables present in generated D1 SQL
|
|
134
|
+
assert.ok(result.summary.d1_sql.includes('INSERT OR REPLACE INTO agentsam_eval_runs'));
|
|
135
|
+
assert.ok(result.summary.d1_sql.includes('INSERT OR REPLACE INTO agentsam_model_eval_observations'));
|
|
136
|
+
|
|
137
|
+
// 3. Local archive created
|
|
138
|
+
const archivedRunPath = path.join(home, '.agentsam', 'eval', 'runs', `${run.run_id}.json`);
|
|
139
|
+
assert.ok(fs.existsSync(archivedRunPath), 'Archived run file must exist locally');
|
|
140
|
+
const archived = JSON.parse(fs.readFileSync(archivedRunPath, 'utf8'));
|
|
141
|
+
assert.equal(archived.evalRunRow.id, run.run_id);
|
|
142
|
+
assert.equal(archived.modelObservationRow.id, `obs_${run.run_id}`);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test('finishLiveEvalRun preserves active run state and receipts if remote persistence fails without --force', async () => {
|
|
146
|
+
const home = tempHome();
|
|
147
|
+
const run = startLiveEvalRun({ case: 'resilience-test' }, { home });
|
|
148
|
+
|
|
149
|
+
recordToolReceipt({ tool_key: 'git_status', duration_ms: 20 }, { home });
|
|
150
|
+
|
|
151
|
+
// Call finish with remote=true pointing to an unreachable endpoint and wrangler fallback disabled
|
|
152
|
+
const result = await finishLiveEvalRun({
|
|
153
|
+
home,
|
|
154
|
+
remote: true,
|
|
155
|
+
evalEndpoint: 'http://127.0.0.1:1/nonexistent',
|
|
156
|
+
wranglerFallback: false,
|
|
157
|
+
timeoutMs: 100,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Verification: remote failure noted, evidence preserved, active run kept intact
|
|
161
|
+
assert.equal(result.summary.d1_executed, false);
|
|
162
|
+
assert.equal(result.summary.state_preserved, true);
|
|
163
|
+
assert.ok(result.summary.d1_error);
|
|
164
|
+
|
|
165
|
+
const activeStatus = getLiveEvalStatus({ home });
|
|
166
|
+
assert.equal(activeStatus.active, true, 'Active run state must be retained when remote persistence fails');
|
|
167
|
+
assert.equal(activeStatus.receipts_summary.tool_call_count, 1, 'Tool receipts must be preserved when remote persistence fails');
|
|
168
|
+
|
|
169
|
+
// Finish with force: true to finalize and clear active run
|
|
170
|
+
const forcedResult = await finishLiveEvalRun({
|
|
171
|
+
home,
|
|
172
|
+
remote: true,
|
|
173
|
+
evalEndpoint: 'http://127.0.0.1:1/nonexistent',
|
|
174
|
+
wranglerFallback: false,
|
|
175
|
+
timeoutMs: 100,
|
|
176
|
+
force: true,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
assert.equal(forcedResult.summary.d1_executed, false);
|
|
180
|
+
const clearedStatus = getLiveEvalStatus({ home });
|
|
181
|
+
assert.equal(clearedStatus.active, false, 'Forced finish clears active run');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test('finishLiveEvalRun reuses the configured inneranimalmedia MCP bearer for remote persistence', { concurrency: false }, async () => {
|
|
185
|
+
const home = tempHome();
|
|
186
|
+
const mcpDir = path.join(home, '.agentsam', 'mcp');
|
|
187
|
+
fs.mkdirSync(mcpDir, { recursive: true });
|
|
188
|
+
fs.writeFileSync(
|
|
189
|
+
path.join(mcpDir, 'inneranimalmedia.json'),
|
|
190
|
+
JSON.stringify({ auth: { type: 'bearer', token: 'fixture-eval-token' } }),
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
startLiveEvalRun({ case: 'authenticated-remote-eval' }, { home });
|
|
194
|
+
|
|
195
|
+
const originalFetch = globalThis.fetch;
|
|
196
|
+
let authorization = null;
|
|
197
|
+
try {
|
|
198
|
+
globalThis.fetch = async (_url, init = {}) => {
|
|
199
|
+
authorization = new Headers(init.headers).get('Authorization');
|
|
200
|
+
return new Response(JSON.stringify({ ok: true }), {
|
|
201
|
+
status: 200,
|
|
202
|
+
headers: { 'Content-Type': 'application/json' },
|
|
203
|
+
});
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const result = await finishLiveEvalRun({
|
|
207
|
+
home,
|
|
208
|
+
remote: true,
|
|
209
|
+
evalEndpoint: 'https://example.test/api/eval/record',
|
|
210
|
+
wranglerFallback: false,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
assert.equal(authorization, 'Bearer fixture-eval-token');
|
|
214
|
+
assert.equal(result.summary.d1_executed, true);
|
|
215
|
+
assert.equal(result.summary.persistence_method, 'http_endpoint');
|
|
216
|
+
} finally {
|
|
217
|
+
globalThis.fetch = originalFetch;
|
|
218
|
+
}
|
|
219
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { discoverGoRuntime, resolveProductRoot, ensureProductContract, buildGoProduct } from '../../src/go/index.js';
|
|
8
|
+
import { runGo } from '../../src/commands/go.js';
|
|
9
|
+
|
|
10
|
+
const SDK_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
|
11
|
+
|
|
12
|
+
test('discoverGoRuntime finds agentsam-go-worker without inventing a sibling', () => {
|
|
13
|
+
const discovery = discoverGoRuntime(SDK_ROOT);
|
|
14
|
+
assert.equal(discovery.go.ok, true);
|
|
15
|
+
assert.ok(discovery.runtime, 'expected Go runtime');
|
|
16
|
+
assert.match(discovery.runtime.module, /agentsam-go-worker/);
|
|
17
|
+
assert.equal(path.basename(discovery.runtime.productRoot), 'agentsam-go-worker');
|
|
18
|
+
const productRoot = resolveProductRoot(discovery, 'agentsam-go-worker');
|
|
19
|
+
const contract = ensureProductContract(productRoot);
|
|
20
|
+
assert.equal(contract.product, 'agentsam-go-worker');
|
|
21
|
+
assert.equal(contract.existing, true);
|
|
22
|
+
assert.deepEqual(contract.created, []);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('ensureProductContract refuses missing product roots instead of scaffolding siblings', () => {
|
|
26
|
+
const missing = path.join(os.tmpdir(), `agentsam-go-missing-${Date.now()}`);
|
|
27
|
+
assert.throws(() => ensureProductContract(missing), /product_root_missing/);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('buildGoProduct emits build receipt after go test/vet/build', () => {
|
|
31
|
+
const discovery = discoverGoRuntime(SDK_ROOT);
|
|
32
|
+
const productRoot = resolveProductRoot(discovery);
|
|
33
|
+
const result = buildGoProduct({
|
|
34
|
+
productRoot,
|
|
35
|
+
runtimeRoot: discovery.runtime.runtimeRoot,
|
|
36
|
+
repositoryRoot: discovery.repository_root,
|
|
37
|
+
});
|
|
38
|
+
assert.equal(result.receipt.schema, 'agentsam.go-build-receipt.v1');
|
|
39
|
+
assert.equal(result.tests.ok, true);
|
|
40
|
+
assert.equal(result.vet.ok, true);
|
|
41
|
+
assert.ok(result.build.binary);
|
|
42
|
+
assert.ok(fs.existsSync(result.receiptPath));
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('agentsam go --cloudflare agentsam-go-worker --skip-deploy is idempotent', async () => {
|
|
46
|
+
const chunks = [];
|
|
47
|
+
const write = (v) => chunks.push(String(v));
|
|
48
|
+
const first = await runGo(['--cloudflare', 'agentsam-go-worker', '--skip-deploy', '--json'], { write });
|
|
49
|
+
assert.equal(first.ok, true);
|
|
50
|
+
assert.equal(first.product, 'agentsam-go-worker');
|
|
51
|
+
assert.equal(first.scaffold_changes_required, false);
|
|
52
|
+
|
|
53
|
+
const chunks2 = [];
|
|
54
|
+
const second = await runGo(['--cloudflare', 'agentsam-go-worker', '--skip-deploy', '--json'], {
|
|
55
|
+
write: (v) => chunks2.push(String(v)),
|
|
56
|
+
});
|
|
57
|
+
assert.equal(second.ok, true);
|
|
58
|
+
assert.equal(second.existing_product, true);
|
|
59
|
+
assert.equal(second.scaffold_changes_required, false);
|
|
60
|
+
assert.ok(second.deploy.receiptPath);
|
|
61
|
+
assert.ok(fs.existsSync(second.deploy.productPath));
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('agentsam go status --json reports discovery', async () => {
|
|
65
|
+
const chunks = [];
|
|
66
|
+
const result = await runGo(['status', '--json'], { write: (v) => chunks.push(String(v)) });
|
|
67
|
+
assert.equal(result.ok, true);
|
|
68
|
+
assert.ok(result.discovery.go.ok);
|
|
69
|
+
const parsed = JSON.parse(chunks.join(''));
|
|
70
|
+
assert.equal(parsed.product, 'agentsam-go-worker');
|
|
71
|
+
});
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
getSecureProviderKey,
|
|
9
|
+
setSecureProviderKey,
|
|
10
|
+
deleteSecureProviderKey,
|
|
11
|
+
listSecureConfiguredProviders,
|
|
12
|
+
hydrateSecureCredentials,
|
|
13
|
+
localVaultPath,
|
|
14
|
+
localVaultSaltPath,
|
|
15
|
+
} from '../../src/security/local-vault.js';
|
|
16
|
+
import { resolveExecutableCommand } from '../../src/security/process.js';
|
|
17
|
+
import {
|
|
18
|
+
resolveProviderCredential,
|
|
19
|
+
setProviderCredential,
|
|
20
|
+
removeProviderCredential,
|
|
21
|
+
exportProviderEnvProfile,
|
|
22
|
+
} from '../../src/lib/provider-credentials.js';
|
|
23
|
+
import {
|
|
24
|
+
validateAndSaveProviderCredential,
|
|
25
|
+
providerChoices,
|
|
26
|
+
runProviders,
|
|
27
|
+
} from '../../src/commands/providers.js';
|
|
28
|
+
import { renderModelsStatus } from '../../src/commands/models.js';
|
|
29
|
+
|
|
30
|
+
// picocolors color-detection differs between local runs and CI runners (CI often
|
|
31
|
+
// reports TTY-like support that enables ANSI output) - strip escape codes before
|
|
32
|
+
// asserting on rendered text content so this test checks content, not incidental
|
|
33
|
+
// terminal color state.
|
|
34
|
+
// eslint-disable-next-line no-control-regex
|
|
35
|
+
const ANSI_PATTERN = /\x1B\[[0-9;]*m/g;
|
|
36
|
+
const stripAnsi = (s) => String(s).replace(ANSI_PATTERN, '');
|
|
37
|
+
|
|
38
|
+
function createTempHome(t) {
|
|
39
|
+
const home = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-vault-test-'));
|
|
40
|
+
t.after(() => fs.rmSync(home, { recursive: true, force: true }));
|
|
41
|
+
return home;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
test('resolveExecutableCommand resolves Windows .cmd shims with shell: true on win32', () => {
|
|
45
|
+
const npxWin = resolveExecutableCommand('npx', 'win32');
|
|
46
|
+
assert.equal(npxWin.command, 'npx.cmd');
|
|
47
|
+
assert.equal(npxWin.shell, true);
|
|
48
|
+
|
|
49
|
+
const npmWin = resolveExecutableCommand('npm', 'win32');
|
|
50
|
+
assert.equal(npmWin.command, 'npm.cmd');
|
|
51
|
+
assert.equal(npmWin.shell, true);
|
|
52
|
+
|
|
53
|
+
const wranglerWin = resolveExecutableCommand('wrangler', 'win32');
|
|
54
|
+
assert.equal(wranglerWin.command, 'wrangler.cmd');
|
|
55
|
+
assert.equal(wranglerWin.shell, true);
|
|
56
|
+
|
|
57
|
+
const scriptWin = resolveExecutableCommand('build.bat', 'win32');
|
|
58
|
+
assert.equal(scriptWin.command, 'build.bat');
|
|
59
|
+
assert.equal(scriptWin.shell, true);
|
|
60
|
+
|
|
61
|
+
// Linux and macOS are untouched
|
|
62
|
+
const npxMac = resolveExecutableCommand('npx', 'darwin');
|
|
63
|
+
assert.equal(npxMac.command, 'npx');
|
|
64
|
+
assert.equal(npxMac.shell, false);
|
|
65
|
+
|
|
66
|
+
const npmLinux = resolveExecutableCommand('npm', 'linux');
|
|
67
|
+
assert.equal(npmLinux.command, 'npm');
|
|
68
|
+
assert.equal(npmLinux.shell, false);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('local vault encrypts with AES-256-GCM and never writes plaintext secrets to disk', (t) => {
|
|
72
|
+
const home = createTempHome(t);
|
|
73
|
+
const opts = { home, disableOsStore: true };
|
|
74
|
+
|
|
75
|
+
const secret = 'sk-proj-testsecret1234567890abcdef';
|
|
76
|
+
setSecureProviderKey('openai', secret, opts);
|
|
77
|
+
|
|
78
|
+
const retrieved = getSecureProviderKey('openai', opts);
|
|
79
|
+
assert.equal(retrieved.value, secret);
|
|
80
|
+
assert.equal(retrieved.source, 'local_vault');
|
|
81
|
+
|
|
82
|
+
// Verify disk contents
|
|
83
|
+
const encFile = localVaultPath(opts);
|
|
84
|
+
assert.equal(fs.existsSync(encFile), true);
|
|
85
|
+
const rawText = fs.readFileSync(encFile, 'utf8');
|
|
86
|
+
|
|
87
|
+
// Plaintext MUST NOT appear anywhere in the file
|
|
88
|
+
assert.equal(rawText.includes(secret), false);
|
|
89
|
+
|
|
90
|
+
// Must have JSON with iv, tag, and data
|
|
91
|
+
const parsed = JSON.parse(rawText);
|
|
92
|
+
assert.ok(parsed.secrets.openai.iv);
|
|
93
|
+
assert.ok(parsed.secrets.openai.tag);
|
|
94
|
+
assert.ok(parsed.secrets.openai.data);
|
|
95
|
+
|
|
96
|
+
// Salt file must exist with restrictive permissions
|
|
97
|
+
const saltFile = localVaultSaltPath(opts);
|
|
98
|
+
assert.equal(fs.existsSync(saltFile), true);
|
|
99
|
+
if (process.platform !== 'win32') {
|
|
100
|
+
assert.equal(fs.statSync(saltFile).mode & 0o777, 0o600);
|
|
101
|
+
assert.equal(fs.statSync(encFile).mode & 0o777, 0o600);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test('local vault detects tampering of encrypted ciphertext', (t) => {
|
|
106
|
+
const home = createTempHome(t);
|
|
107
|
+
const opts = { home, disableOsStore: true };
|
|
108
|
+
|
|
109
|
+
setSecureProviderKey('anthropic', 'sk-ant-test-key-12345', opts);
|
|
110
|
+
|
|
111
|
+
// Tamper with the ciphertext
|
|
112
|
+
const encFile = localVaultPath(opts);
|
|
113
|
+
const parsed = JSON.parse(fs.readFileSync(encFile, 'utf8'));
|
|
114
|
+
const originalData = parsed.secrets.anthropic.data;
|
|
115
|
+
// Flip the last hex byte
|
|
116
|
+
const tamperedData = originalData.slice(0, -2) + (originalData.slice(-2) === 'aa' ? 'bb' : 'aa');
|
|
117
|
+
parsed.secrets.anthropic.data = tamperedData;
|
|
118
|
+
fs.writeFileSync(encFile, JSON.stringify(parsed));
|
|
119
|
+
|
|
120
|
+
// Decryption must fail and return null safely rather than corrupt data
|
|
121
|
+
const retrieved = getSecureProviderKey('anthropic', opts);
|
|
122
|
+
assert.equal(retrieved, null);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('local vault stores and retrieves Cloudflare accountId alongside token', (t) => {
|
|
126
|
+
const home = createTempHome(t);
|
|
127
|
+
const opts = { home, disableOsStore: true };
|
|
128
|
+
|
|
129
|
+
setSecureProviderKey('cloudflare', { value: 'cf-token-123', accountId: 'abcdef0123456789abcdef0123456789' }, opts);
|
|
130
|
+
const retrieved = getSecureProviderKey('cloudflare', opts);
|
|
131
|
+
|
|
132
|
+
assert.equal(retrieved.value, 'cf-token-123');
|
|
133
|
+
assert.equal(retrieved.accountId, 'abcdef0123456789abcdef0123456789');
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('hydrateSecureCredentials populates process.env for unconfigured providers without overwriting', (t) => {
|
|
137
|
+
const home = createTempHome(t);
|
|
138
|
+
const opts = { home, disableOsStore: true };
|
|
139
|
+
|
|
140
|
+
setSecureProviderKey('gemini', 'gemini-key-val-789', opts);
|
|
141
|
+
|
|
142
|
+
const mockEnv = {
|
|
143
|
+
EXISTING_KEY: 'pre-existing',
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const hydrated = hydrateSecureCredentials(mockEnv, opts);
|
|
147
|
+
assert.ok(hydrated.includes('gemini'));
|
|
148
|
+
assert.equal(mockEnv.GEMINI_API_KEY, 'gemini-key-val-789');
|
|
149
|
+
|
|
150
|
+
// Second run does not overwrite
|
|
151
|
+
mockEnv.GEMINI_API_KEY = 'user-override';
|
|
152
|
+
hydrateSecureCredentials(mockEnv, opts);
|
|
153
|
+
assert.equal(mockEnv.GEMINI_API_KEY, 'user-override');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test('resolveProviderCredential resolves keys from local secure vault across any directory', (t) => {
|
|
157
|
+
const home = createTempHome(t);
|
|
158
|
+
const opts = { home, disableOsStore: true };
|
|
159
|
+
|
|
160
|
+
setProviderCredential('cursor', 'cur-key-secret-456', opts);
|
|
161
|
+
|
|
162
|
+
const resolved = resolveProviderCredential('cursor', { env: {}, home, disableOsStore: true });
|
|
163
|
+
assert.equal(resolved.configured, true);
|
|
164
|
+
assert.equal(resolved.value, 'cur-key-secret-456');
|
|
165
|
+
|
|
166
|
+
// Deleting removes it
|
|
167
|
+
removeProviderCredential('cursor', opts);
|
|
168
|
+
const afterRemove = resolveProviderCredential('cursor', { env: {}, home, disableOsStore: true });
|
|
169
|
+
assert.equal(afterRemove.configured, false);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test('validateAndSaveProviderCredential rejects invalid key and does NOT persist it', async (t) => {
|
|
173
|
+
const home = createTempHome(t);
|
|
174
|
+
const opts = {
|
|
175
|
+
home,
|
|
176
|
+
disableOsStore: true,
|
|
177
|
+
fetchImpl: async () => ({
|
|
178
|
+
ok: false,
|
|
179
|
+
status: 401,
|
|
180
|
+
json: async () => ({ error: { message: 'Incorrect API key provided' } }),
|
|
181
|
+
}),
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const result = await validateAndSaveProviderCredential('openai', 'sk-invalid-test-key', opts);
|
|
185
|
+
assert.equal(result.ok, false);
|
|
186
|
+
assert.equal(result.saved, false);
|
|
187
|
+
assert.match(result.error, /Incorrect API key/i);
|
|
188
|
+
|
|
189
|
+
// Verify it was NOT stored in the vault!
|
|
190
|
+
const retrieved = getSecureProviderKey('openai', opts);
|
|
191
|
+
assert.equal(retrieved, null);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test('validateAndSaveProviderCredential verifies valid key and saves ONLY to local vault without plaintext file', async (t) => {
|
|
195
|
+
const home = createTempHome(t);
|
|
196
|
+
const opts = {
|
|
197
|
+
home,
|
|
198
|
+
disableOsStore: true,
|
|
199
|
+
fetchImpl: async () => ({
|
|
200
|
+
ok: true,
|
|
201
|
+
status: 200,
|
|
202
|
+
json: async () => ({
|
|
203
|
+
data: [{ id: 'gpt-4o' }, { id: 'gpt-4o-mini' }],
|
|
204
|
+
}),
|
|
205
|
+
}),
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const result = await validateAndSaveProviderCredential('openai', 'sk-valid-key-xyz', opts);
|
|
209
|
+
assert.equal(result.ok, true);
|
|
210
|
+
assert.equal(result.saved, true);
|
|
211
|
+
assert.equal(result.model_count, 2);
|
|
212
|
+
|
|
213
|
+
// Verify it was saved to local vault
|
|
214
|
+
const retrieved = getSecureProviderKey('openai', opts);
|
|
215
|
+
assert.equal(retrieved.value, 'sk-valid-key-xyz');
|
|
216
|
+
|
|
217
|
+
// CRITICAL: Plaintext .env profile file MUST NOT be created automatically!
|
|
218
|
+
const plaintextFile = path.join(home, '.agentsam', 'env.d', 'openai.env');
|
|
219
|
+
assert.equal(fs.existsSync(plaintextFile), false, 'Plaintext .env file must NOT exist after secure provider setup');
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test('exportProviderEnvProfile and agentsam providers export create plaintext .env file ONLY on explicit opt-in', async (t) => {
|
|
223
|
+
const home = createTempHome(t);
|
|
224
|
+
const opts = { home, disableOsStore: true };
|
|
225
|
+
|
|
226
|
+
// Set up provider key in secure vault
|
|
227
|
+
setProviderCredential('anthropic', 'sk-ant-test-export-key', opts);
|
|
228
|
+
|
|
229
|
+
// Confirm NO plaintext file exists yet
|
|
230
|
+
const plaintextFile = path.join(home, '.agentsam', 'env.d', 'anthropic.env');
|
|
231
|
+
assert.equal(fs.existsSync(plaintextFile), false);
|
|
232
|
+
|
|
233
|
+
// Explicit opt-in export via CLI command
|
|
234
|
+
let output = '';
|
|
235
|
+
const exported = await runProviders(['export', 'anthropic'], {
|
|
236
|
+
...opts,
|
|
237
|
+
write: (text) => { output += text; },
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
assert.equal(exported.provider, 'anthropic');
|
|
241
|
+
assert.equal(fs.existsSync(plaintextFile), true);
|
|
242
|
+
const content = fs.readFileSync(plaintextFile, 'utf8');
|
|
243
|
+
assert.match(content, /ANTHROPIC_API_KEY="sk-ant-test-export-key"/);
|
|
244
|
+
assert.match(output, /Exported anthropic profile/);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test('renderModelsStatus shows tip: Select your preferred provider when providers are unconfigured', () => {
|
|
248
|
+
const status = {
|
|
249
|
+
providers: [
|
|
250
|
+
{ id: 'openai', label: 'OpenAI', configured: false, credential: 'OPENAI_API_KEY' },
|
|
251
|
+
{ id: 'anthropic', label: 'Anthropic', configured: false, credential: 'ANTHROPIC_API_KEY' },
|
|
252
|
+
],
|
|
253
|
+
discovery: {},
|
|
254
|
+
providerModels: {},
|
|
255
|
+
local: { online: false, models: [] },
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const output = stripAnsi(renderModelsStatus(status));
|
|
259
|
+
assert.match(output, /Tip:\s*Select your preferred provider/i);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
test('providerChoices returns valid choice list for select picker', () => {
|
|
263
|
+
const choices = providerChoices();
|
|
264
|
+
assert.ok(choices.length >= 6);
|
|
265
|
+
assert.ok(choices.some((c) => c.value === 'openai'));
|
|
266
|
+
assert.ok(choices.some((c) => c.value === 'anthropic'));
|
|
267
|
+
assert.ok(choices.some((c) => c.value === 'gemini'));
|
|
268
|
+
});
|