From f263b541516027b59acfc903ecd6f88bf9b7fde6 Mon Sep 17 00:00:00 2001 From: Guillaume Aquilina Date: Mon, 31 Mar 2025 14:36:48 -0400 Subject: [PATCH] fix: version semver usage --- .github/workflows/.publish.yml | 4 ++ .github/workflows/tags.yml | 16 ++++-- package-lock.json | 2 +- packages/workflowai/README.md | 80 +++++++++++++++++++++++++++ packages/workflowai/package.json | 2 +- packages/workflowai/src/api/README.md | 36 ------------ packages/workflowai/src/api/types.ts | 6 +- tests/integration/agent.test.ts | 32 ++++++++++- 8 files changed, 132 insertions(+), 46 deletions(-) create mode 100644 packages/workflowai/README.md delete mode 100644 packages/workflowai/src/api/README.md diff --git a/.github/workflows/.publish.yml b/.github/workflows/.publish.yml index 195ea98..f09c854 100644 --- a/.github/workflows/.publish.yml +++ b/.github/workflows/.publish.yml @@ -15,10 +15,14 @@ on: expectedVersion: type: string required: true + env: + type: string + default: npm jobs: publish: runs-on: ubuntu-latest + environment: ${{ inputs.env }} steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/tags.yml b/.github/workflows/tags.yml index 25005ae..3df64d1 100644 --- a/.github/workflows/tags.yml +++ b/.github/workflows/tags.yml @@ -19,16 +19,22 @@ jobs: splits: runs-on: ubuntu-latest + steps: - name: Set package and version + id: set_package_and_version run: | - echo "PACKAGE=${TAG_NAME%%@*}" >> $GITHUB_ENV - echo "VERSION=${TAG_NAME#*@}" >> $GITHUB_ENV + echo "package=${TAG_NAME%%@*}" >> $GITHUB_OUTPUT + echo "version=${TAG_NAME#*@}" >> $GITHUB_OUTPUT + outputs: + package: ${{ steps.set_package_and_version.outputs.package }} + version: ${{ steps.set_package_and_version.outputs.version }} + publish: - needs: quality + needs: split uses: ./.github/workflows/.publish.yml secrets: inherit with: tag: latest - expectedVersion: ${{ env.VERSION }} - package: ${{ env.PACKAGE }} + expectedVersion: ${{ needs.split.outputs.version }} + package: ${{ needs.split.outputs.package }} diff --git a/package-lock.json b/package-lock.json index a663b0b..ddbc81a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13028,7 +13028,7 @@ }, "packages/workflowai": { "name": "@workflowai/workflowai", - "version": "1.6.4", + "version": "1.6.5", "dependencies": { "fetch-event-stream": "^0.1.5", "fetch-retry": "^6.0.0", diff --git a/packages/workflowai/README.md b/packages/workflowai/README.md new file mode 100644 index 0000000..da93341 --- /dev/null +++ b/packages/workflowai/README.md @@ -0,0 +1,80 @@ +# Javascript / Typescript SDK for WorkflowAI + +[![WorkflowAI](./examples/assets/readme-header.png)](https://workflowai.com) + +[![npm version](https://img.shields.io/npm/v/@workflowai/workflowai.svg)](https://www.npmjs.com/package/@workflowai/workflowai) +[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) + +## WorkflowAI + +[WorkflowAI](https://workflowai.com) is a low-code tool for product managers and software engineers +that makes it easier to ship features powered by AI. + +## Get Started + +1. Go to [workflowai.com](https://workflowai.com). +2. Enter your company URL, and get suggestions of AI-powered features for your product. +3. Build your first AI features in a few minutes. +4. Then go to the **Code** section to copy the code generated for Typescript. + +[![Code Section](./examples/assets/code-section.png)](https://workflowai.com/docs/agents/get-capital-info/1/code) + +## Example Syntax + +```ts +// Initialize WorkflowAI Client +import { WorkflowAI } from '@workflowai/workflowai'; + +const workflowAI = new WorkflowAI({ + // optional, defaults to process.env.WORKFLOWAI_API_KEY + // key: // Add your API key here +}); + +// Initialize Your AI agent +export interface GetCapitalInfoInput { + city: string; +} + +export interface GetCapitalInfoOutput { + country: string; + capital: string; + fun_fact: string; +} + +const getCapitalInfo = workflowAI.agent< + GetCapitalInfoInput, + GetCapitalInfoOutput +>({ + id: 'get-capital-info', + schemaId: 1, + version: '1.4', + // Cache options: + // - "auto" (default): if a previous run exists with the same version and input, and if + // the temperature is 0, the cached output is returned + // - "always": the cached output is returned when available, regardless + // of the temperature value + // - "never": the cache is never used + useCache: 'auto', +}); + +// Run Your AI agent +async function getCapitalInfoRun() { + const input: GetCapitalInfoInput = { + city: 'Wellington', + }; + + try { + const { + output, + data: { duration_seconds, cost_usd, version }, + } = await getCapitalInfo(input); + + console.log(output); + console.log('\nModel: ', version?.properties?.model); + console.log('Cost: $', cost_usd); + console.log('Latency: ', duration_seconds?.toFixed(2), 's'); + } catch (error) { + console.error('Failed to run :', error); + } +} +``` diff --git a/packages/workflowai/package.json b/packages/workflowai/package.json index f631feb..d64c181 100644 --- a/packages/workflowai/package.json +++ b/packages/workflowai/package.json @@ -1,6 +1,6 @@ { "name": "@workflowai/workflowai", - "version": "1.6.5", + "version": "1.6.6", "type": "module", "description": "WorkflowAI JS SDK", "author": "WorkflowAI", diff --git a/packages/workflowai/src/api/README.md b/packages/workflowai/src/api/README.md deleted file mode 100644 index 15b960f..0000000 --- a/packages/workflowai/src/api/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# workflowAI typed API client - -Wrapper for workflowAI's OpenAPI specs, for node or browser - -## Install - -``` -npm install @workflowai/api -``` - -## Initialize API - -```ts -import { initWorkflowAIApi } from '@workflowai/api'; - -const workflowAIApi = initWorkflowAIApi({ - apiKey: '...', // optional, defaults to process.env.WORKFLOWAI_API_KEY - apiUrl: '...', // optional, defaults to process.env.WORKFLOWAI_API_URL, then to https://api.workflowai.com - use: [], // optional, fetch middlewares -}); -``` - -## Call endpoints - -```ts -const { data: list } = await workflowAIApi.models.list(); - -console.log(list.models[0].providers[0].name); - -const { data: run } = await workflowaiApi.runs.annotate({ - run_id: '1', - score: 1, -}); - -console.log(run.scores); -``` diff --git a/packages/workflowai/src/api/types.ts b/packages/workflowai/src/api/types.ts index d709fc3..9dbf6a3 100644 --- a/packages/workflowai/src/api/types.ts +++ b/packages/workflowai/src/api/types.ts @@ -9,7 +9,11 @@ export type VersionProperties = Schema['TaskGroupProperties']; export type VersionEnvironment = 'dev' | 'staging' | 'production'; -export type VersionReference = VersionEnvironment | number | VersionProperties; +export type VersionReference = + | VersionEnvironment + | number + | string + | VersionProperties; export type RunRequest = Schema['RunRequest']; diff --git a/tests/integration/agent.test.ts b/tests/integration/agent.test.ts index ecf4125..5d41102 100644 --- a/tests/integration/agent.test.ts +++ b/tests/integration/agent.test.ts @@ -37,7 +37,7 @@ const run = workflowAI.agent< >({ id: 'animal-classification', schemaId: 4, - version: 43, + version: 'production', }); describe('run', () => { @@ -68,7 +68,35 @@ describe('run', () => { expect(req.headers.get('Authorization')).toEqual('Bearer hello'); const body = await req.json(); expect(body).toEqual({ - version: 43, + version: 'production', + stream: false, + task_input: { + animal: 'platypus', + }, + use_cache: 'auto', + }); + }); + it('allows overriding the version by a semver semver', async () => { + const run1Fixture = await readFile(fixturePath('run1.json'), 'utf-8'); + mockFetch.mockResponseOnce(run1Fixture); + + const result = await run({ animal: 'platypus' }, { version: '1.4' }); + expect(result.output).toEqual({ + is_cute: true, + is_dangerous: true, + explanation_of_reasoning: 'Plat plat', + }); + + expect(mockFetch.mock.calls.length).toEqual(1); + const req = mockFetch.mock.calls[0][0] as Request; + expect(req.url).toEqual( + 'https://run.workflowai.com/v1/_/agents/animal-classification/schemas/4/run' + ); + expect(req.method).toEqual('POST'); + expect(req.headers.get('Authorization')).toEqual('Bearer hello'); + const body = await req.json(); + expect(body).toEqual({ + version: '1.4', stream: false, task_input: { animal: 'platypus',