@inneranimalmedia/agentsam-sdk 2.6.7 → 2.6.9
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/README.md +37 -0
- package/apps/README.md +25 -0
- package/apps/cad-creator/shared/cad/package.json +1 -1
- package/apps/client-cms-editor/backend/package.json +4 -6
- package/apps/client-cms-editor/frontend/package.json +6 -8
- package/apps/client-cms-editor/frontend/tsconfig.json +27 -8
- package/apps/client-cms-editor/package.json +1 -1
- package/apps/client-cms-editor/shared/cms/package.json +4 -6
- package/docs/LOCAL_ENGINE_COMPUTE_AUDIT_PLAN.md +299 -0
- package/docs/REPO_FILE_MAP.txt +132 -0
- package/migrations/d1/0018_goap_control_plane_remaster.sql +40 -0
- package/migrations/d1/0019_agentsam_agent_run_plan_todo.sql +14 -0
- package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +20 -9
- package/migrations/runtime/0002_goap_blackboard_v1.sql +15 -0
- package/migrations/runtime/0004_agent_run_plan_linkage.sql +8 -0
- package/native/agentsam-machine/cli/Cargo.toml +8 -1
- package/native/agentsam-machine/cli/README.md +21 -0
- package/native/agentsam-machine/core/Cargo.toml +7 -0
- package/native/agentsam-machine/core/README.md +14 -0
- package/native/agentsam-machine/core/build.rs +33 -0
- package/native/agentsam-machine/core/contracts/source-types.v1.json +353 -0
- package/native/agentsam-machine/core/src/lib.rs +6 -0
- package/native/agentsam-machine/core/src/source_types.rs +2 -2
- package/package.json +31 -10
- package/packages/agentsam-brand/package.json +1 -1
- package/packages/agentsam-contracts/package.json +71 -20
- package/packages/agentsam-contracts/scripts/build.mjs +18 -0
- package/packages/agentsam-contracts/test/contracts.test.mjs +4 -1
- package/packages/agentsam-contracts/test/repository.test.mjs +4 -1
- package/packages/agentsam-contracts/tsconfig.build.json +10 -0
- package/packages/agentsam-errors/package.json +3 -2
- package/packages/agentsam-errors/src/index.js +1 -0
- package/packages/agentsam-errors/src/tool.js +56 -0
- package/packages/agentsam-errors/test/tool.test.mjs +58 -0
- package/packages/agentsam-goap/README.md +52 -0
- package/packages/agentsam-goap/package.json +37 -0
- package/packages/agentsam-goap/src/adapters/d1-sqlite.js +570 -0
- package/packages/agentsam-goap/src/adapters/memory.js +199 -0
- package/packages/agentsam-goap/src/contracts.js +226 -0
- package/packages/agentsam-goap/src/control-plane.js +112 -0
- package/packages/agentsam-goap/src/errors.js +157 -0
- package/packages/agentsam-goap/src/index.js +5 -0
- package/packages/agentsam-goap/src/world.js +202 -0
- package/packages/agentsam-goap/test/goap-control-plane.test.mjs +245 -0
- package/packages/agentsam-goap/test/world.test.mjs +79 -0
- package/packages/agentsam-knowledge/package.json +3 -2
- package/packages/agentsam-nav/package.json +1 -1
- package/packages/agentsam-queue-control/package.json +1 -1
- package/packages/agentsam-rapid-rust/src/main.rs +1 -0
- package/packages/agentsam-repository/package.json +3 -2
- package/packages/agentsam-repository/src/goap.js +13 -14
- package/packages/agentsam-repository/src/tickets.js +15 -22
- package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +19 -8
- package/packages/agentsam-vault/package.json +8 -5
- package/packages/agentsam-workbench/package.json +44 -17
- package/packages/connectors/cloudflare/package.json +4 -2
- package/packages/heuristic-theme/package.json +1 -1
- package/packages/identity/package.json +4 -3
- package/packages/identity/tests/lane1-packed-consumer.test.mjs +10 -2
- package/packages/providers/completeful/package.json +1 -1
- package/packages/theme-church-site/README.md +2 -2
- package/packages/theme-church-site/package.json +3 -4
- package/packages/theme-church-site/src/index.js +1 -1
- package/packages/theme-church-site/test/theme.test.mjs +1 -1
- package/packages/theme-companions-site/README.md +2 -2
- package/packages/theme-companions-site/package.json +3 -4
- package/packages/theme-companions-site/src/index.js +1 -1
- package/packages/theme-companions-site/test/theme.test.mjs +1 -1
- package/packages/theme-floors-site/README.md +2 -2
- package/packages/theme-floors-site/package.json +3 -4
- package/packages/theme-floors-site/src/index.js +1 -1
- package/packages/theme-floors-site/test/theme.test.mjs +1 -1
- package/packages/theme-fuelnfree-site/README.md +2 -2
- package/packages/theme-fuelnfree-site/package.json +3 -4
- package/packages/theme-fuelnfree-site/src/index.js +1 -1
- package/packages/theme-fuelnfree-site/test/theme.test.mjs +1 -1
- package/packages/theme-handyman-site/README.md +2 -2
- package/packages/theme-handyman-site/package.json +3 -4
- package/packages/theme-handyman-site/src/index.js +1 -1
- package/packages/theme-handyman-site/test/theme.test.mjs +1 -1
- package/packages/theme-insurance-site/README.md +2 -2
- package/packages/theme-insurance-site/package.json +3 -4
- package/packages/theme-insurance-site/src/index.js +1 -1
- package/packages/theme-insurance-site/test/theme.test.mjs +1 -1
- package/packages/theme-scenes/package.json +1 -1
- package/packages/theme-shinshu-site/README.md +2 -2
- package/packages/theme-shinshu-site/package.json +3 -4
- package/packages/theme-shinshu-site/src/index.js +1 -1
- package/packages/theme-shinshu-site/test/theme.test.mjs +1 -1
- package/packages/work-graph/package.json +3 -2
- package/protocol/local-engine/benchmark.v1.schema.json +14 -0
- package/protocol/local-engine/engine.v1.schema.json +17 -0
- package/python/agentsam_sdk/repository/intelligence/discovery.py +27 -2
- package/python/agentsam_sdk/repository/intelligence/git.py +4 -0
- package/python/tests/test_repository_intelligence.py +30 -0
- package/src/cli/command-catalog.js +3 -1
- package/src/cli.js +20 -1
- package/src/commands/app.js +10 -0
- package/src/commands/engine.js +10 -0
- package/src/commands/goap-world.js +134 -0
- package/src/commands/goap.js +11 -4
- package/src/commands/machine-binary.js +33 -27
- package/src/commands/machine-runtime.js +266 -0
- package/src/commands/machine.js +155 -51
- package/src/commands/package.js +537 -0
- package/src/commands/plan-ledger.js +370 -0
- package/src/commands/plan.js +183 -0
- package/src/commands/runtime.js +25 -10
- package/src/commands/setup.js +30 -6
- package/src/commands/skill.js +78 -17
- package/src/commands/terminal.js +20 -8
- package/src/errors/contract.js +4 -4
- package/src/errors/diagnostic.js +1 -1
- package/src/errors/index.js +1 -1
- package/src/index.js +20 -0
- package/src/indexing/ingest/materials.js +237 -30
- package/src/knowledge/source.js +1 -1
- package/src/lib/setup/runtime.js +4 -2
- package/src/lib/slash-commands.js +1 -1
- package/src/local/runtime-store.js +24 -2
- package/src/local/sqlite.js +17 -0
- package/src/local-engine/assets.js +37 -0
- package/src/local-engine/audit.js +133 -0
- package/src/local-engine/benchmark.js +26 -0
- package/src/local-engine/contracts.js +101 -0
- package/src/local-engine/engines.js +142 -0
- package/src/local-engine/index.js +18 -0
- package/src/local-engine/runtime.js +39 -0
- package/src/sam/operations/package-audit.js +41 -0
- package/src/sam/seed.js +2 -0
- package/skills/grok-auth/SKILL.md +0 -110
- package/skills/grok-auth/agentsam.skill.json +0 -25
- package/skills/grok-auth/references/grok-identity.md +0 -64
- package/skills/grok-auth/references/per-user-data.md +0 -49
- package/skills/grok-auth/references/prewired-and-env.md +0 -54
- package/skills/grok-auth/references/session-ui.md +0 -133
- package/skills/grok-auth/references/sign-in-methods.md +0 -55
- package/skills/grok-auth/references/wiring.md +0 -71
- package/skills/grok-building-games/SKILL.md +0 -213
- package/skills/grok-building-games/agentsam.skill.json +0 -25
- package/skills/grok-building-games/references/3d-libs.md +0 -64
- package/skills/grok-building-games/references/ai-pathfinding.md +0 -122
- package/skills/grok-building-games/references/audio.md +0 -129
- package/skills/grok-building-games/references/babylon.md +0 -202
- package/skills/grok-building-games/references/collision-physics.md +0 -122
- package/skills/grok-building-games/references/ecs-architecture.md +0 -111
- package/skills/grok-building-games/references/game-feel-juice.md +0 -110
- package/skills/grok-building-games/references/genres/board-card-chess.md +0 -89
- package/skills/grok-building-games/references/genres/endless-runner.md +0 -83
- package/skills/grok-building-games/references/genres/fps.md +0 -105
- package/skills/grok-building-games/references/genres/platformer-2d.md +0 -97
- package/skills/grok-building-games/references/genres/puzzle-match3-tetris.md +0 -131
- package/skills/grok-building-games/references/genres/racing-kart.md +0 -106
- package/skills/grok-building-games/references/genres/topdown-twin-stick.md +0 -97
- package/skills/grok-building-games/references/genres/tower-defense.md +0 -84
- package/skills/grok-building-games/references/genres/voxel-minecraft.md +0 -89
- package/skills/grok-building-games/references/input.md +0 -139
- package/skills/grok-building-games/references/phaser.md +0 -277
- package/skills/grok-building-games/references/procedural-generation.md +0 -141
- package/skills/grok-building-games/references/save-persistence.md +0 -108
- package/skills/grok-building-games/references/threejs-foundational.md +0 -148
- package/skills/grok-controls/SKILL.md +0 -274
- package/skills/grok-controls/agentsam.skill.json +0 -25
- package/skills/grok-design-ui/SKILL.md +0 -122
- package/skills/grok-design-ui/agentsam.skill.json +0 -25
- package/skills/grok-design-ui/references/animations.md +0 -379
- package/skills/grok-design-ui/references/performance.md +0 -88
- package/skills/grok-design-ui/references/refined-ui.md +0 -384
- package/skills/grok-design-ui/references/surfaces.md +0 -247
- package/skills/grok-design-ui/references/typography.md +0 -123
- package/skills/grok-game-animation-frames/SKILL.md +0 -84
- package/skills/grok-game-animation-frames/agentsam.skill.json +0 -25
- package/skills/grok-game-asset-core/SKILL.md +0 -69
- package/skills/grok-game-asset-core/agentsam.skill.json +0 -25
- package/skills/grok-game-character-consistency/SKILL.md +0 -69
- package/skills/grok-game-character-consistency/agentsam.skill.json +0 -25
- package/skills/grok-game-tilesets/SKILL.md +0 -65
- package/skills/grok-game-tilesets/agentsam.skill.json +0 -25
- package/skills/grok-game-ui-icons/SKILL.md +0 -56
- package/skills/grok-game-ui-icons/agentsam.skill.json +0 -25
- package/skills/grok-generate2dmap/LICENSE +0 -21
- package/skills/grok-generate2dmap/SKILL.md +0 -120
- package/skills/grok-generate2dmap/SOURCE.md +0 -6
- package/skills/grok-generate2dmap/agentsam.skill.json +0 -25
- package/skills/grok-generate2dmap/references/deliverables.md +0 -101
- package/skills/grok-generate2dmap/references/layered-map-contract.md +0 -209
- package/skills/grok-generate2dmap/references/map-strategies.md +0 -341
- package/skills/grok-generate2dmap/references/object-production-gate.md +0 -24
- package/skills/grok-generate2dmap/references/pipeline.md +0 -149
- package/skills/grok-generate2dmap/references/prop-pack-contract.md +0 -174
- package/skills/grok-generate2dmap/references/side-scroll-stages.md +0 -29
- package/skills/grok-generate2dmap/scripts/compose_layered_preview.py +0 -157
- package/skills/grok-generate2dmap/scripts/extract_prop_pack.py +0 -369
- package/skills/grok-generate2dsprite/LICENSE +0 -21
- package/skills/grok-generate2dsprite/SKILL.md +0 -313
- package/skills/grok-generate2dsprite/SOURCE.md +0 -6
- package/skills/grok-generate2dsprite/agentsam.skill.json +0 -25
- package/skills/grok-generate2dsprite/references/modes.md +0 -124
- package/skills/grok-generate2dsprite/references/prompt-rules.md +0 -315
- package/skills/grok-generate2dsprite/scripts/generate2dsprite.py +0 -1031
- package/skills/grok-generate2dsprite/scripts/make_layout_guide.py +0 -109
- package/skills/grok-imagine/SKILL.md +0 -201
- package/skills/grok-imagine/agentsam.skill.json +0 -25
- package/skills/grok-multiplayer-p2p/SKILL.md +0 -111
- package/skills/grok-multiplayer-p2p/agentsam.skill.json +0 -25
- package/skills/grok-multiplayer-p2p/references/react-binding.md +0 -144
- package/skills/grok-multiplayer-p2p/references/signaling-relay.md +0 -269
- package/skills/grok-neon/SKILL.md +0 -157
- package/skills/grok-neon/agentsam.skill.json +0 -25
- package/skills/grok-og/SKILL.md +0 -102
- package/skills/grok-og/agentsam.skill.json +0 -25
- package/skills/grok-og/references/brand-pass.md +0 -53
- package/skills/grok-og/references/custom-card.md +0 -107
- package/skills/grok-og/references/favicon-and-icons.md +0 -48
- package/skills/grok-og/references/og-type-contract.md +0 -18
- package/skills/grok-og/references/placeholder-card.md +0 -21
- package/skills/grok-og/references/x-banner.md +0 -41
- package/skills/grok-threejs/SKILL.md +0 -67
- package/skills/grok-threejs/agentsam.skill.json +0 -25
- package/skills/grok-threejs/references/llms-full.txt +0 -2780
- package/skills/grok-video2dsprite/LICENSE +0 -21
- package/skills/grok-video2dsprite/SKILL.md +0 -236
- package/skills/grok-video2dsprite/SOURCE.md +0 -6
- package/skills/grok-video2dsprite/agentsam.skill.json +0 -25
- package/skills/grok-video2dsprite/references/pipeline.md +0 -90
- package/skills/grok-video2dsprite/references/prompt-rules.md +0 -63
- package/skills/grok-video2dsprite/scripts/video2dsprite.py +0 -490
- package/skills/grok-xai-api/SKILL.md +0 -152
- package/skills/grok-xai-api/agentsam.skill.json +0 -25
- package/test/account-session.test.mjs +0 -101
- package/test/agent-capabilities.test.mjs +0 -67
- package/test/app-authority-context.test.mjs +0 -32
- package/test/app-building-skills.test.mjs +0 -61
- package/test/apps-scaffold-contract.test.mjs +0 -115
- package/test/blender-cad.test.mjs +0 -146
- package/test/cad-docker.test.mjs +0 -96
- package/test/capabilities.test.mjs +0 -133
- package/test/cli/api-key-env-whoami.test.mjs +0 -129
- package/test/cli/catalog-authority.test.mjs +0 -64
- package/test/cli/codebaseindex-plan-ux.test.mjs +0 -37
- package/test/cli/eval-live.test.mjs +0 -219
- package/test/cli/go.test.mjs +0 -128
- package/test/cli/local-vault-and-provider-setup.test.mjs +0 -268
- package/test/cli/machine-command.test.mjs +0 -34
- package/test/cli/mcp-client.test.mjs +0 -256
- package/test/cli/preferences-runtime.test.mjs +0 -11
- package/test/cli/runtime-persist.test.mjs +0 -56
- package/test/cli/runtime-ui.test.mjs +0 -141
- package/test/cli/rust-command.test.mjs +0 -21
- package/test/cli/skill-npm-and-env.test.mjs +0 -52
- package/test/cli/status-actions.test.mjs +0 -88
- package/test/cli/wireframes-go-registry.test.mjs +0 -139
- package/test/cli-preferences.test.mjs +0 -46
- package/test/cloudflare-connector.test.mjs +0 -93
- package/test/cloudflare-runtime.test.mjs +0 -82
- package/test/context.test.mjs +0 -159
- package/test/credentials-audit.test.mjs +0 -113
- package/test/deploy-health-scan.test.mjs +0 -95
- package/test/deploy-receipt.test.mjs +0 -91
- package/test/dockerize.test.mjs +0 -93
- package/test/error-diagnostics.test.mjs +0 -124
- package/test/eval-context.test.mjs +0 -37
- package/test/execution-approvals.test.mjs +0 -27
- package/test/fixtures/cad/courtyard-house.json +0 -208
- package/test/fixtures/knowledge-rpc-worker.mjs +0 -16
- package/test/fixtures/project-authority/customer-app/.agentsam/app.json +0 -5
- package/test/fixtures/project-authority/customer-app/apps/my-product/index.ts +0 -1
- package/test/fixtures/project-authority/customer-app/wrangler.toml +0 -17
- package/test/gcloud-auth.test.mjs +0 -111
- package/test/go/build-source-identity.test.mjs +0 -31
- package/test/go/cloudflare-probe.test.mjs +0 -317
- package/test/go/distribution.test.mjs +0 -28
- package/test/google-cloud-connection.test.mjs +0 -83
- package/test/google-cloud-inventory.test.mjs +0 -64
- package/test/indexing-provider.test.mjs +0 -29
- package/test/init-options.test.mjs +0 -35
- package/test/integration/ai-access-onboarding.test.mjs +0 -47
- package/test/integration/app-command.test.mjs +0 -85
- package/test/integration/autorag-project-authority.integration.test.mjs +0 -51
- package/test/integration/autorag-runtime-discovery.test.mjs +0 -107
- package/test/integration/cad-discovery.test.mjs +0 -158
- package/test/integration/cad-docker-executor.test.mjs +0 -249
- package/test/integration/cad-execution.test.mjs +0 -184
- package/test/integration/cad-project-app.test.mjs +0 -31
- package/test/integration/cad-project-d1.test.mjs +0 -25
- package/test/integration/cad-project-native.test.mjs +0 -24
- package/test/integration/cad-project-workflow.test.mjs +0 -9
- package/test/integration/cad-project.test.mjs +0 -85
- package/test/integration/cli-help.test.mjs +0 -41
- package/test/integration/cms-app-scaffold.test.mjs +0 -77
- package/test/integration/cms-site-tenancy-contract.test.mjs +0 -268
- package/test/integration/codebaseindex-ingest.test.mjs +0 -255
- package/test/integration/core-client.integration.test.mjs +0 -55
- package/test/integration/database-hosted-honesty.test.mjs +0 -49
- package/test/integration/desktop-keychain-boundary.test.mjs +0 -45
- package/test/integration/error-runtime-rpc.test.mjs +0 -71
- package/test/integration/features-resolve.test.mjs +0 -147
- package/test/integration/hosted-work-host-authority.test.mjs +0 -47
- package/test/integration/icon-registry.test.mjs +0 -67
- package/test/integration/ingest-discover-models.test.mjs +0 -30
- package/test/integration/inspect-path-cli.test.mjs +0 -46
- package/test/integration/install-script.test.mjs +0 -110
- package/test/integration/inventory-core.test.mjs +0 -53
- package/test/integration/inventory-eligibility.test.mjs +0 -59
- package/test/integration/inventory-evidence.test.mjs +0 -125
- package/test/integration/knowledge-rpc.test.mjs +0 -112
- package/test/integration/local-fs.test.mjs +0 -113
- package/test/integration/local-provider-bridge.test.mjs +0 -65
- package/test/integration/local-studio-settings-production.test.mjs +0 -40
- package/test/integration/lockfile-sync.test.mjs +0 -26
- package/test/integration/merkle-cli.test.mjs +0 -61
- package/test/integration/merkle-persistence-identity.test.mjs +0 -48
- package/test/integration/plugins-cloudflare.integration.test.mjs +0 -28
- package/test/integration/provider-env-cli.test.mjs +0 -60
- package/test/integration/provider-factory.test.mjs +0 -197
- package/test/integration/repository-company-graph.test.mjs +0 -90
- package/test/integration/runtime-migrations.test.mjs +0 -87
- package/test/integration/runtime-status.integration.test.mjs +0 -227
- package/test/integration/sam-activity-recovery.test.mjs +0 -147
- package/test/integration/sam-decision.test.mjs +0 -584
- package/test/integration/sam-kernel.test.mjs +0 -99
- package/test/integration/sam-planning-astar.test.mjs +0 -279
- package/test/integration/scaffold-cloudflare.test.mjs +0 -46
- package/test/integration/skill-runtime.test.mjs +0 -240
- package/test/integration/storage-architecture.test.mjs +0 -154
- package/test/integration/store-discovery.test.mjs +0 -44
- package/test/integration/studio-fs-pty-e2e.test.mjs +0 -294
- package/test/integration/terminal-exec.integration.test.mjs +0 -86
- package/test/integration/theme-package-registry.test.mjs +0 -31
- package/test/integration/tool-runtime.test.mjs +0 -124
- package/test/integration/tool-schema.test.mjs +0 -59
- package/test/jr-dev-skill.test.mjs +0 -26
- package/test/knowledge-context-pack.test.mjs +0 -19
- package/test/knowledge-postgres.test.mjs +0 -40
- package/test/knowledge-service.test.mjs +0 -110
- package/test/knowledge.test.mjs +0 -206
- package/test/live/terminal-transport.live.test.mjs +0 -24
- package/test/local-sessions.test.mjs +0 -57
- package/test/local-studio-deploy.test.mjs +0 -83
- package/test/loopback-oauth.test.mjs +0 -53
- package/test/merkle-render.test.mjs +0 -31
- package/test/mini.test.mjs +0 -140
- package/test/model-catalog.test.mjs +0 -70
- package/test/models.test.mjs +0 -309
- package/test/npm10-lock.test.mjs +0 -29
- package/test/ollama.test.mjs +0 -137
- package/test/open-url.test.mjs +0 -64
- package/test/openai-responses.test.mjs +0 -155
- package/test/portable-context.test.mjs +0 -94
- package/test/project-config.test.mjs +0 -81
- package/test/project-rules.test.mjs +0 -44
- package/test/provider-credentials.test.mjs +0 -106
- package/test/rehydrate.test.mjs +0 -25
- package/test/release-hygiene.test.mjs +0 -42
- package/test/repository-snapshot-view.test.mjs +0 -112
- package/test/responses-runner.test.mjs +0 -465
- package/test/runtime-activity.test.mjs +0 -98
- package/test/sdk-worker-contract.test.mjs +0 -72
- package/test/security.test.mjs +0 -266
- package/test/setup-planner.test.mjs +0 -74
- package/test/setup-runtime.test.mjs +0 -51
- package/test/shell.test.mjs +0 -281
- package/test/skills.test.mjs +0 -22
- package/test/smoke.mjs +0 -122
- package/test/telemetry.test.mjs +0 -79
- package/test/terminal/local-pty.mock.test.mjs +0 -153
- package/test/terminal-machine-identity.test.mjs +0 -88
- package/test/theme-portability.test.mjs +0 -14
- package/test/tools-search.test.mjs +0 -73
- package/test/unit/website-assets-bindings.test.mjs +0 -60
- package/test/whoami-resume.test.mjs +0 -157
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import test from 'node:test';
|
|
3
|
-
import { createOpenAIResponsesAdapter } from '../src/providers/index.js';
|
|
4
|
-
|
|
5
|
-
function jsonResponse(body, status = 200) {
|
|
6
|
-
return { ok: status >= 200 && status < 300, status, async json() { return body; } };
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
test('Responses adapter sends reasoning/service tier without legacy sampling parameters and reconciles provider usage', async () => {
|
|
10
|
-
let request = null;
|
|
11
|
-
const events = [];
|
|
12
|
-
const adapter = createOpenAIResponsesAdapter({
|
|
13
|
-
apiKey: 'test-key',
|
|
14
|
-
emit: event => events.push(event),
|
|
15
|
-
fetchImpl: async (url, options) => {
|
|
16
|
-
request = { url, options, body: JSON.parse(options.body) };
|
|
17
|
-
return jsonResponse({
|
|
18
|
-
id: 'resp_test', status: 'completed', model: 'gpt-6-astra', service_tier: 'fast',
|
|
19
|
-
output: [{ type: 'message', content: [{ type: 'output_text', text: 'done' }] }],
|
|
20
|
-
usage: {
|
|
21
|
-
input_tokens: 100_000,
|
|
22
|
-
input_tokens_details: { cached_tokens: 80_000, cache_write_tokens: 10_000 },
|
|
23
|
-
output_tokens: 5_000,
|
|
24
|
-
output_tokens_details: { reasoning_tokens: 2_000 },
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
const result = await adapter.create({ model: 'gpt-6-astra', input: 'work', reasoningEffort: 'high', serviceTier: 'fast' });
|
|
30
|
-
assert.equal(request.url, 'https://api.openai.com/v1/responses');
|
|
31
|
-
assert.equal(request.body.reasoning.effort, 'high');
|
|
32
|
-
assert.equal(request.body.service_tier, 'fast');
|
|
33
|
-
assert.equal(request.body.truncation, 'disabled');
|
|
34
|
-
assert.equal('temperature' in request.body, false);
|
|
35
|
-
assert.equal('top_p' in request.body, false);
|
|
36
|
-
assert.equal(result.output_text, 'done');
|
|
37
|
-
assert.equal(result.usage_snapshot.current_context.input_tokens, 100_000);
|
|
38
|
-
assert.equal(result.usage_snapshot.current_context.window_tokens, 1_050_000);
|
|
39
|
-
assert.equal(result.actual_service_tier, 'fast');
|
|
40
|
-
assert.equal(result.cost.rates_per_million.input, 20);
|
|
41
|
-
assert.deepEqual(events.map(event => event.type), ['model.started', 'usage.snapshot', 'cost.snapshot', 'model.completed']);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('Responses adapter carries hosted built-ins and function tools through /v1/responses with model capability checks', async () => {
|
|
45
|
-
let request = null;
|
|
46
|
-
const adapter = createOpenAIResponsesAdapter({
|
|
47
|
-
apiKey: 'test-key',
|
|
48
|
-
fetchImpl: async (url, options) => {
|
|
49
|
-
request = { url, body: JSON.parse(options.body) };
|
|
50
|
-
return jsonResponse({
|
|
51
|
-
id: 'resp_tools',
|
|
52
|
-
status: 'completed',
|
|
53
|
-
service_tier: 'default',
|
|
54
|
-
output: [{ type: 'message', content: [{ type: 'output_text', text: 'done' }] }],
|
|
55
|
-
usage: { input_tokens: 100, output_tokens: 10 },
|
|
56
|
-
});
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
await adapter.create({
|
|
61
|
-
model: 'gpt-6-luna',
|
|
62
|
-
input: 'research and summarize',
|
|
63
|
-
reasoningEffort: 'medium',
|
|
64
|
-
serviceTier: 'default',
|
|
65
|
-
tools: [
|
|
66
|
-
{ type: 'web_search' },
|
|
67
|
-
{ type: 'function', name: 'repository_snapshot', description: 'Snapshot repo', parameters: { type: 'object', properties: {} } },
|
|
68
|
-
],
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
assert.equal(request.url, 'https://api.openai.com/v1/responses');
|
|
72
|
-
assert.equal(request.body.reasoning.effort, 'medium');
|
|
73
|
-
assert.deepEqual(request.body.tools[0], { type: 'web_search' });
|
|
74
|
-
assert.equal(request.body.tools[1].type, 'function');
|
|
75
|
-
assert.equal(request.body.tools[1].name, 'repository_snapshot');
|
|
76
|
-
|
|
77
|
-
await assert.rejects(
|
|
78
|
-
() => adapter.create({
|
|
79
|
-
model: 'gpt-5.3-codex',
|
|
80
|
-
input: 'search',
|
|
81
|
-
reasoningEffort: 'medium',
|
|
82
|
-
serviceTier: 'default',
|
|
83
|
-
tools: [{ type: 'web_search' }],
|
|
84
|
-
}),
|
|
85
|
-
/does not declare Responses tool support: web_search/,
|
|
86
|
-
);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
test('Responses adapter preserves function call_id when returning tool output', async () => {
|
|
90
|
-
const bodies = [];
|
|
91
|
-
const adapter = createOpenAIResponsesAdapter({
|
|
92
|
-
apiKey: 'test-key',
|
|
93
|
-
fetchImpl: async (_url, options) => {
|
|
94
|
-
const body = JSON.parse(options.body);
|
|
95
|
-
bodies.push(body);
|
|
96
|
-
if (bodies.length === 1) {
|
|
97
|
-
return jsonResponse({
|
|
98
|
-
id: 'resp_calls', status: 'completed', service_tier: 'default',
|
|
99
|
-
output: [{ type: 'function_call', id: 'fc_1', call_id: 'call_abc', name: 'repository_snapshot', arguments: '{"depth":"quick"}', status: 'completed' }],
|
|
100
|
-
usage: { input_tokens: 100, output_tokens: 20 },
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
return jsonResponse({
|
|
104
|
-
id: 'resp_done', status: 'completed', service_tier: 'default',
|
|
105
|
-
output: [{ type: 'message', content: [{ type: 'output_text', text: 'complete' }] }],
|
|
106
|
-
usage: { input_tokens: 200, output_tokens: 30 },
|
|
107
|
-
});
|
|
108
|
-
},
|
|
109
|
-
});
|
|
110
|
-
const first = await adapter.create({
|
|
111
|
-
model: 'gpt-6-astra', input: 'inspect', reasoningEffort: 'low', serviceTier: 'default',
|
|
112
|
-
tools: [{ type: 'function', name: 'repository_snapshot', description: 'Snapshot repo', parameters: { type: 'object', properties: {} } }],
|
|
113
|
-
});
|
|
114
|
-
assert.equal(first.tool_calls[0].call_id, 'call_abc');
|
|
115
|
-
const second = await adapter.continueWithToolOutputs({
|
|
116
|
-
model: 'gpt-6-astra', previousResponseId: first.response_id, reasoningEffort: 'low', serviceTier: 'default',
|
|
117
|
-
toolOutputs: [{ call_id: first.tool_calls[0].call_id, output: { ok: true } }],
|
|
118
|
-
});
|
|
119
|
-
assert.equal(bodies[1].previous_response_id, 'resp_calls');
|
|
120
|
-
assert.deepEqual(bodies[1].input, [{ type: 'function_call_output', call_id: 'call_abc', output: '{"ok":true}' }]);
|
|
121
|
-
assert.equal(second.output_text, 'complete');
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
test('compaction is an explicit provider operation and has no arbitrary default wall-clock timeout', async () => {
|
|
125
|
-
let signal = 'unset';
|
|
126
|
-
let body = null;
|
|
127
|
-
const adapter = createOpenAIResponsesAdapter({
|
|
128
|
-
apiKey: 'test-key',
|
|
129
|
-
fetchImpl: async (url, options) => {
|
|
130
|
-
assert.equal(url, 'https://api.openai.com/v1/responses/compact');
|
|
131
|
-
signal = options.signal;
|
|
132
|
-
body = JSON.parse(options.body);
|
|
133
|
-
return jsonResponse({ id: 'cmp_1', object: 'response.compaction', output: [{ type: 'compaction', encrypted_content: 'opaque' }], usage: { input_tokens: 1_000, output_tokens: 100 } });
|
|
134
|
-
},
|
|
135
|
-
});
|
|
136
|
-
const compacted = await adapter.compact({ model: 'gpt-6-astra', previousResponseId: 'resp_previous' });
|
|
137
|
-
assert.equal(signal, undefined);
|
|
138
|
-
assert.equal(body.previous_response_id, 'resp_previous');
|
|
139
|
-
assert.equal(compacted.compaction_id, 'cmp_1');
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
test('OpenAI server-side compaction uses canonical policy and honors disable with previous_response_id', async () => {
|
|
143
|
-
const { getModelRecord } = await import('../src/models/index.js');
|
|
144
|
-
const bodies = [];
|
|
145
|
-
const adapter = createOpenAIResponsesAdapter({ apiKey: 'test', fetchImpl: async (_, init) => {
|
|
146
|
-
bodies.push(JSON.parse(init.body));
|
|
147
|
-
return jsonResponse({ id: 'resp_1', output: [], usage: {} });
|
|
148
|
-
} });
|
|
149
|
-
await adapter.create({ model: 'gpt-6-astra', previousResponseId: 'resp_previous', input: 'new message' });
|
|
150
|
-
assert.deepEqual(bodies[0].context_management, [{ type: 'compaction', compact_threshold: getModelRecord('gpt-6-astra').context_policy.compact_at_tokens }]);
|
|
151
|
-
assert.equal(bodies[0].input, 'new message');
|
|
152
|
-
assert.equal(bodies[0].previous_response_id, 'resp_previous');
|
|
153
|
-
await adapter.create({ model: 'gpt-6-astra', input: 'test', autoCompact: false });
|
|
154
|
-
assert.equal(bodies[1].context_management, undefined);
|
|
155
|
-
});
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import test from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import { execFileSync } from 'node:child_process';
|
|
4
|
-
import { mkdtempSync, realpathSync, writeFileSync } from 'node:fs';
|
|
5
|
-
import { tmpdir } from 'node:os';
|
|
6
|
-
import { join } from 'node:path';
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
normalizeGitRemote,
|
|
10
|
-
resolveGitContext,
|
|
11
|
-
} from '../packages/agentsam-repository/src/git-context.js';
|
|
12
|
-
import {
|
|
13
|
-
buildBridgeHeaders,
|
|
14
|
-
createBridgeClient,
|
|
15
|
-
resolveAgentSamBaseUrl,
|
|
16
|
-
} from '../src/lib/bridge-client.js';
|
|
17
|
-
import { buildContextReport } from '../src/commands/context.js';
|
|
18
|
-
|
|
19
|
-
test('normalizeGitRemote handles HTTPS and SSH GitHub remotes', () => {
|
|
20
|
-
assert.equal(normalizeGitRemote('https://github.com/SamPrimeaux/agentsam-sdk.git').repoFullName, 'SamPrimeaux/agentsam-sdk');
|
|
21
|
-
assert.equal(normalizeGitRemote('git@github.com:SamPrimeaux/AgentSamRemix.git').repoFullName, 'SamPrimeaux/AgentSamRemix');
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test('resolveGitContext derives repository identity from Git without user/workspace env', () => {
|
|
25
|
-
const root = mkdtempSync(join(tmpdir(), 'agentsam-sdk-git-'));
|
|
26
|
-
execFileSync('git', ['init'], { cwd: root, stdio: 'ignore' });
|
|
27
|
-
execFileSync('git', ['config', 'user.email', 'sdk-test@example.com'], { cwd: root });
|
|
28
|
-
execFileSync('git', ['config', 'user.name', 'SDK Test'], { cwd: root });
|
|
29
|
-
execFileSync('git', ['remote', 'add', 'origin', 'git@github.com:SamPrimeaux/example-repo.git'], { cwd: root });
|
|
30
|
-
writeFileSync(join(root, 'README.md'), '# test\n');
|
|
31
|
-
execFileSync('git', ['add', 'README.md'], { cwd: root });
|
|
32
|
-
execFileSync('git', ['commit', '-m', 'test'], { cwd: root, stdio: 'ignore' });
|
|
33
|
-
|
|
34
|
-
const ctx = resolveGitContext({ cwd: root });
|
|
35
|
-
assert.equal(ctx.repoFullName, 'SamPrimeaux/example-repo');
|
|
36
|
-
assert.match(ctx.revisionSha, /^[0-9a-f]{40}$/);
|
|
37
|
-
assert.equal(ctx.dirty, false);
|
|
38
|
-
assert.equal('workspaceId' in ctx, false);
|
|
39
|
-
assert.equal('userId' in ctx, false);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test('resolveGitContext supports an initialized repository before its first commit', () => {
|
|
43
|
-
const root = mkdtempSync(join(tmpdir(), 'agentsam-sdk-unborn-'));
|
|
44
|
-
execFileSync('git', ['init'], { cwd: root, stdio: 'ignore' });
|
|
45
|
-
writeFileSync(join(root, 'README.md'), '# unborn\n');
|
|
46
|
-
const ctx = resolveGitContext({ cwd: root });
|
|
47
|
-
assert.equal(ctx.root, realpathSync(root));
|
|
48
|
-
assert.equal(ctx.revisionSha, null);
|
|
49
|
-
assert.equal(ctx.dirty, true);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('bridge headers authenticate only the machine principal', () => {
|
|
53
|
-
const headers = buildBridgeHeaders({
|
|
54
|
-
env: {
|
|
55
|
-
AGENTSAM_BRIDGE_KEY: 'bridge_test_key',
|
|
56
|
-
AGENTSAM_USER_ID: 'should-not-leak',
|
|
57
|
-
AGENTSAM_WORKSPACE_ID: 'should-not-leak',
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
assert.equal(headers.Authorization, 'Bearer bridge_test_key');
|
|
61
|
-
assert.equal(headers['X-Bridge-Key'], 'bridge_test_key');
|
|
62
|
-
assert.equal(Object.values(headers).includes('should-not-leak'), false);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('bridge client uses shared service principal and explicit base URL', async () => {
|
|
66
|
-
let observed;
|
|
67
|
-
const client = createBridgeClient({
|
|
68
|
-
baseUrl: 'https://agent.example.test/',
|
|
69
|
-
key: 'bridge_test_key',
|
|
70
|
-
fetchImpl: async (url, options) => {
|
|
71
|
-
observed = { url, options };
|
|
72
|
-
return new Response(JSON.stringify({ ok: true }), {
|
|
73
|
-
status: 200,
|
|
74
|
-
headers: { 'Content-Type': 'application/json' },
|
|
75
|
-
});
|
|
76
|
-
},
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
assert.deepEqual(await client.post('/api/proof', { repo: 'SamPrimeaux/example-repo' }), { ok: true });
|
|
80
|
-
assert.equal(observed.url, 'https://agent.example.test/api/proof');
|
|
81
|
-
assert.equal(observed.options.headers['X-Bridge-Key'], 'bridge_test_key');
|
|
82
|
-
assert.deepEqual(JSON.parse(observed.options.body), { repo: 'SamPrimeaux/example-repo' });
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test('context report exposes repo facts and bridge readiness without secret value', () => {
|
|
86
|
-
const report = buildContextReport({
|
|
87
|
-
cwd: process.cwd(),
|
|
88
|
-
env: { AGENTSAM_BRIDGE_KEY: 'super-secret', AGENTSAM_BASE_URL: 'https://example.test' },
|
|
89
|
-
});
|
|
90
|
-
assert.equal(report.bridge.configured, true);
|
|
91
|
-
assert.equal(report.bridge.baseUrl, 'https://example.test');
|
|
92
|
-
assert.equal(JSON.stringify(report).includes('super-secret'), false);
|
|
93
|
-
assert.equal(resolveAgentSamBaseUrl({}), 'https://inneranimalmedia.com');
|
|
94
|
-
});
|
|
@@ -1,81 +0,0 @@
|
|
|
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 { execFileSync } from 'node:child_process';
|
|
6
|
-
import test from 'node:test';
|
|
7
|
-
import {
|
|
8
|
-
createProjectManifest,
|
|
9
|
-
getDefaultProfile,
|
|
10
|
-
getDefaultRuntime,
|
|
11
|
-
getDeployTarget,
|
|
12
|
-
getLocalDatabasePath,
|
|
13
|
-
getProjectName,
|
|
14
|
-
getProjectPreset,
|
|
15
|
-
getProjectRulesPath,
|
|
16
|
-
getRepositoryId,
|
|
17
|
-
portableRepositoryIdFromGit,
|
|
18
|
-
} from '../src/lib/project-config.js';
|
|
19
|
-
|
|
20
|
-
function git(cwd, args) {
|
|
21
|
-
return execFileSync('git', args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
test('portable project manifest is small and excludes runtime/account history', () => {
|
|
25
|
-
const config = createProjectManifest({
|
|
26
|
-
projectName: 'demo',
|
|
27
|
-
preset: 'cms',
|
|
28
|
-
profile: 'cms',
|
|
29
|
-
runTarget: 'local',
|
|
30
|
-
sdkVersion: '2.5.0',
|
|
31
|
-
repositoryId: 'github:owner/demo',
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
assert.equal(config.schema_version, 2);
|
|
35
|
-
assert.deepEqual(config.project, { name: 'demo' });
|
|
36
|
-
assert.equal(config.repository.id, 'github:owner/demo');
|
|
37
|
-
assert.equal(config.product.preset, 'cms');
|
|
38
|
-
assert.equal(config.defaults.profile, 'cms');
|
|
39
|
-
assert.equal(config.defaults.runtime, 'local');
|
|
40
|
-
assert.equal(config.defaults.model, 'auto');
|
|
41
|
-
assert.deepEqual(config.merkle, { enabled: true, semantic: true, persistence: 'auto' });
|
|
42
|
-
assert.equal(config.rules.file, '.agentsamrules');
|
|
43
|
-
assert.equal(getProjectRulesPath(config), '.agentsamrules');
|
|
44
|
-
assert.equal(config.knowledge.config, '.agentsam/knowledge.json');
|
|
45
|
-
assert.equal(config.local.database, '.agentsam/data/agentsam.sqlite');
|
|
46
|
-
|
|
47
|
-
const forbidden = [
|
|
48
|
-
'account_id', 'user_id', 'tenant_id', 'workspace_id', 'current_run_id', 'plan_id', 'task_id',
|
|
49
|
-
'connection_id', 'runtime_lease_id', 'latest_merkle_root', 'root_hash', 'model_history',
|
|
50
|
-
'subagent_runs', 'pty_port', 'dev_port', 'deployed_at', 'cloudflare',
|
|
51
|
-
];
|
|
52
|
-
const serialized = JSON.stringify(config);
|
|
53
|
-
for (const field of forbidden) assert.equal(serialized.includes(`"${field}"`), false, field);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
test('project config accessors keep legacy flat projects readable during migration', () => {
|
|
57
|
-
const legacy = {
|
|
58
|
-
project: 'legacy-demo',
|
|
59
|
-
lane: 'data',
|
|
60
|
-
agent: 'data',
|
|
61
|
-
run_target: 'local',
|
|
62
|
-
deploy_target: 'gcp',
|
|
63
|
-
db_path: '.agentsam/old.sqlite',
|
|
64
|
-
};
|
|
65
|
-
assert.equal(getProjectName(legacy), 'legacy-demo');
|
|
66
|
-
assert.equal(getProjectPreset(legacy), 'data');
|
|
67
|
-
assert.equal(getDefaultProfile(legacy), 'data');
|
|
68
|
-
assert.equal(getDefaultRuntime(legacy), 'local');
|
|
69
|
-
assert.equal(getDeployTarget(legacy), 'gcp');
|
|
70
|
-
assert.equal(getLocalDatabasePath(legacy), '.agentsam/old.sqlite');
|
|
71
|
-
assert.equal(getRepositoryId(legacy), null);
|
|
72
|
-
assert.equal(getProjectRulesPath(legacy), '.agentsamrules');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test('GitHub remote becomes portable repository identity when adopting an existing repo', t => {
|
|
76
|
-
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-project-config-'));
|
|
77
|
-
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
|
78
|
-
git(root, ['init', '-q']);
|
|
79
|
-
git(root, ['remote', 'add', 'origin', 'git@github.com:ExampleOrg/DemoRepo.git']);
|
|
80
|
-
assert.equal(portableRepositoryIdFromGit(root), 'github:exampleorg/demorepo');
|
|
81
|
-
});
|
|
@@ -1,44 +0,0 @@
|
|
|
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 { defaultProjectRules, findProjectRules, loadProjectRules } from '../src/lib/project-rules.js';
|
|
7
|
-
|
|
8
|
-
test('.agentsamrules behaves like a committed repo-level instruction file', t => {
|
|
9
|
-
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-rules-'));
|
|
10
|
-
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
|
11
|
-
const nested = path.join(root, 'src', 'nested');
|
|
12
|
-
fs.mkdirSync(nested, { recursive: true });
|
|
13
|
-
const content = defaultProjectRules('demo');
|
|
14
|
-
fs.writeFileSync(path.join(root, '.agentsamrules'), content);
|
|
15
|
-
|
|
16
|
-
assert.equal(findProjectRules(nested), path.join(root, '.agentsamrules'));
|
|
17
|
-
const loaded = loadProjectRules(nested);
|
|
18
|
-
assert.equal(loaded.found, true);
|
|
19
|
-
assert.equal(loaded.content, content);
|
|
20
|
-
assert.match(loaded.hash, /^sha256:[a-f0-9]{64}$/);
|
|
21
|
-
assert.equal(loaded.truncated, false);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test('project rules are deterministically bounded before entering context', t => {
|
|
25
|
-
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-rules-bound-'));
|
|
26
|
-
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
|
27
|
-
fs.writeFileSync(path.join(root, '.agentsamrules'), 'x'.repeat(200));
|
|
28
|
-
const loaded = loadProjectRules(root, { maxChars: 40 });
|
|
29
|
-
assert.equal(loaded.chars, 40);
|
|
30
|
-
assert.equal(loaded.source_chars, 200);
|
|
31
|
-
assert.equal(loaded.truncated, true);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
test('project rules discovery never leaks across the repository boundary', t => {
|
|
36
|
-
const parent = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-rules-boundary-'));
|
|
37
|
-
t.after(() => fs.rmSync(parent, { recursive: true, force: true }));
|
|
38
|
-
fs.writeFileSync(path.join(parent, '.agentsamrules'), 'parent rules\n');
|
|
39
|
-
const repo = path.join(parent, 'repo');
|
|
40
|
-
const nested = path.join(repo, 'src');
|
|
41
|
-
fs.mkdirSync(path.join(repo, '.git'), { recursive: true });
|
|
42
|
-
fs.mkdirSync(nested, { recursive: true });
|
|
43
|
-
assert.equal(findProjectRules(nested), null);
|
|
44
|
-
});
|
|
@@ -1,106 +0,0 @@
|
|
|
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 { describeProviderCredential, ensureProviderEnvProfile, resolveProviderCredential } from '../src/lib/provider-credentials.js';
|
|
7
|
-
|
|
8
|
-
function fixtureHome(t) {
|
|
9
|
-
const home = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-credentials-'));
|
|
10
|
-
t.after(() => fs.rmSync(home, { recursive: true, force: true }));
|
|
11
|
-
fs.mkdirSync(path.join(home, '.agentsam', 'env.d'), { recursive: true });
|
|
12
|
-
return home;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
test('provider credential resolver loads a secure AgentSam env file without exposing it in status', t => {
|
|
16
|
-
const home = fixtureHome(t);
|
|
17
|
-
const filename = path.join(home, '.agentsam', 'env.d', 'openai.env');
|
|
18
|
-
fs.writeFileSync(filename, 'export OPENAI_API_KEY="secret-from-file"\n', { mode: 0o600 });
|
|
19
|
-
if (process.platform !== 'win32') fs.chmodSync(filename, 0o600);
|
|
20
|
-
|
|
21
|
-
const resolved = resolveProviderCredential('openai', { env: {}, home });
|
|
22
|
-
assert.equal(resolved.configured, true);
|
|
23
|
-
assert.equal(resolved.source, 'agentsam_env_file');
|
|
24
|
-
assert.equal(resolved.value, 'secret-from-file');
|
|
25
|
-
|
|
26
|
-
const safe = describeProviderCredential('openai', { env: {}, home });
|
|
27
|
-
assert.equal(safe.configured, true);
|
|
28
|
-
assert.equal(safe.source, 'agentsam_env_file');
|
|
29
|
-
assert.equal(Object.hasOwn(safe, 'value'), false);
|
|
30
|
-
assert.doesNotMatch(JSON.stringify(safe), /secret-from-file/);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test('environment credential wins over disk fallback', t => {
|
|
34
|
-
const home = fixtureHome(t);
|
|
35
|
-
const filename = path.join(home, '.agentsam', 'env.d', 'openai.env');
|
|
36
|
-
fs.writeFileSync(filename, 'OPENAI_API_KEY=file-value\n', { mode: 0o600 });
|
|
37
|
-
if (process.platform !== 'win32') fs.chmodSync(filename, 0o600);
|
|
38
|
-
const resolved = resolveProviderCredential('openai', { env: { OPENAI_API_KEY: 'env-value' }, home });
|
|
39
|
-
assert.equal(resolved.source, 'environment');
|
|
40
|
-
assert.equal(resolved.value, 'env-value');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('AgentSam refuses provider credential files with broad POSIX permissions', { skip: process.platform === 'win32' }, t => {
|
|
44
|
-
const home = fixtureHome(t);
|
|
45
|
-
const filename = path.join(home, '.agentsam', 'env.d', 'openai.env');
|
|
46
|
-
fs.writeFileSync(filename, 'OPENAI_API_KEY=unsafe-value\n', { mode: 0o644 });
|
|
47
|
-
fs.chmodSync(filename, 0o644);
|
|
48
|
-
const resolved = resolveProviderCredential('openai', { env: {}, home });
|
|
49
|
-
assert.equal(resolved.configured, false);
|
|
50
|
-
assert.equal(resolved.error, 'permissions_too_open');
|
|
51
|
-
assert.equal(resolved.value, '');
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
test('provider env profiles create a secure reusable source loader without embedding secrets', { skip: process.platform === 'win32' }, t => {
|
|
56
|
-
const home = fixtureHome(t);
|
|
57
|
-
const openai = ensureProviderEnvProfile('openai', { home });
|
|
58
|
-
assert.equal(openai.source_command, 'source ~/.agentsam/load-agent-env.sh openai');
|
|
59
|
-
assert.equal(fs.statSync(openai.file).mode & 0o777, 0o600);
|
|
60
|
-
assert.equal(fs.statSync(openai.loader).mode & 0o777, 0o700);
|
|
61
|
-
assert.match(fs.readFileSync(openai.file, 'utf8'), /OPENAI_API_KEY=""/);
|
|
62
|
-
assert.doesNotMatch(fs.readFileSync(openai.loader, 'utf8'), /sk-|secret-/);
|
|
63
|
-
|
|
64
|
-
const cloudflare = ensureProviderEnvProfile('cloudflare', { home });
|
|
65
|
-
const source = fs.readFileSync(cloudflare.file, 'utf8');
|
|
66
|
-
assert.match(source, /CLOUDFLARE_ACCOUNT_ID=""/);
|
|
67
|
-
assert.match(source, /CLOUDFLARE_API_TOKEN=""/);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test('Cloudflare credential identity never falls back to generic ACCOUNT_ID', t => {
|
|
71
|
-
const home = fixtureHome(t);
|
|
72
|
-
const resolved = resolveProviderCredential('cloudflare', {
|
|
73
|
-
env: { CLOUDFLARE_API_TOKEN: 'token-secret', ACCOUNT_ID: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' },
|
|
74
|
-
home,
|
|
75
|
-
});
|
|
76
|
-
assert.equal(resolved.configured, true);
|
|
77
|
-
assert.equal(resolved.account_id, null);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test('Cloudflare credential status carries non-secret account identity from the provider profile', t => {
|
|
81
|
-
const home = fixtureHome(t);
|
|
82
|
-
const profile = path.join(home, '.agentsam', 'env.d', 'cloudflare.env');
|
|
83
|
-
fs.writeFileSync(profile, 'export CLOUDFLARE_ACCOUNT_ID="0123456789abcdef0123456789abcdef"\nexport CLOUDFLARE_API_TOKEN="token-secret"\n', { mode: 0o600 });
|
|
84
|
-
if (process.platform !== 'win32') fs.chmodSync(profile, 0o600);
|
|
85
|
-
const resolved = resolveProviderCredential('cloudflare', { env: {}, home });
|
|
86
|
-
assert.equal(resolved.account_id, '0123456789abcdef0123456789abcdef');
|
|
87
|
-
const safe = describeProviderCredential('cloudflare', { env: {}, home });
|
|
88
|
-
assert.equal(safe.account_id, '0123456789abcdef0123456789abcdef');
|
|
89
|
-
assert.doesNotMatch(JSON.stringify(safe), /token-secret/);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
test('Cloudflare profile account backfill never overwrites an existing token or account choice', t => {
|
|
94
|
-
const home = fixtureHome(t);
|
|
95
|
-
const profile = path.join(home, '.agentsam', 'env.d', 'cloudflare.env');
|
|
96
|
-
fs.writeFileSync(profile, 'export CLOUDFLARE_ACCOUNT_ID=""\nexport CLOUDFLARE_API_TOKEN="keep-me"\n', { mode: 0o600 });
|
|
97
|
-
ensureProviderEnvProfile('cloudflare', { home, accountId: '11111111111111111111111111111111' });
|
|
98
|
-
let source = fs.readFileSync(profile, 'utf8');
|
|
99
|
-
assert.match(source, /CLOUDFLARE_ACCOUNT_ID="11111111111111111111111111111111"/);
|
|
100
|
-
assert.match(source, /CLOUDFLARE_API_TOKEN="keep-me"/);
|
|
101
|
-
|
|
102
|
-
ensureProviderEnvProfile('cloudflare', { home, accountId: '22222222222222222222222222222222' });
|
|
103
|
-
source = fs.readFileSync(profile, 'utf8');
|
|
104
|
-
assert.match(source, /CLOUDFLARE_ACCOUNT_ID="11111111111111111111111111111111"/);
|
|
105
|
-
assert.doesNotMatch(source, /22222222222222222222222222222222/);
|
|
106
|
-
});
|
package/test/rehydrate.test.mjs
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import { createHash } from 'node:crypto';
|
|
3
|
-
import test from 'node:test';
|
|
4
|
-
import { compactConsumedToolResult, rehydrateContextRef } from '../src/context/index.js';
|
|
5
|
-
|
|
6
|
-
const sha = value => `sha256:${createHash('sha256').update(value).digest('hex')}`;
|
|
7
|
-
|
|
8
|
-
test('large consumed evidence can leave active context and later rehydrate by stable ref/hash', async () => {
|
|
9
|
-
const source = 'important evidence '.repeat(800);
|
|
10
|
-
const ref = 'tool:call_123';
|
|
11
|
-
const digest = sha(source);
|
|
12
|
-
const compacted = compactConsumedToolResult(source, { ref, hash: digest });
|
|
13
|
-
assert.equal(compacted.compacted, true);
|
|
14
|
-
assert.equal(compacted.chars, 4_000);
|
|
15
|
-
assert.equal(compacted.source_chars, source.length);
|
|
16
|
-
const adapter = { async read(requested) { assert.equal(requested, ref); return { content: source, hash: digest, kind: 'tool_result' }; } };
|
|
17
|
-
const restored = await rehydrateContextRef(ref, adapter, { expectedHash: digest, kind: 'tool_result', maxChars: 64_000 });
|
|
18
|
-
assert.equal(restored.content, source);
|
|
19
|
-
assert.equal(restored.hash, digest);
|
|
20
|
-
assert.equal(restored.truncated, false);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test('rehydration fails closed when stable source hash changed', async () => {
|
|
24
|
-
await assert.rejects(() => rehydrateContextRef('file:x', async () => ({ content: 'changed' }), { expectedHash: sha('original') }), /rehydration_hash_mismatch/);
|
|
25
|
-
});
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import fs from 'node:fs';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import test from 'node:test';
|
|
5
|
-
|
|
6
|
-
const root = path.resolve(import.meta.dirname, '..');
|
|
7
|
-
const read = (rel) => fs.readFileSync(path.join(root, rel), 'utf8');
|
|
8
|
-
|
|
9
|
-
test('release candidate metadata and public terminal vocabulary are aligned', () => {
|
|
10
|
-
const pkg = JSON.parse(read('package.json'));
|
|
11
|
-
const manifest = read('agentsam.yaml');
|
|
12
|
-
const readme = read('README.md');
|
|
13
|
-
const escapedVersion = pkg.version.replaceAll('.', '\\.');
|
|
14
|
-
|
|
15
|
-
assert.match(
|
|
16
|
-
manifest,
|
|
17
|
-
new RegExp(`packages:[\\s\\S]*?root_sdk:[\\s\\S]*?version: "${escapedVersion}"`),
|
|
18
|
-
);
|
|
19
|
-
assert.match(
|
|
20
|
-
manifest,
|
|
21
|
-
new RegExp(`release:[\\s\\S]*?root_sdk:[\\s\\S]*?target_version: "${escapedVersion}"`),
|
|
22
|
-
);
|
|
23
|
-
assert.match(manifest, /state: (candidate|published)/);
|
|
24
|
-
assert.match(manifest, /current_latest: "\d+\.\d+\.\d+"/);
|
|
25
|
-
assert.match(manifest, /verification_command: npm run verify:release/);
|
|
26
|
-
assert.doesNotMatch(manifest, /^\s*- tui\s*$/m);
|
|
27
|
-
assert.doesNotMatch(readme, /agentsam tui|CLI\/TUI/);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test('dead branded splash paths are gone and UI preview stays dev-only', () => {
|
|
31
|
-
for (const rel of ['src/ui/splash.js', 'src/ui/splash-xterm.js', 'src/commands/tui.js']) {
|
|
32
|
-
assert.equal(fs.existsSync(path.join(root, rel)), false, `${rel} should not ship`);
|
|
33
|
-
}
|
|
34
|
-
for (const rel of ['scripts/internal/ui-preview-runner.mjs', 'scripts/internal/ansi-ui-preview.mjs']) {
|
|
35
|
-
assert.equal(fs.existsSync(path.join(root, rel)), true, `${rel} should remain available to contributors`);
|
|
36
|
-
}
|
|
37
|
-
assert.equal(fs.existsSync(path.join(root, 'src/ui/runtime-activity.js')), true, 'automatic runtime activity must ship with the product CLI');
|
|
38
|
-
|
|
39
|
-
const pkg = JSON.parse(read('package.json'));
|
|
40
|
-
assert.ok(pkg.files.includes('skills'));
|
|
41
|
-
assert.equal(pkg.files.includes('scripts'), false, 'internal preview scripts must not be published');
|
|
42
|
-
});
|