Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
9e23e52
fix(mcp): return correct lines on typescript errors
stainless-app[bot] Dec 6, 2025
43c1b91
chore(internal): codegen related update
stainless-app[bot] Dec 6, 2025
e1d8df1
fix(mcp): correct code tool API endpoint
stainless-app[bot] Dec 6, 2025
efcc324
chore(internal): codegen related update
stainless-app[bot] Dec 6, 2025
f157a69
codegen metadata
stainless-app[bot] Dec 8, 2025
b703bb5
codegen metadata
stainless-app[bot] Dec 9, 2025
279de67
codegen metadata
stainless-app[bot] Dec 16, 2025
0d68c1f
codegen metadata
stainless-app[bot] Dec 16, 2025
fe83e26
feat(api): api update
stainless-app[bot] Dec 18, 2025
bbebe4a
feat(api): api update
stainless-app[bot] Dec 19, 2025
7f4433d
codegen metadata
stainless-app[bot] Dec 19, 2025
197cdca
codegen metadata
stainless-app[bot] Dec 29, 2025
e7ffd0c
chore(internal): codegen related update
stainless-app[bot] Jan 6, 2026
2a92dd1
chore: break long lines in snippets into multiline
stainless-app[bot] Jan 7, 2026
02d2330
codegen metadata
stainless-app[bot] Jan 7, 2026
b90b238
codegen metadata
stainless-app[bot] Jan 8, 2026
508b400
codegen metadata
stainless-app[bot] Jan 15, 2026
fe821a3
chore(internal): upgrade babel, qs, js-yaml
stainless-app[bot] Jan 15, 2026
3eece52
codegen metadata
stainless-app[bot] Jan 15, 2026
0a620ee
chore(internal): update `actions/checkout` version
stainless-app[bot] Jan 17, 2026
63946c7
codegen metadata
stainless-app[bot] Jan 20, 2026
924599d
codegen metadata
stainless-app[bot] Jan 20, 2026
a93a07c
feat(api): api update
stainless-app[bot] Jan 24, 2026
16bd5ac
chore(ci): upgrade `actions/github-script`
stainless-app[bot] Jan 24, 2026
d8ddd0a
feat(api): api update
stainless-app[bot] Jan 24, 2026
6286210
codegen metadata
stainless-app[bot] Jan 26, 2026
d90179c
codegen metadata
stainless-app[bot] Jan 26, 2026
3125a12
codegen metadata
stainless-app[bot] Jan 27, 2026
81cd1ab
codegen metadata
stainless-app[bot] Jan 28, 2026
fee3f3a
codegen metadata
stainless-app[bot] Jan 29, 2026
0ec5e60
codegen metadata
stainless-app[bot] Jan 30, 2026
01abc61
feat(api): api update
stainless-app[bot] Jan 31, 2026
58aa0a6
feat(api): api update
stainless-app[bot] Feb 3, 2026
a1c5d0e
fix(client): avoid memory leak with abort signals
stainless-app[bot] Feb 3, 2026
b9f61a8
chore(client): do not parse responses with empty content-length
stainless-app[bot] Feb 3, 2026
9acb0f7
chore(client): restructure abort controller binding
stainless-app[bot] Feb 5, 2026
7088589
fix(client): avoid removing abort listener too early
stainless-app[bot] Feb 6, 2026
4df6efb
feat(api): api update
stainless-app[bot] Feb 6, 2026
0f22218
codegen metadata
stainless-app[bot] Feb 6, 2026
c8873ca
codegen metadata
stainless-app[bot] Feb 9, 2026
d77a39f
feat(api): api update
stainless-app[bot] Feb 10, 2026
f01343c
feat(api): api update
stainless-app[bot] Feb 11, 2026
ef3a2a6
chore(internal): avoid type checking errors with ts-reset
stainless-app[bot] Feb 12, 2026
d938908
codegen metadata
stainless-app[bot] Feb 14, 2026
19a65d7
feat(api): api update
stainless-app[bot] Feb 17, 2026
8d42413
feat(api): api update
stainless-app[bot] Feb 17, 2026
bbe3dc6
feat(api): api update
stainless-app[bot] Feb 17, 2026
e4dbdc4
codegen metadata
stainless-app[bot] Feb 17, 2026
8b100f7
chore(internal/client): fix form-urlencoded requests
stainless-app[bot] Feb 18, 2026
842a3dc
codegen metadata
stainless-app[bot] Feb 19, 2026
94dbc6d
chore(internal): remove mock server code
stainless-app[bot] Feb 20, 2026
214b3fb
chore: update mock server docs
stainless-app[bot] Feb 20, 2026
f78465d
release: 0.1.0-alpha.28
stainless-app[bot] Feb 20, 2026
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
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
runs-on: ${{ github.repository == 'stainless-sdks/sfc-nodes-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Set up Node
uses: actions/setup-node@v4
Expand All @@ -41,7 +41,7 @@ jobs:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Set up Node
uses: actions/setup-node@v4
Expand All @@ -57,7 +57,7 @@ jobs:
- name: Get GitHub OIDC Token
if: github.repository == 'stainless-sdks/sfc-nodes-typescript'
id: github-oidc
uses: actions/github-script@v6
uses: actions/github-script@v8
with:
script: core.setOutput('github_token', await core.getIDToken());

Expand All @@ -74,7 +74,7 @@ jobs:
runs-on: ${{ github.repository == 'stainless-sdks/sfc-nodes-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Set up Node
uses: actions/setup-node@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-npm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Set up Node
uses: actions/setup-node@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-doctor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
if: github.repository == 'sfcompute/nodes-typescript' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next')

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Check release environment
run: |
Expand Down
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.1.0-alpha.27"
".": "0.1.0-alpha.28"
}
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 15
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-7284b205c8d1bc77799405fdd08ca68120426b87031cbc22718da68e22ed5a4c.yml
openapi_spec_hash: b0248957ae5bcf9896f6d74d5c05351b
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-d786973209f42e6ca35f318f4d5bf01e4abd77205e210409c6a3fb371a99a4c5.yml
openapi_spec_hash: 03857ab189ed9fcd889e7b3fe1cc2f2f
config_hash: a187153315a646ecf95709ee4a223df5
44 changes: 44 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
# Changelog

## 0.1.0-alpha.28 (2026-02-20)

Full Changelog: [v0.1.0-alpha.27...v0.1.0-alpha.28](https://github.com/sfcompute/nodes-typescript/compare/v0.1.0-alpha.27...v0.1.0-alpha.28)

### Features

* **api:** api update ([bbe3dc6](https://github.com/sfcompute/nodes-typescript/commit/bbe3dc66127afe52d873191fc7c73af1e9d4bd10))
* **api:** api update ([8d42413](https://github.com/sfcompute/nodes-typescript/commit/8d42413dbed30ce854bb64631954b878b98c127f))
* **api:** api update ([19a65d7](https://github.com/sfcompute/nodes-typescript/commit/19a65d74432438206bd3c8606af656ed28b9496a))
* **api:** api update ([f01343c](https://github.com/sfcompute/nodes-typescript/commit/f01343c9704771e3852d0c6a0c75dc239021967a))
* **api:** api update ([d77a39f](https://github.com/sfcompute/nodes-typescript/commit/d77a39f76881955d9e3231aef26d63fe3309b6dd))
* **api:** api update ([4df6efb](https://github.com/sfcompute/nodes-typescript/commit/4df6efb7e1e4d00a8a7eaf41c67363771adcc56f))
* **api:** api update ([58aa0a6](https://github.com/sfcompute/nodes-typescript/commit/58aa0a6527b383deb0612308a6d6639af8488aaa))
* **api:** api update ([01abc61](https://github.com/sfcompute/nodes-typescript/commit/01abc6189822a16326fddfe3c772fc5747024699))
* **api:** api update ([d8ddd0a](https://github.com/sfcompute/nodes-typescript/commit/d8ddd0a62ea2c7cc12de16b2c3198e84e62c867d))
* **api:** api update ([a93a07c](https://github.com/sfcompute/nodes-typescript/commit/a93a07c6ac7774864fc54059a3ce6c02002f298e))
* **api:** api update ([bbebe4a](https://github.com/sfcompute/nodes-typescript/commit/bbebe4afcdcae6e389e7f25a15ed924d7dbd25b3))
* **api:** api update ([fe83e26](https://github.com/sfcompute/nodes-typescript/commit/fe83e263cf3bef0a4d231172b231b126d4bc81da))


### Bug Fixes

* **client:** avoid memory leak with abort signals ([a1c5d0e](https://github.com/sfcompute/nodes-typescript/commit/a1c5d0e09b6c77eb7b982a82ef87f5d0e3150268))
* **client:** avoid removing abort listener too early ([7088589](https://github.com/sfcompute/nodes-typescript/commit/7088589b8f94f2f5d1200ccbf44f21856789fdea))
* **mcp:** correct code tool API endpoint ([e1d8df1](https://github.com/sfcompute/nodes-typescript/commit/e1d8df157f5bd1c9922ff4689a6ff69288ea31c0))
* **mcp:** return correct lines on typescript errors ([9e23e52](https://github.com/sfcompute/nodes-typescript/commit/9e23e52f4e9e18876ea7454bf2dc1f3e393ba9b4))


### Chores

* break long lines in snippets into multiline ([2a92dd1](https://github.com/sfcompute/nodes-typescript/commit/2a92dd1fadce15736de21aef47c6a09053fcfdbe))
* **ci:** upgrade `actions/github-script` ([16bd5ac](https://github.com/sfcompute/nodes-typescript/commit/16bd5ac8c6a4ca5370c03e4105abd1b5f9f3bcf1))
* **client:** do not parse responses with empty content-length ([b9f61a8](https://github.com/sfcompute/nodes-typescript/commit/b9f61a83ea06509354396c66604bc811f90d18b5))
* **client:** restructure abort controller binding ([9acb0f7](https://github.com/sfcompute/nodes-typescript/commit/9acb0f7b00ca428a1e0681214c41fa59146d41fc))
* **internal/client:** fix form-urlencoded requests ([8b100f7](https://github.com/sfcompute/nodes-typescript/commit/8b100f79af31c3bf7c5e3b27f1efe7acbaaf5a3d))
* **internal:** avoid type checking errors with ts-reset ([ef3a2a6](https://github.com/sfcompute/nodes-typescript/commit/ef3a2a6dd52aad23d937e5a81ff759e8e4c60937))
* **internal:** codegen related update ([e7ffd0c](https://github.com/sfcompute/nodes-typescript/commit/e7ffd0c274c456917d2ef7dcd7b78d2b12370bd9))
* **internal:** codegen related update ([efcc324](https://github.com/sfcompute/nodes-typescript/commit/efcc3241aab120b1e10d771c14f0fa97763c38c5))
* **internal:** codegen related update ([43c1b91](https://github.com/sfcompute/nodes-typescript/commit/43c1b91d4522c19e7000542db9b26d0ba5b96b32))
* **internal:** remove mock server code ([94dbc6d](https://github.com/sfcompute/nodes-typescript/commit/94dbc6de3d7b9fe23be9f0ea99cc0a77422c6afb))
* **internal:** update `actions/checkout` version ([0a620ee](https://github.com/sfcompute/nodes-typescript/commit/0a620ee1a5685cf84a5a05d471c12bbc3713aab6))
* **internal:** upgrade babel, qs, js-yaml ([fe821a3](https://github.com/sfcompute/nodes-typescript/commit/fe821a3fa77954f51049813e63d58342795f65e3))
* update mock server docs ([214b3fb](https://github.com/sfcompute/nodes-typescript/commit/214b3fb0d450acb4a33f1fdd8854ba9ed40c8b2b))

## 0.1.0-alpha.27 (2025-12-06)

Full Changelog: [v0.1.0-alpha.26...v0.1.0-alpha.27](https://github.com/sfcompute/nodes-typescript/compare/v0.1.0-alpha.26...v0.1.0-alpha.27)
Expand Down
6 changes: 0 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,6 @@ $ pnpm link -—global @sfcompute/nodes-sdk-alpha

## Running tests

Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests.

```sh
$ npx prism mock path/to/your/openapi.yml
```

```sh
$ yarn run test
```
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2025 SFC Nodes
Copyright 2026 SFC Nodes

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sfcompute/nodes-sdk-alpha",
"version": "0.1.0-alpha.27",
"version": "0.1.0-alpha.28",
"description": "The official TypeScript library for the SFC Nodes API",
"author": "SFC Nodes <hello@sfcompute.com>",
"types": "dist/index.d.ts",
Expand Down
41 changes: 0 additions & 41 deletions scripts/mock

This file was deleted.

46 changes: 0 additions & 46 deletions scripts/test
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,7 @@ set -e

cd "$(dirname "$0")/.."

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color

function prism_is_running() {
curl --silent "http://localhost:4010" >/dev/null 2>&1
}

kill_server_on_port() {
pids=$(lsof -t -i tcp:"$1" || echo "")
if [ "$pids" != "" ]; then
kill "$pids"
echo "Stopped $pids."
fi
}

function is_overriding_api_base_url() {
[ -n "$TEST_API_BASE_URL" ]
}

if ! is_overriding_api_base_url && ! prism_is_running ; then
# When we exit this script, make sure to kill the background mock server process
trap 'kill_server_on_port 4010' EXIT

# Start the dev server
./scripts/mock --daemon
fi

if is_overriding_api_base_url ; then
echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}"
echo
elif ! prism_is_running ; then
echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server"
echo -e "running against your OpenAPI spec."
echo
echo -e "To run the server, pass in the path or url of your OpenAPI"
echo -e "spec to the prism command:"
echo
echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}"
echo

exit 1
else
echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}"
echo
fi

echo "==> Running tests"
./node_modules/.bin/jest "$@"
21 changes: 18 additions & 3 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ export class SFCNodes {
loggerFor(this).info(`${responseInfo} - ${retryMessage}`);

const errText = await response.text().catch((err: any) => castToError(err).message);
const errJSON = safeJSON(errText);
const errJSON = safeJSON(errText) as any;
const errMessage = errJSON ? undefined : errText;

loggerFor(this).debug(
Expand Down Expand Up @@ -499,9 +499,10 @@ export class SFCNodes {
controller: AbortController,
): Promise<Response> {
const { signal, method, ...options } = init || {};
if (signal) signal.addEventListener('abort', () => controller.abort());
const abort = this._makeAbort(controller);
if (signal) signal.addEventListener('abort', abort, { once: true });

const timeout = setTimeout(() => controller.abort(), ms);
const timeout = setTimeout(abort, ms);

const isReadableBody =
((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) ||
Expand Down Expand Up @@ -668,6 +669,12 @@ export class SFCNodes {
return headers.values;
}

private _makeAbort(controller: AbortController) {
// note: we can't just inline this method inside `fetchWithTimeout()` because then the closure
// would capture all request options, and cause a memory leak.
return () => controller.abort();
}

private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): {
bodyHeaders: HeadersLike;
body: BodyInit | undefined;
Expand Down Expand Up @@ -700,6 +707,14 @@ export class SFCNodes {
(Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))
) {
return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body as AsyncIterable<Uint8Array>) };
} else if (
typeof body === 'object' &&
headers.values.get('content-type') === 'application/x-www-form-urlencoded'
) {
return {
bodyHeaders: { 'content-type': 'application/x-www-form-urlencoded' },
body: this.stringifyQuery(body as Record<string, unknown>),
};
} else {
return this.#encoder({ body, headers });
}
Expand Down
6 changes: 6 additions & 0 deletions src/internal/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ export async function defaultParseResponse<T>(client: SFCNodes, props: APIRespon
const mediaType = contentType?.split(';')[0]?.trim();
const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json');
if (isJSON) {
const contentLength = response.headers.get('content-length');
if (contentLength === '0') {
// if there is no content we can't do anything
return undefined as T;
}

const json = await response.json();
return json as T;
}
Expand Down
14 changes: 12 additions & 2 deletions src/resources/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class Nodes extends APIResource {
* ```ts
* const listResponseNode = await client.nodes.create({
* desired_count: 1,
* max_price_per_node_hour: 1000,
* max_price_per_node_hour: 1600,
* });
* ```
*/
Expand Down Expand Up @@ -134,6 +134,11 @@ export interface CreateNodesRequest {
*/
end_at?: number | null;

/**
* (Optional) If set, enables forwarding to the VM on port 443.
*/
forward_443?: boolean;

/**
* Custom image ID to use for the VM instances
*/
Expand Down Expand Up @@ -176,7 +181,7 @@ export interface ErrorDetail {
code: string;

/**
* Detailed error message
* Human-readable error message
*/
message: string;

Expand Down Expand Up @@ -480,6 +485,11 @@ export interface NodeCreateParams {
*/
end_at?: number | null;

/**
* (Optional) If set, enables forwarding to the VM on port 443.
*/
forward_443?: boolean;

/**
* Custom image ID to use for the VM instances
*/
Expand Down
4 changes: 2 additions & 2 deletions src/resources/vms/vms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ export interface VMSSHResponse {
ssh_port: number;

/**
* Unix timestamp in seconds since epoch
* Unix timestamp.
*/
last_attempted_key_update?: number | null;

/**
* Unix timestamp in seconds since epoch
* Unix timestamp.
*/
last_successful_key_update?: number | null;

Expand Down
Loading