@inneranimalmedia/agentsam-sdk 2.6.7 → 2.6.8
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/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 +16 -6
- package/packages/agentsam-errors/package.json +1 -1
- 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-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 +135 -0
- package/packages/agentsam-nav/dist/browser.js +7290 -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 +7291 -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-repository/src/goap.js +13 -14
- package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +670 -0
- package/packages/agentsam-repository/src/tickets.js +15 -22
- package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +19 -8
- package/packages/connectors/cloudflare/package.json +3 -1
- package/packages/identity/tests/lane1-packed-consumer.test.mjs +1 -1
- 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 +2 -1
- package/src/cli.js +10 -1
- 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 +122 -51
- package/src/commands/package.js +530 -0
- package/src/commands/plan-ledger.js +370 -0
- package/src/commands/plan.js +183 -0
- package/src/commands/skill.js +78 -17
- package/src/knowledge/source.js +1 -1
- 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/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,57 +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 { createLocalSession, listLocalSessions, loadLocalSession, saveLocalSession, sessionTitleFromInput } from '../src/lib/local-sessions.js';
|
|
7
|
-
import { renderSessionReceipt } from '../src/commands/shell.js';
|
|
8
|
-
|
|
9
|
-
function tempHome(t) {
|
|
10
|
-
const home = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-session-home-'));
|
|
11
|
-
t.after(() => fs.rmSync(home, { recursive: true, force: true }));
|
|
12
|
-
return home;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
test('local sessions persist safe continuation, usage, cost, and an explicit title', t => {
|
|
16
|
-
const home = tempHome(t);
|
|
17
|
-
const cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-session-project-'));
|
|
18
|
-
t.after(() => fs.rmSync(cwd, { recursive: true, force: true }));
|
|
19
|
-
let session = createLocalSession({ cwd, last_input: 'Run wrangler whoami' }, { home });
|
|
20
|
-
assert.match(session.id, /^asess_[0-9a-f-]{36}$/i);
|
|
21
|
-
assert.equal(session.title, 'Agent Sam session');
|
|
22
|
-
assert.equal(session.last_input, null);
|
|
23
|
-
session = saveLocalSession({
|
|
24
|
-
...session,
|
|
25
|
-
title: sessionTitleFromInput('Run wrangler whoami'),
|
|
26
|
-
model_key: 'openai:gpt-6-astra',
|
|
27
|
-
actual_service_tier: 'fast',
|
|
28
|
-
provider_state: { provider: 'openai', previous_response_id: 'resp_123' },
|
|
29
|
-
usage_snapshot: { current_context: { input_tokens: 21_244, window_tokens: 1_050_000 } },
|
|
30
|
-
cumulative_usage: { input_tokens: 21_244, cached_input_tokens: 60_544, output_tokens: 219, reasoning_tokens: 31 },
|
|
31
|
-
total_cost_usd: 0.123456,
|
|
32
|
-
cost_breakdown_usd: { input: 0.08, cached_input: 0.01, cache_write: 0.003456, output: 0.03 },
|
|
33
|
-
status: 'paused',
|
|
34
|
-
active_elapsed_ms: 90_000,
|
|
35
|
-
active_started_at: null,
|
|
36
|
-
}, { home });
|
|
37
|
-
|
|
38
|
-
const loaded = loadLocalSession(session.id, { home, cwd });
|
|
39
|
-
assert.equal(loaded.provider_state.previous_response_id, 'resp_123');
|
|
40
|
-
assert.equal(loaded.cumulative_usage.cached_input_tokens, 60_544);
|
|
41
|
-
assert.equal(listLocalSessions({ home, cwd })[0].id, session.id);
|
|
42
|
-
assert.equal(loaded.project_root, cwd);
|
|
43
|
-
assert.equal(loaded.storage.runtime, 'sqlite');
|
|
44
|
-
assert.equal(loaded.storage.path, '.agentsam/data/agentsam.sqlite');
|
|
45
|
-
assert.equal(loaded.storage.remote, null);
|
|
46
|
-
assert.equal(loaded.storage.capabilities.local_only, true);
|
|
47
|
-
assert.equal(fs.existsSync(path.join(home, '.agentsam', 'sessions', `${session.id}.json`)), false);
|
|
48
|
-
assert.equal(fs.existsSync(path.join(cwd, '.agentsam', 'data', 'agentsam.sqlite')), true);
|
|
49
|
-
|
|
50
|
-
const receipt = renderSessionReceipt(loaded);
|
|
51
|
-
assert.match(receipt, /Token usage: total=21,463 input=21,244 \(\+ 60,544 cached\) output=219 reasoning=31/);
|
|
52
|
-
assert.match(receipt, /Spent: \$0\.1235/);
|
|
53
|
-
assert.match(receipt, /Elapsed: 1m 30s/);
|
|
54
|
-
assert.match(receipt, /Cost breakdown: input \$0\.0800 · cached \$0\.0100 · cache write \$0\.003456 · output \$0\.0300/);
|
|
55
|
-
assert.match(receipt, new RegExp(`agentsam resume ${session.id}`));
|
|
56
|
-
assert.match(receipt, /Run wrangler whoami/);
|
|
57
|
-
});
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import os from 'node:os';
|
|
4
|
-
import fs from 'node:fs';
|
|
5
|
-
import { describe, it } from 'node:test';
|
|
6
|
-
import { fileURLToPath } from 'node:url';
|
|
7
|
-
import {
|
|
8
|
-
DEPLOY_INPUT_GLOBS,
|
|
9
|
-
loadOptionalCloudflareEnv,
|
|
10
|
-
resolveLocalStudioDeployable,
|
|
11
|
-
wranglerDeployCommand,
|
|
12
|
-
isLocalStudioCheckout,
|
|
13
|
-
runLocalStudioDeploy,
|
|
14
|
-
} from '../src/lib/deploy/local-studio.js';
|
|
15
|
-
import { productionDeployBlockedReason } from '../src/lib/deploy/git-guard.js';
|
|
16
|
-
|
|
17
|
-
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
18
|
-
|
|
19
|
-
describe('local-studio deploy resolver', () => {
|
|
20
|
-
it('resolves apps/local-studio + backend/wrangler.jsonc from the repo', () => {
|
|
21
|
-
const target = resolveLocalStudioDeployable(root);
|
|
22
|
-
assert.equal(target.provider, 'cloudflare');
|
|
23
|
-
assert.equal(target.app, 'local-studio');
|
|
24
|
-
assert.equal(path.basename(path.dirname(target.wranglerConfig)), 'backend');
|
|
25
|
-
assert.deepEqual(target.wranglerArgs, ['deploy', '-c', 'backend/wrangler.jsonc']);
|
|
26
|
-
assert.equal(isLocalStudioCheckout(root), true);
|
|
27
|
-
const cmd = wranglerDeployCommand(target, { dryRun: true });
|
|
28
|
-
assert.equal(cmd.bin, process.platform === 'win32' ? 'npx.cmd' : 'npx');
|
|
29
|
-
assert.equal(cmd.cwd, target.appRoot);
|
|
30
|
-
assert.deepEqual(cmd.args, ['wrangler', 'deploy', '-c', 'backend/wrangler.jsonc', '--dry-run']);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('fingerprints the cloudflare connector package', () => {
|
|
34
|
-
assert.equal(DEPLOY_INPUT_GLOBS.includes('packages/connectors/cloudflare'), true);
|
|
35
|
-
assert.equal(DEPLOY_INPUT_GLOBS.includes('apps/local-studio'), true);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('treats missing .env.cloudflare as optional', () => {
|
|
39
|
-
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'cf-env-'));
|
|
40
|
-
const loaded = loadOptionalCloudflareEnv(tmp);
|
|
41
|
-
assert.equal(loaded.loaded, false);
|
|
42
|
-
assert.deepEqual(loaded.vars, {});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('plan does not invoke wrangler', async () => {
|
|
46
|
-
const result = await runLocalStudioDeploy({ cwd: root, planOnly: true, execute: false });
|
|
47
|
-
assert.equal(result.plan.provider, 'cloudflare');
|
|
48
|
-
assert.equal(result.plan.wranglerConfig, 'apps/local-studio/backend/wrangler.jsonc');
|
|
49
|
-
assert.equal(result.plan.genericRootDeploy, false);
|
|
50
|
-
assert.equal(result.receipt.plan, true);
|
|
51
|
-
assert.equal(result.receipt.promoted, false);
|
|
52
|
-
assert.equal(result.receipt.wranglerConfig, 'apps/local-studio/backend/wrangler.jsonc');
|
|
53
|
-
assert.equal(result.receipt.hostname, 'agentsam.inneranimalmedia.com');
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('blocks production deploys from feat branches', () => {
|
|
57
|
-
const reason = productionDeployBlockedReason({
|
|
58
|
-
ok: true,
|
|
59
|
-
branch: 'feat/cloudflare-connector-deploy-control',
|
|
60
|
-
detached: false,
|
|
61
|
-
head: 'aaa',
|
|
62
|
-
originMain: 'aaa',
|
|
63
|
-
dirty: false,
|
|
64
|
-
tmpCheckout: false,
|
|
65
|
-
repoRoot: root,
|
|
66
|
-
});
|
|
67
|
-
assert.match(reason, /feat\/cloudflare-connector-deploy-control/);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('allows production only when HEAD is a clean origin/main', () => {
|
|
71
|
-
const reason = productionDeployBlockedReason({
|
|
72
|
-
ok: true,
|
|
73
|
-
branch: 'main',
|
|
74
|
-
detached: false,
|
|
75
|
-
head: 'abc',
|
|
76
|
-
originMain: 'abc',
|
|
77
|
-
dirty: false,
|
|
78
|
-
tmpCheckout: false,
|
|
79
|
-
repoRoot: root,
|
|
80
|
-
});
|
|
81
|
-
assert.equal(reason, null);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import http from 'node:http';
|
|
3
|
-
import { describe, it } from 'node:test';
|
|
4
|
-
import { createLoopbackCallbackListener } from '../src/lib/auth.js';
|
|
5
|
-
|
|
6
|
-
describe('loopback OAuth callback', () => {
|
|
7
|
-
it('settles waitForCallback when browser hits success page', async () => {
|
|
8
|
-
const state = 'test_state_abc';
|
|
9
|
-
const listener = await createLoopbackCallbackListener({
|
|
10
|
-
state,
|
|
11
|
-
host: '127.0.0.1',
|
|
12
|
-
timeoutMs: 5_000,
|
|
13
|
-
});
|
|
14
|
-
try {
|
|
15
|
-
const wait = listener.waitForCallback();
|
|
16
|
-
const port = new URL(listener.redirectUri).port;
|
|
17
|
-
const res = await fetch(
|
|
18
|
-
`http://127.0.0.1:${port}/callback?state=${state}&code=auth_code_xyz`,
|
|
19
|
-
);
|
|
20
|
-
assert.equal(res.status, 200);
|
|
21
|
-
const html = await res.text();
|
|
22
|
-
assert.match(html, /Authentication complete/);
|
|
23
|
-
const callback = await wait;
|
|
24
|
-
assert.equal(callback.code, 'auth_code_xyz');
|
|
25
|
-
assert.equal(callback.state, state);
|
|
26
|
-
} finally {
|
|
27
|
-
await listener.close();
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('does not settle on code-less probe so a later redirect can succeed', async () => {
|
|
32
|
-
const state = 'test_state_probe';
|
|
33
|
-
const listener = await createLoopbackCallbackListener({
|
|
34
|
-
state,
|
|
35
|
-
host: '127.0.0.1',
|
|
36
|
-
timeoutMs: 5_000,
|
|
37
|
-
});
|
|
38
|
-
try {
|
|
39
|
-
const wait = listener.waitForCallback();
|
|
40
|
-
const port = new URL(listener.redirectUri).port;
|
|
41
|
-
const probe = await fetch(`http://127.0.0.1:${port}/callback?state=${state}`);
|
|
42
|
-
assert.equal(probe.status, 400);
|
|
43
|
-
const res = await fetch(
|
|
44
|
-
`http://127.0.0.1:${port}/callback?state=${state}&code=real_code`,
|
|
45
|
-
);
|
|
46
|
-
assert.equal(res.status, 200);
|
|
47
|
-
const callback = await wait;
|
|
48
|
-
assert.equal(callback.code, 'real_code');
|
|
49
|
-
} finally {
|
|
50
|
-
await listener.close();
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
});
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import { test } from 'node:test';
|
|
3
|
-
import { renderExplorer, renderSummary, safeText, treeRows } from '../src/ui/merkle/render.js';
|
|
4
|
-
|
|
5
|
-
const hash = 'sha256:' + 'a'.repeat(64);
|
|
6
|
-
const entries = [
|
|
7
|
-
{ path: '', type: 'directory', hash },
|
|
8
|
-
{ path: 'src', type: 'directory', hash },
|
|
9
|
-
{ path: 'src/app.js', type: 'file', hash, size: 12 },
|
|
10
|
-
{ path: 'bad\x1b[2J.txt', type: 'file', hash, size: 1 },
|
|
11
|
-
];
|
|
12
|
-
const tree = { rootPath: '/tmp/project', rootHash: hash, stats: { files: 2, symlinks: 0, bytes: 13 }, entries };
|
|
13
|
-
test('terminal rendering escapes file control sequences and fits a mobile terminal', () => {
|
|
14
|
-
const state = { result: { title: 'Merkle root', tree }, expanded: new Set(['', 'src']), selected: 0 };
|
|
15
|
-
const frame = renderExplorer(state, { columns: 40, rows: 24 });
|
|
16
|
-
assert.ok(!frame.includes('\x1b'));
|
|
17
|
-
assert.ok(frame.includes('\\u001b'));
|
|
18
|
-
assert.ok(frame.split('\r\n').every((line) => [...line].length <= 39));
|
|
19
|
-
assert.ok(frame.split('\r\n').length <= 23);
|
|
20
|
-
assert.ok(frame.replaceAll('\r\n', '').includes(hash), 'full selected hash wraps without truncation');
|
|
21
|
-
assert.equal(safeText('a\nb'), 'a\\u000ab');
|
|
22
|
-
assert.ok(!renderSummary({ title: 'Merkle', tree }, { inspect: true }).includes('\x1b'));
|
|
23
|
-
});
|
|
24
|
-
test('explorer expands folders and can filter unchanged branches', () => {
|
|
25
|
-
const result = { title: 'Verify', before: tree, tree: { ...tree, entries: entries.map((entry) => entry.path === 'src/app.js' ? { ...entry, hash: 'sha256:' + 'b'.repeat(64) } : entry) } };
|
|
26
|
-
assert.ok(!treeRows(result, new Set([''])).some((entry) => entry.path === 'src/app.js'));
|
|
27
|
-
assert.ok(treeRows(result, new Set(['', 'src'])).some((entry) => entry.path === 'src/app.js'));
|
|
28
|
-
const changed = treeRows({ ...result, tree: { ...result.tree, entries: result.tree.entries.map((entry) => entry.type === 'directory' ? { ...entry, hash: 'sha256:' + 'b'.repeat(64) } : entry) } }, new Set(['', 'src']), true);
|
|
29
|
-
assert.ok(changed.some((entry) => entry.path === 'src/app.js'));
|
|
30
|
-
assert.ok(!changed.some((entry) => entry.path.startsWith('bad')));
|
|
31
|
-
});
|
package/test/mini.test.mjs
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import { test } from 'node:test';
|
|
3
|
-
import fs from 'node:fs';
|
|
4
|
-
import http from 'node:http';
|
|
5
|
-
import net from 'node:net';
|
|
6
|
-
import os from 'node:os';
|
|
7
|
-
import path from 'node:path';
|
|
8
|
-
import { execFileSync, spawn } from 'node:child_process';
|
|
9
|
-
import { once } from 'node:events';
|
|
10
|
-
import { fileURLToPath } from 'node:url';
|
|
11
|
-
import { createMini, MINI_TEMPLATES, startMiniPreview } from '../src/lib/mini/index.js';
|
|
12
|
-
|
|
13
|
-
const cli = fileURLToPath(new URL('../src/cli.js', import.meta.url));
|
|
14
|
-
function fixture(t) {
|
|
15
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-mini-test-'));
|
|
16
|
-
t.after(() => fs.rmSync(dir, { recursive: true, force: true }));
|
|
17
|
-
return dir;
|
|
18
|
-
}
|
|
19
|
-
function request(url, pathname, { method = 'GET', headers = {} } = {}) {
|
|
20
|
-
return new Promise((resolve, reject) => {
|
|
21
|
-
const req = http.request(url + pathname, { method, headers }, (res) => {
|
|
22
|
-
let body = '';
|
|
23
|
-
res.on('data', (chunk) => { body += chunk; });
|
|
24
|
-
res.on('end', () => resolve({ status: res.statusCode, headers: res.headers, body }));
|
|
25
|
-
});
|
|
26
|
-
req.on('error', reject);
|
|
27
|
-
req.end();
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
test('all mini starters are portable files; existing projects are never overwritten', (t) => {
|
|
32
|
-
const cwd = fixture(t);
|
|
33
|
-
for (const template of Object.keys(MINI_TEMPLATES)) {
|
|
34
|
-
const { root } = createMini({ name: template, template, cwd });
|
|
35
|
-
const html = fs.readFileSync(path.join(root, 'public/index.html'), 'utf8');
|
|
36
|
-
assert.ok(html.includes('<title>' + template));
|
|
37
|
-
assert.ok(!html.includes('{{NAME}}'));
|
|
38
|
-
execFileSync(process.execPath, ['--check', path.join(root, 'public/app.js')]);
|
|
39
|
-
assert.ok(fs.existsSync(path.join(root, 'public/style.css')));
|
|
40
|
-
assert.ok(!fs.existsSync(path.join(root, 'node_modules')));
|
|
41
|
-
assert.ok(!fs.existsSync(path.join(root, 'package.json')));
|
|
42
|
-
assert.throws(() => createMini({ name: template, template, cwd }), /EEXIST/);
|
|
43
|
-
assert.equal(fs.readFileSync(path.join(root, 'public/index.html'), 'utf8'), html);
|
|
44
|
-
}
|
|
45
|
-
assert.throws(() => createMini({ name: '../escape', cwd }), /name/);
|
|
46
|
-
assert.throws(() => createMini({ name: 'bad', template: 'constructor', cwd }), /Unknown template/);
|
|
47
|
-
assert.ok(!fs.existsSync(path.join(cwd, 'bad')));
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test('preview reflects edits and protects files outside public/', async (t) => {
|
|
51
|
-
const cwd = fixture(t);
|
|
52
|
-
const { root } = createMini({ name: 'preview-test', cwd });
|
|
53
|
-
fs.writeFileSync(path.join(root, 'secret.txt'), 'private-project-file');
|
|
54
|
-
fs.writeFileSync(path.join(root, 'public/.env'), 'private-dotfile');
|
|
55
|
-
fs.writeFileSync(path.join(root, 'public/.secret.txt'), 'private-dotfile');
|
|
56
|
-
fs.symlinkSync(path.join(root, 'public/.secret.txt'), path.join(root, 'public/alias.txt'));
|
|
57
|
-
fs.symlinkSync(path.join(root, 'secret.txt'), path.join(root, 'public/linked.txt'));
|
|
58
|
-
const preview = await startMiniPreview({ root, timeoutSeconds: 30 });
|
|
59
|
-
t.after(() => preview.stop());
|
|
60
|
-
const home = await request(preview.url, '/');
|
|
61
|
-
assert.equal(home.status, 200);
|
|
62
|
-
assert.match(home.body, /focus timer/i);
|
|
63
|
-
assert.equal(home.headers['cache-control'], 'no-store');
|
|
64
|
-
assert.equal((await request(preview.url, '/app.js')).status, 200);
|
|
65
|
-
assert.equal((await request(preview.url, '/', { method: 'HEAD' })).body, '');
|
|
66
|
-
assert.equal((await request(preview.url, '/', { method: 'POST' })).status, 405);
|
|
67
|
-
for (const target of ['/mini.json', '/secret.txt', '/.env', '/%2eenv', '/linked.txt', '/alias.txt', '/%2e%2e/secret.txt', '/missing', '/%5csecret.txt']) {
|
|
68
|
-
assert.equal((await request(preview.url, target)).status, 404, target);
|
|
69
|
-
}
|
|
70
|
-
assert.equal((await request(preview.url, '/%ZZ')).status, 400);
|
|
71
|
-
assert.equal((await request(preview.url, '/', { headers: { Host: 'example.com' } })).status, 403);
|
|
72
|
-
assert.equal((await request(preview.url, '/', { headers: { Origin: 'https://example.com' } })).status, 403);
|
|
73
|
-
fs.writeFileSync(path.join(root, 'public/index.html'), '<h1>Edited locally</h1>');
|
|
74
|
-
assert.equal((await request(preview.url, '/')).body, '<h1>Edited locally</h1>');
|
|
75
|
-
await preview.stop();
|
|
76
|
-
await assert.rejects(request(preview.url, '/'));
|
|
77
|
-
assert.ok(fs.existsSync(root));
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test('preview refuses a public directory that points outside the project', async (t) => {
|
|
81
|
-
const cwd = fixture(t);
|
|
82
|
-
const { root } = createMini({ name: 'symlink-test', cwd });
|
|
83
|
-
fs.rmSync(path.join(root, 'public'), { recursive: true });
|
|
84
|
-
fs.symlinkSync(cwd, path.join(root, 'public'), 'dir');
|
|
85
|
-
await assert.rejects(startMiniPreview({ root }), /public\/ must be inside/);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test('timeout shuts the listener and open connections, retaining files', async (t) => {
|
|
89
|
-
const cwd = fixture(t);
|
|
90
|
-
const { root } = createMini({ name: 'timeout-test', cwd });
|
|
91
|
-
const preview = await startMiniPreview({ root, timeoutSeconds: 1 });
|
|
92
|
-
t.after(() => preview.stop());
|
|
93
|
-
const socket = net.connect(Number(new URL(preview.url).port), '127.0.0.1');
|
|
94
|
-
t.after(() => socket.destroy());
|
|
95
|
-
const socketClosed = once(socket, 'close');
|
|
96
|
-
await once(socket, 'connect');
|
|
97
|
-
assert.equal(await preview.closed, 'timeout');
|
|
98
|
-
await socketClosed;
|
|
99
|
-
await preview.stop();
|
|
100
|
-
await assert.rejects(request(preview.url, '/'));
|
|
101
|
-
assert.ok(fs.existsSync(path.join(root, 'mini.json')));
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
test('CLI write-only exits, and invalid inputs create no project', (t) => {
|
|
105
|
-
const cwd = fixture(t);
|
|
106
|
-
const output = execFileSync(process.execPath, [cli, 'mini', 'files-only', '--write-only'], { cwd, encoding: 'utf8', timeout: 5000 });
|
|
107
|
-
assert.match(output, /Files only/);
|
|
108
|
-
assert.doesNotMatch(output, /Auto-stop in/);
|
|
109
|
-
assert.ok(fs.existsSync(path.join(cwd, 'files-only/mini.json')));
|
|
110
|
-
for (const args of [['bad', '--timeout', '0'], ['bad', '--port', '65536'], ['bad', '--typo'], ['bad', '--template'], ['bad', '--open', '--write-only']]) {
|
|
111
|
-
assert.throws(() => execFileSync(process.execPath, [cli, 'mini', ...args], { cwd, stdio: 'pipe', timeout: 5000 }));
|
|
112
|
-
assert.ok(!fs.existsSync(path.join(cwd, 'bad')));
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
for (const signal of ['SIGINT', 'SIGTERM']) {
|
|
117
|
-
test(`CLI ${signal} closes preview without deleting the mini`, { timeout: 10000 }, async (t) => {
|
|
118
|
-
const cwd = fixture(t);
|
|
119
|
-
const { root } = createMini({ name: 'signal-test', cwd });
|
|
120
|
-
const child = spawn(process.execPath, [cli, 'mini', 'preview', root, '--timeout', '30'], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
121
|
-
t.after(() => { if (child.exitCode === null && child.signalCode === null) child.kill('SIGKILL'); });
|
|
122
|
-
const exited = once(child, 'exit');
|
|
123
|
-
const url = await new Promise((resolve, reject) => {
|
|
124
|
-
let output = '';
|
|
125
|
-
child.once('error', reject);
|
|
126
|
-
child.once('exit', () => reject(new Error('Preview exited before printing its URL')));
|
|
127
|
-
child.stdout.on('data', (chunk) => {
|
|
128
|
-
output += chunk;
|
|
129
|
-
const match = output.match(/Preview: (http:\/\/127\.0\.0\.1:\d+)/);
|
|
130
|
-
if (match) resolve(match[1]);
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
assert.equal((await request(url, '/')).status, 200);
|
|
134
|
-
child.kill(signal);
|
|
135
|
-
const [code] = await exited;
|
|
136
|
-
assert.equal(code, 0);
|
|
137
|
-
await assert.rejects(request(url, '/'));
|
|
138
|
-
assert.ok(fs.existsSync(path.join(root, 'public/index.html')));
|
|
139
|
-
});
|
|
140
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import test from 'node:test';
|
|
3
|
-
import { calculateModelCost, getModelRecord, mergeModelReference } from '../src/models/index.js';
|
|
4
|
-
|
|
5
|
-
test('Astra catalog separates technical window, reasoning controls, service tiers, and economics', () => {
|
|
6
|
-
const model = getModelRecord('gpt-6-astra');
|
|
7
|
-
assert.ok(model);
|
|
8
|
-
assert.equal(model.context_window, 1_050_000);
|
|
9
|
-
assert.equal(model.max_output_tokens, 128_000);
|
|
10
|
-
assert.deepEqual(model.reasoning_efforts, ['low', 'medium', 'high', 'xhigh', 'max']);
|
|
11
|
-
assert.deepEqual(model.service_tiers, ['default', 'fast', 'flex']);
|
|
12
|
-
assert.equal(model.context_policy.target_input_tokens, 120_000);
|
|
13
|
-
assert.equal(model.context_policy.compact_at_tokens, 180_000);
|
|
14
|
-
assert.equal(model.context_policy.max_normal_input_tokens, 250_000);
|
|
15
|
-
assert.equal(model.context_policy.pricing_threshold_tokens, 272_000);
|
|
16
|
-
assert.equal(model.batch.interactive, false);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test('cost calculation applies the long-context threshold to the full request only after crossing it', () => {
|
|
20
|
-
const atBoundary = calculateModelCost('gpt-6-astra', { input_tokens: 272_000, output_tokens: 10_000 });
|
|
21
|
-
assert.equal(atBoundary.threshold_applied, null);
|
|
22
|
-
assert.equal(atBoundary.rates_per_million.input, 10);
|
|
23
|
-
assert.equal(atBoundary.rates_per_million.output, 50);
|
|
24
|
-
|
|
25
|
-
const crossed = calculateModelCost('gpt-6-astra', { input_tokens: 272_001, output_tokens: 10_000 });
|
|
26
|
-
assert.equal(crossed.threshold_applied.input_tokens_gt, 272_000);
|
|
27
|
-
assert.equal(crossed.rates_per_million.input, 20);
|
|
28
|
-
assert.equal(crossed.rates_per_million.output, 75);
|
|
29
|
-
assert.ok(crossed.total_usd > atBoundary.total_usd);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test('service tier and cache pricing stay explicit rather than hidden in prompts', () => {
|
|
33
|
-
const usage = { input_tokens: 100_000, cached_input_tokens: 80_000, cache_write_tokens: 10_000, output_tokens: 20_000 };
|
|
34
|
-
const standard = calculateModelCost('gpt-6-astra', usage, { serviceTier: 'default' });
|
|
35
|
-
const fast = calculateModelCost('gpt-6-astra', usage, { serviceTier: 'fast' });
|
|
36
|
-
const flex = calculateModelCost('gpt-6-astra', usage, { serviceTier: 'flex' });
|
|
37
|
-
const batch = calculateModelCost('gpt-6-astra', usage, { serviceTier: 'batch' });
|
|
38
|
-
assert.equal(fast.total_usd, standard.total_usd * 2);
|
|
39
|
-
assert.equal(flex.total_usd, standard.total_usd * 0.5);
|
|
40
|
-
assert.equal(batch.total_usd, standard.total_usd * 0.5);
|
|
41
|
-
assert.equal(standard.rates_per_million.cached_input, 1);
|
|
42
|
-
assert.equal(standard.rates_per_million.cache_write, 12.5);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
test('GPT-6 Luna reference hydrates a stale provider-verified snapshot without changing availability authority', () => {
|
|
47
|
-
const merged = mergeModelReference({
|
|
48
|
-
model_key: 'openai:gpt-6-luna',
|
|
49
|
-
provider: 'openai',
|
|
50
|
-
provider_model_id: 'gpt-6-luna',
|
|
51
|
-
availability: 'available',
|
|
52
|
-
availability_source: 'provider_api',
|
|
53
|
-
context_window: null,
|
|
54
|
-
context_window_source: 'unknown',
|
|
55
|
-
max_output_tokens: null,
|
|
56
|
-
max_output_tokens_source: 'unknown',
|
|
57
|
-
reasoning_efforts: ['auto'],
|
|
58
|
-
service_tiers: ['default'],
|
|
59
|
-
capabilities: { responses: true },
|
|
60
|
-
});
|
|
61
|
-
assert.equal(merged.availability, 'available');
|
|
62
|
-
assert.equal(merged.availability_source, 'provider_api');
|
|
63
|
-
assert.equal(merged.context_window, 1_050_000);
|
|
64
|
-
assert.equal(merged.context_window_source, 'sdk_reference');
|
|
65
|
-
assert.equal(merged.max_output_tokens, 128_000);
|
|
66
|
-
assert.deepEqual(merged.reasoning_efforts, ['none', 'low', 'medium', 'high', 'xhigh', 'max']);
|
|
67
|
-
assert.equal(merged.default_reasoning_effort, 'medium');
|
|
68
|
-
assert.equal(merged.capabilities.responses, true);
|
|
69
|
-
assert.equal(merged.capabilities.function_calling, true);
|
|
70
|
-
});
|