Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release: 4.13.0 #389

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
2 changes: 1 addition & 1 deletion .github/workflows/create-releases.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ jobs:
run: |
bash ./bin/publish-npm
env:
NPM_TOKEN: ${{ secrets.OPENAI_NPM_TOKEN }}
NPM_TOKEN: ${{ secrets.OPENAI_NPM_TOKEN || secrets.NPM_TOKEN }}
2 changes: 1 addition & 1 deletion .github/workflows/publish-npm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ jobs:
run: |
bash ./bin/publish-npm
env:
NPM_TOKEN: ${{ secrets.OPENAI_NPM_TOKEN }}
NPM_TOKEN: ${{ secrets.OPENAI_NPM_TOKEN || secrets.NPM_TOKEN }}
2 changes: 1 addition & 1 deletion .github/workflows/release-doctor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ jobs:
bash ./bin/check-release-environment
env:
STAINLESS_API_KEY: ${{ secrets.STAINLESS_API_KEY }}
NPM_TOKEN: ${{ secrets.OPENAI_NPM_TOKEN }}
NPM_TOKEN: ${{ secrets.OPENAI_NPM_TOKEN || secrets.NPM_TOKEN }}
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "4.12.4"
".": "4.13.0"
}
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## 4.13.0 (2023-10-22)

Full Changelog: [v4.12.4...v4.13.0](https://github.com/openai/openai-node/compare/v4.12.4...v4.13.0)

### Features

* **api:** add embeddings encoding_format ([#390](https://github.com/openai/openai-node/issues/390)) ([cf70dea](https://github.com/openai/openai-node/commit/cf70deaba1426786aba9b938d280c61aeb516e34))
* handle 204 No Content gracefully ([#391](https://github.com/openai/openai-node/issues/391)) ([2dd005c](https://github.com/openai/openai-node/commit/2dd005c1c497605036d3524f19d130b3fc5f8d8b))

## 4.12.4 (2023-10-17)

Full Changelog: [v4.12.3...v4.12.4](https://github.com/openai/openai-node/compare/v4.12.3...v4.12.4)
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ npm install --save openai
yarn add openai
```

You can import in Deno via:

```ts
import OpenAI from 'https://raw.githubusercontent.com/openai/openai-node/v4.12.4-deno/mod.ts';
```

## Usage

The full API of this library can be found in [api.md file](https://github.com/openai/openai-node/blob/master/api.md). The code below shows how to get started using the chat completions API.
Expand Down
25 changes: 25 additions & 0 deletions build-deno
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash

set -exuo pipefail

rm -rf deno; mkdir deno
cp -rp src/* README.md deno
rm deno/_shims/auto/*-node.ts
for dir in deno/_shims deno/_shims/auto; do
rm "${dir}"/*.{d.ts,js,mjs}
for file in "${dir}"/*-deno.ts; do
mv -- "$file" "${file%-deno.ts}.ts"
done
done
for file in LICENSE CHANGELOG.md; do
if [ -e "${file}" ]; then cp "${file}" deno; fi
done
npm exec ts-node -- scripts/denoify.ts
deno fmt deno
deno check deno/mod.ts
if [ -e deno_tests ]; then
deno test deno_tests --allow-env
fi

# make sure that nothing crashes when we load the Deno module
(cd deno && deno run mod.ts)
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "openai",
"version": "4.12.4",
"version": "4.13.0",
"description": "Client library for the OpenAI API",
"author": "OpenAI <support@openai.com>",
"types": "dist/index.d.ts",
Expand Down Expand Up @@ -83,7 +83,8 @@
"format": "prettier --write --cache --cache-strategy metadata . !dist",
"tsn": "ts-node -r tsconfig-paths/register",
"lint": "eslint --ext ts,js .",
"fix": "eslint --fix --ext ts,js ."
"fix": "eslint --fix --ext ts,js .",
"postpublish": "bash scripts/git-publish-deno.sh"
},
"dependencies": {
"@types/node": "^18.11.18",
Expand Down
229 changes: 229 additions & 0 deletions scripts/denoify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
import path from 'path';
import * as tm from 'ts-morph';
import { name as pkgName } from '../package.json';
import fs from 'fs';

const rootDir = path.resolve(__dirname, '..');
const denoDir = path.join(rootDir, 'deno');
const tsConfigFilePath = path.join(rootDir, 'tsconfig.deno.json');

async function denoify() {
const project = new tm.Project({ tsConfigFilePath });

for (const file of project.getSourceFiles()) {
if (!file.getFilePath().startsWith(denoDir + '/')) continue;

let addedBuffer = false,
addedProcess = false;
file.forEachDescendant((node) => {
switch (node.getKind()) {
case tm.ts.SyntaxKind.ExportDeclaration: {
const decl: tm.ExportDeclaration = node as any;
if (decl.isTypeOnly()) return;
for (const named of decl.getNamedExports()) {
// Convert `export { Foo } from './foo.ts'`
// to `export { type Foo } from './foo.ts'`
// if `./foo.ts` only exports types for `Foo`
if (!named.isTypeOnly() && !hasValueDeclarations(named)) {
named.replaceWithText(`type ${named.getText()}`);
}
}
break;
}
case tm.ts.SyntaxKind.ImportEqualsDeclaration: {
const decl: tm.ImportEqualsDeclaration = node as any;
if (decl.isTypeOnly()) return;

const ref = decl.getModuleReference();
if (!hasValueDeclarations(ref)) {
const params = isBuiltinType(ref.getType()) ? [] : ref.getType().getTypeArguments();
if (params.length) {
const paramsStr = params.map((p: tm.TypeParameter) => p.getText()).join(', ');
const bindingsStr = params
.map((p: tm.TypeParameter) => p.getSymbol()?.getName() || p.getText())
.join(', ');
decl.replaceWithText(
`export type ${decl.getName()}<${paramsStr}> = ${ref.getText()}<${bindingsStr}>`,
);
} else {
decl.replaceWithText(`export type ${decl.getName()} = ${ref.getText()}`);
}
}
break;
}
case tm.ts.SyntaxKind.Identifier: {
const id = node as tm.Identifier;
if (!addedBuffer && id.getText() === 'Buffer') {
addedBuffer = true;
file?.addVariableStatement({
declarations: [
{
name: 'Buffer',
type: 'any',
},
],
hasDeclareKeyword: true,
});
file?.addTypeAlias({
name: 'Buffer',
type: 'any',
});
}
if (!addedProcess && id.getText() === 'process') {
addedProcess = true;
file?.addVariableStatement({
declarations: [
{
name: 'process',
type: 'any',
},
],
hasDeclareKeyword: true,
});
}
}
}
});
}

await project.save();

for (const file of project.getSourceFiles()) {
if (!file.getFilePath().startsWith(denoDir + '/')) continue;
for (const decl of [...file.getImportDeclarations(), ...file.getExportDeclarations()]) {
const moduleSpecifier = decl.getModuleSpecifier();
if (!moduleSpecifier) continue;
let specifier = moduleSpecifier.getLiteralValue().replace(/^node:/, '');
if (!specifier || specifier.startsWith('http')) continue;

if (nodeStdModules.has(specifier)) {
// convert node builtins to deno.land/std
specifier = `https://deno.land/std@0.177.0/node/${specifier}.ts`;
} else if (specifier.startsWith(pkgName + '/')) {
// convert self-referencing module specifiers to relative paths
specifier = file.getRelativePathAsModuleSpecifierTo(denoDir + specifier.substring(pkgName.length));
} else if (specifier === 'qs') {
decl.replaceWithText(`import { qs } from "https://deno.land/x/deno_qs@0.0.1/mod.ts"`);
continue;
} else if (!decl.isModuleSpecifierRelative()) {
specifier = `npm:${specifier}`;
}

if (specifier.startsWith('./') || specifier.startsWith('../')) {
// there may be CJS directory module specifiers that implicitly resolve
// to /index.ts. Add an explicit /index.ts to the end
const sourceFile = decl.getModuleSpecifierSourceFile();
if (sourceFile && /\/index\.ts$/.test(sourceFile.getFilePath()) && !/\/mod\.ts$/.test(specifier)) {
if (/\/index(\.ts)?$/.test(specifier)) {
specifier = specifier.replace(/\/index(\.ts)?$/, '/mod.ts');
} else {
specifier += '/mod.ts';
}
}
// add explicit .ts file extensions to relative module specifiers
specifier = specifier.replace(/(\.[^./]*)?$/, '.ts');
}
moduleSpecifier.replaceWithText(JSON.stringify(specifier));
}
}

await project.save();

await Promise.all(
project.getSourceFiles().map(async (f) => {
const filePath = f.getFilePath();
if (filePath.endsWith('index.ts')) {
const newPath = filePath.replace(/index\.ts$/, 'mod.ts');
await fs.promises.rename(filePath, newPath);
}
}),
);
}

const nodeStdModules = new Set([
'assert',
'assertion_error',
'async_hooks',
'buffer',
'child_process',
'cluster',
'console',
'constants',
'crypto',
'dgram',
'diagnostics_channel',
'dns',
'domain',
'events',
'fs',
'global',
'http',
'http2',
'https',
'inspector',
'module_all',
'module_esm',
'module',
'net',
'os',
'path',
'perf_hooks',
'process',
'punycode',
'querystring',
'readline',
'repl',
'stream',
'string_decoder',
'sys',
'timers',
'tls',
'tty',
'upstream_modules',
'url',
'util',
'v8',
'vm',
'wasi',
'worker_threads',
'zlib',
]);

const typeDeclarationKinds = new Set([
tm.ts.SyntaxKind.InterfaceDeclaration,
tm.ts.SyntaxKind.ModuleDeclaration,
tm.ts.SyntaxKind.TypeAliasDeclaration,
]);

const builtinTypeNames = new Set(['Array', 'Set', 'Map', 'Record', 'Promise']);

function isBuiltinType(type: tm.Type): boolean {
const symbol = type.getSymbol();
return (
symbol != null &&
builtinTypeNames.has(symbol.getName()) &&
symbol.getDeclarations().some((d) => d.getSourceFile().getFilePath().includes('node_modules/typescript'))
);
}

function hasValueDeclarations(nodes?: tm.Node): boolean;
function hasValueDeclarations(nodes?: tm.Node[]): boolean;
function hasValueDeclarations(nodes?: tm.Node | tm.Node[]): boolean {
if (nodes && !Array.isArray(nodes)) {
return (
!isBuiltinType(nodes.getType()) && hasValueDeclarations(nodes.getType().getSymbol()?.getDeclarations())
);
}
return nodes ?
nodes.some((n) => {
const parent = n.getParent();
return (
!typeDeclarationKinds.has(n.getKind()) &&
// sometimes the node will be the right hand side of a type alias
(!parent || !typeDeclarationKinds.has(parent.getKind()))
);
})
: false;
}

denoify();
63 changes: 63 additions & 0 deletions scripts/git-publish-deno.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env bash

# This script pushes the contents of the `deno`` directory to the `deno` branch,
# and creates a `vx.x.x-deno` tag, so that Deno users can
# import OpenAI from "https://raw.githubusercontent.com/openai/openai-node/vx.x.x-deno/mod.ts"

# It's also possible to publish to deno.land. You can do this by:
# - Creating a separate GitHub repo
# - Add the deno.land webhook to the repo as described at https://deno.com/add_module
# - Set the following environment variables when running this script:
# - DENO_PUSH_REMOTE_URL - the remote url of the separate GitHub repo
# - DENO_PUSH_BRANCH - the branch you want to push to in that repo (probably `main`)
# - DENO_PUSH_VERSION - defaults to version in package.json
# - DENO_PUSH_RELEASE_TAG - defaults to v$DENO_PUSH_VERSION-deno

die () {
echo >&2 "$@"
exit 1
}

set -exuo pipefail

# Allow caller to set the following environment variables, but provide defaults
# if unset
# : "${FOO:=bar}" sets FOO=bar unless it's set and non-empty
# https://stackoverflow.com/questions/307503/whats-a-concise-way-to-check-that-environment-variables-are-set-in-a-unix-shell
# https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html

: "${DENO_PUSH_VERSION:=$(node -p 'require("./package.json").version')}"
: "${DENO_PUSH_BRANCH:=deno}"
: "${DENO_PUSH_REMOTE_URL:=$(git remote get-url origin)}"
: "${DENO_PUSH_RELEASE_TAG:="v$DENO_PUSH_VERSION-deno"}"

if [ ! -e deno ]; then ./build; fi

# We want to commit and push a branch where everything inside the deno
# directory is at root level in the branch.

# We can do this by temporarily creating a git repository inside deno,
# committing files to the branch, and pushing it to the remote.

cd deno
rm -rf .git
git init
git remote add origin "$DENO_PUSH_REMOTE_URL"
if git fetch origin "$DENO_PUSH_RELEASE_TAG"; then
die "Tag $DENO_PUSH_RELEASE_TAG already exists"
fi
if git fetch origin "$DENO_PUSH_BRANCH"; then
# the branch already exists on the remote; "check out" the branch without
# changing files in the working directory
git branch "$DENO_PUSH_BRANCH" -t origin/"$DENO_PUSH_BRANCH"
git symbolic-ref HEAD refs/heads/"$DENO_PUSH_BRANCH"
git reset
else
# the branch doesn't exist on the remote yet
git checkout -b "$DENO_PUSH_BRANCH"
fi
git add .
git commit -m "chore(deno): release $DENO_PUSH_VERSION"
git tag -a "$DENO_PUSH_RELEASE_TAG" -m "release $DENO_PUSH_VERSION"
git push --tags --set-upstream origin "$DENO_PUSH_BRANCH"
rm -rf .git
Loading