Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 62 additions & 23 deletions .github/workflows/auto-test-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
fetch-depth: 0

- name: Install pnpm
run: npm install -g pnpm
run: npm install -g pnpm@10.11.0

- name: Setup Node.js
uses: actions/setup-node@v4
Expand Down Expand Up @@ -84,10 +84,17 @@ jobs:
PACKAGE_NAME=$(node -p "require('./package.json').name")
PACKAGE_VERSION=$(node -p "require('./package.json').version")

echo "🚀 Publishing $PACKAGE_NAME@$PACKAGE_VERSION to test tag..."
pnpm publish --access public --tag test --no-git-checks
echo "published=true" >> $GITHUB_OUTPUT
echo "✅ Successfully published $PACKAGE_NAME to test tag"
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "🔍 Validating $PACKAGE_NAME@$PACKAGE_VERSION with publish dry-run..."
pnpm publish --dry-run --access public --tag test --no-git-checks
echo "published=false" >> $GITHUB_OUTPUT
echo "✅ Successfully validated $PACKAGE_NAME publish"
else
echo "🚀 Publishing $PACKAGE_NAME@$PACKAGE_VERSION to test tag..."
pnpm publish --access public --tag test --no-git-checks
echo "published=true" >> $GITHUB_OUTPUT
echo "✅ Successfully published $PACKAGE_NAME to test tag"
fi

# React SDK
- name: Version and build React SDK
Expand Down Expand Up @@ -126,10 +133,17 @@ jobs:
PACKAGE_NAME=$(node -p "require('./package.json').name")
PACKAGE_VERSION=$(node -p "require('./package.json').version")

echo "🚀 Publishing $PACKAGE_NAME@$PACKAGE_VERSION to test tag..."
pnpm publish --access public --tag test --no-git-checks
echo "published=true" >> $GITHUB_OUTPUT
echo "✅ Successfully published $PACKAGE_NAME to test tag"
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "🔍 Validating $PACKAGE_NAME@$PACKAGE_VERSION with publish dry-run..."
pnpm publish --dry-run --access public --tag test --no-git-checks
echo "published=false" >> $GITHUB_OUTPUT
echo "✅ Successfully validated $PACKAGE_NAME publish"
else
echo "🚀 Publishing $PACKAGE_NAME@$PACKAGE_VERSION to test tag..."
pnpm publish --access public --tag test --no-git-checks
echo "published=true" >> $GITHUB_OUTPUT
echo "✅ Successfully published $PACKAGE_NAME to test tag"
fi

# Next.js SDK
- name: Version and build Next.js SDK
Expand Down Expand Up @@ -168,10 +182,17 @@ jobs:
PACKAGE_NAME=$(node -p "require('./package.json').name")
PACKAGE_VERSION=$(node -p "require('./package.json').version")

echo "🚀 Publishing $PACKAGE_NAME@$PACKAGE_VERSION to test tag..."
pnpm publish --access public --tag test --no-git-checks
echo "published=true" >> $GITHUB_OUTPUT
echo "✅ Successfully published $PACKAGE_NAME to test tag"
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "🔍 Validating $PACKAGE_NAME@$PACKAGE_VERSION with publish dry-run..."
pnpm publish --dry-run --access public --tag test --no-git-checks
echo "published=false" >> $GITHUB_OUTPUT
echo "✅ Successfully validated $PACKAGE_NAME publish"
else
echo "🚀 Publishing $PACKAGE_NAME@$PACKAGE_VERSION to test tag..."
pnpm publish --access public --tag test --no-git-checks
echo "published=true" >> $GITHUB_OUTPUT
echo "✅ Successfully published $PACKAGE_NAME to test tag"
fi

# AIx402 SDK
- name: Version and build AIx402 SDK
Expand Down Expand Up @@ -210,10 +231,17 @@ jobs:
PACKAGE_NAME=$(node -p "require('./package.json').name")
PACKAGE_VERSION=$(node -p "require('./package.json').version")

echo "🚀 Publishing $PACKAGE_NAME@$PACKAGE_VERSION to test tag..."
pnpm publish --access public --tag test --no-git-checks
echo "published=true" >> $GITHUB_OUTPUT
echo "✅ Successfully published $PACKAGE_NAME to test tag"
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "🔍 Validating $PACKAGE_NAME@$PACKAGE_VERSION with publish dry-run..."
pnpm publish --dry-run --access public --tag test --no-git-checks
echo "published=false" >> $GITHUB_OUTPUT
echo "✅ Successfully validated $PACKAGE_NAME publish"
else
echo "🚀 Publishing $PACKAGE_NAME@$PACKAGE_VERSION to test tag..."
pnpm publish --access public --tag test --no-git-checks
echo "published=true" >> $GITHUB_OUTPUT
echo "✅ Successfully published $PACKAGE_NAME to test tag"
fi

# Echo Start CLI
- name: Version and build Echo Start CLI
Expand Down Expand Up @@ -252,15 +280,26 @@ jobs:
PACKAGE_NAME=$(node -p "require('./package.json').name")
PACKAGE_VERSION=$(node -p "require('./package.json').version")

echo "🚀 Publishing $PACKAGE_NAME@$PACKAGE_VERSION to test tag..."
pnpm publish --access public --tag test --no-git-checks
echo "published=true" >> $GITHUB_OUTPUT
echo "✅ Successfully published $PACKAGE_NAME to test tag"
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "🔍 Validating $PACKAGE_NAME@$PACKAGE_VERSION with publish dry-run..."
pnpm publish --dry-run --access public --tag test --no-git-checks
echo "published=false" >> $GITHUB_OUTPUT
echo "✅ Successfully validated $PACKAGE_NAME publish"
else
echo "🚀 Publishing $PACKAGE_NAME@$PACKAGE_VERSION to test tag..."
pnpm publish --access public --tag test --no-git-checks
echo "published=true" >> $GITHUB_OUTPUT
echo "✅ Successfully published $PACKAGE_NAME to test tag"
fi

- name: Summary
run: |
echo "✅ Test version published successfully!"
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "✅ Test version validated successfully!"
else
echo "✅ Test version published successfully!"
fi
echo "📦 Version: ${{ steps.get-version.outputs.version }}"
echo "🏷️ Tag: test"
echo ""
echo "Install with: npm install @merit-systems/echo-typescript-sdk@test"
echo "Install with: npm install @merit-systems/echo-typescript-sdk@test"
2 changes: 1 addition & 1 deletion .github/workflows/ci-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
uses: actions/checkout@v4

- name: Install pnpm
run: npm install -g pnpm
run: npm install -g pnpm@10.11.0

- name: Setup Node.js
uses: actions/setup-node@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ jobs:
uses: actions/checkout@v4

- name: Install pnpm
run: npm install -g pnpm
run: npm install -g pnpm@10.11.0

- name: Setup Node.js
uses: actions/setup-node@v4
Expand Down Expand Up @@ -378,7 +378,7 @@ jobs:
uses: actions/checkout@v4

- name: Install pnpm
run: npm install -g pnpm
run: npm install -g pnpm@10.11.0

- name: Setup Node.js
uses: actions/setup-node@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/provider-smoke-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@v4

- name: Install pnpm
run: npm install -g pnpm
run: npm install -g pnpm@10.11.0

- name: Setup Node.js
uses: actions/setup-node@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-sdks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
fetch-depth: 0

- name: Install pnpm
run: npm install -g pnpm
run: npm install -g pnpm@10.11.0

- name: Setup Node.js
uses: actions/setup-node@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ jobs:
fetch-depth: 0

- name: Install pnpm
run: npm install -g pnpm
run: npm install -g pnpm@10.11.0

- name: Setup Node.js
uses: actions/setup-node@v4
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@merit-systems/echo-next-sdk",
"version": "0.0.30",
"version": "0.0.31",
"description": "Next.js SDK for Echo",
"type": "module",
"main": "./dist/index.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@merit-systems/echo-react-sdk",
"version": "1.0.39",
"version": "1.0.40",
"description": "React SDK for Echo OAuth2 + PKCE authentication and token management",
"type": "module",
"main": "./dist/index.cjs",
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/ts/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@merit-systems/echo-typescript-sdk",
"version": "1.0.23",
"version": "1.0.24",
"description": "TypeScript SDK for Echo platform",
"type": "module",
"main": "./dist/index.cjs",
Expand Down
16 changes: 15 additions & 1 deletion packages/sdk/ts/src/supported-models/chat/anthropic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ export type AnthropicModel =
| 'claude-haiku-4-5-20251001'
| 'claude-opus-4-1-20250805'
| 'claude-opus-4-20250514'
| 'claude-opus-4-8'
| 'claude-sonnet-4-20250514'
| 'claude-sonnet-4-5-20250929';
| 'claude-sonnet-4-5-20250929'
| 'claude-sonnet-4-6';

export const AnthropicModels: SupportedModel[] = [
{
Expand Down Expand Up @@ -69,6 +71,12 @@ export const AnthropicModels: SupportedModel[] = [
output_cost_per_token: 0.000075,
provider: 'Anthropic',
},
{
model_id: 'claude-opus-4-8',
input_cost_per_token: 0.000005,
output_cost_per_token: 0.000025,
provider: 'Anthropic',
},
{
model_id: 'claude-sonnet-4-20250514',
input_cost_per_token: 0.000003,
Expand All @@ -81,4 +89,10 @@ export const AnthropicModels: SupportedModel[] = [
output_cost_per_token: 0.000015,
provider: 'Anthropic',
},
{
model_id: 'claude-sonnet-4-6',
input_cost_per_token: 0.000003,
output_cost_per_token: 0.000015,
provider: 'Anthropic',
},
];
14 changes: 14 additions & 0 deletions packages/sdk/ts/src/supported-models/chat/openrouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ export type OpenRouterModel =
| 'anthropic/claude-haiku-4.5'
| 'anthropic/claude-opus-4'
| 'anthropic/claude-opus-4.1'
| 'anthropic/claude-opus-4.8'
| 'anthropic/claude-sonnet-4'
| 'anthropic/claude-sonnet-4.5'
| 'anthropic/claude-sonnet-4.6'
| 'arcee-ai/afm-4.5b'
| 'arcee-ai/coder-large'
| 'arcee-ai/maestro-reasoning'
Expand Down Expand Up @@ -421,6 +423,12 @@ export const OpenRouterModels: SupportedModel[] = [
output_cost_per_token: 0.000075,
provider: 'OpenRouter',
},
{
model_id: 'anthropic/claude-opus-4.8',
input_cost_per_token: 0.000005,
output_cost_per_token: 0.000025,
provider: 'OpenRouter',
},
{
model_id: 'anthropic/claude-sonnet-4',
input_cost_per_token: 0.000003,
Expand All @@ -433,6 +441,12 @@ export const OpenRouterModels: SupportedModel[] = [
output_cost_per_token: 0.000015,
provider: 'OpenRouter',
},
{
model_id: 'anthropic/claude-sonnet-4.6',
input_cost_per_token: 0.000003,
output_cost_per_token: 0.000015,
provider: 'OpenRouter',
},
{
model_id: 'arcee-ai/afm-4.5b',
input_cost_per_token: 4.8e-8,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { TEST_CONFIG } from '@/config/test-config';
import { describe, test, expect } from 'vitest';
import { TEST_CLIENT_IDS, TEST_USER_API_KEYS } from '@/config/test-data';
import { echoControlApi } from '@/utils/api-client';
import { waitForBalanceUpdate } from '@/utils/balance-helpers';
import OpenAI from 'openai';

describe('API Key Client', () => {
Expand Down Expand Up @@ -39,9 +40,10 @@ describe('API Key Client', () => {
expect(chunkCount).toBeGreaterThan(0);
expect(receivedContent.length).toBeGreaterThan(0);

// await new Promise(resolve => setTimeout(resolve, 1000)); /// TODO BEN REALLY TODO: SPEED UP THE BALANCE UPDATE SO WE DON'T HAVE TO WAIT FOR 2 SECONDS

const secondBalanceCheck = await echoControlApi.getBalance(apiKey);
const secondBalanceCheck = await waitForBalanceUpdate(
() => echoControlApi.getBalance(apiKey),
balanceCheck
);
console.log('🔄 Second balance check: ', secondBalanceCheck);

expect(secondBalanceCheck.totalPaid).toBe(balanceCheck.totalPaid);
Expand Down Expand Up @@ -76,7 +78,10 @@ describe('API Key Client', () => {
expect(completion.choices).toBeDefined();
expect(completion.choices[0]?.message?.content).toBeDefined();

const secondBalanceCheck = await echoControlApi.getBalance(apiKey);
const secondBalanceCheck = await waitForBalanceUpdate(
() => echoControlApi.getBalance(apiKey),
balanceCheck
);
expect(secondBalanceCheck.totalPaid).toBe(balanceCheck.totalPaid);
expect(secondBalanceCheck.totalSpent).toBeGreaterThanOrEqual(
balanceCheck.totalSpent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
TEST_CONFIG,
echoControlApi,
TEST_CLIENT_IDS,
waitForBalanceUpdate,
} from '../../utils/index.js';
import { EchoControlApiClient } from '../../utils/api-client.js';

Expand Down Expand Up @@ -178,8 +179,9 @@ describe('Echo Data Server Client Integration Tests', () => {

accessToken = await getAccessTokenForPaidUser();

const secondBalanceCheck = await echoControlApi.getBalance(
accessToken.access_token
const secondBalanceCheck = await waitForBalanceUpdate(
() => echoControlApi.getBalance(accessToken.access_token),
balanceCheck
);
expect(secondBalanceCheck.totalPaid).toBe(balanceCheck.totalPaid);
expect(secondBalanceCheck.totalSpent).toBeGreaterThan(
Expand Down Expand Up @@ -233,8 +235,9 @@ describe('Echo Data Server Client Integration Tests', () => {

accessToken = await getAccessTokenForPaidUser();

const secondBalanceCheck = await echoControlApi.getBalance(
accessToken.access_token
const secondBalanceCheck = await waitForBalanceUpdate(
() => echoControlApi.getBalance(accessToken.access_token),
balanceCheck
);
expect(secondBalanceCheck.totalPaid).toBe(balanceCheck.totalPaid);
expect(secondBalanceCheck.totalSpent).toBeGreaterThan(
Expand Down
41 changes: 41 additions & 0 deletions packages/tests/integration/utils/balance-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
export interface BalanceSnapshot {
totalPaid: number;
totalSpent: number;
balance: number;
}

interface WaitForBalanceUpdateOptions {
timeoutMs?: number;
intervalMs?: number;
}

const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

export async function waitForBalanceUpdate(
getBalance: () => Promise<BalanceSnapshot>,
initialBalance: BalanceSnapshot,
options: WaitForBalanceUpdateOptions = {}
): Promise<BalanceSnapshot> {
const timeoutMs = options.timeoutMs ?? 5000;
const intervalMs = options.intervalMs ?? 250;
const deadline = Date.now() + timeoutMs;
let latestBalance = await getBalance();

while (Date.now() < deadline) {
if (
latestBalance.totalSpent > initialBalance.totalSpent ||
latestBalance.balance < initialBalance.balance
) {
return latestBalance;
}

await sleep(intervalMs);
latestBalance = await getBalance();
}

throw new Error(
`Balance did not update within ${timeoutMs}ms. Initial: ${JSON.stringify(
initialBalance
)}. Latest: ${JSON.stringify(latestBalance)}.`
);
}
1 change: 1 addition & 0 deletions packages/tests/integration/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from './api-client';
export * from './auth-helpers';
export * from './test-data-factory';
export * from './browser-helpers';
export * from './balance-helpers';

// Re-export configuration and test data
export * from '../config/index.js';
Expand Down
Loading
Loading