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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules/
dist/
.corbits/
.DS_Store
.env
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
dist
bun.lock
28 changes: 18 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ reimplementing OAuth or the Responses wire protocol.

## Rules

- Consume `@intx/*` (peer dependency) and the two `@corbits/*` dependencies (`github:` specifiers) as packages only — never vendor or fork them.
- Consume `@intx/*` and the two `@corbits/*` packages (all peer dependencies) as packages only — never vendor or fork them.
- Parse every trust boundary with arktype (JWT payload); never `as T` untrusted input.
- `exactOptionalPropertyTypes` is on: omit optional keys, never assign `undefined` to them.
- No product strings baked in; the x-grok-\* headers and user-agent are xAI wire requirements, not branding.
Expand All @@ -31,15 +31,23 @@ bun install
bun run check # typecheck + lint + format:check + test
```

`@corbits/oauth-core` and `@corbits/openai-responses` resolve from their
GitHub repos, so `bun install` needs those repos pushed. To work against an
unpushed local checkout of either, `bun link` it here; a later `bun install`
re-resolves from git and drops the link.
`@corbits/oauth-core` and `@corbits/openai-responses` are peer dependencies
(`^0.1.0`) — the host provides them. `devDependencies` mirrors the same
`^0.1.0` npm ranges so installs are git-free. The siblings are still
unpublished, so local `bun run check` verification temporarily swaps in
`file:` stand-ins and reverts before commit — never commit stand-in paths or
the lockfile churn they cause. To work against an unpushed local checkout of
either, `bun link` it here.

## Distribution

The package ships TypeScript source: `exports` points at `src/index.ts`,
there is no build step and no `dist/`. Consumers install it with
`bun add @corbits/xai-provider` and Bun runs the source as-is. `bun.lock`
is committed; the two `@corbits/*` dependencies still resolve from their
GitHub repos and switch to npm version ranges at publish time.
The package ships compiled output: `bun run build` (`tsc -p
tsconfig.build.json`, NodeNext, no sourcemaps) emits `dist/` (JS +
declarations, tests excluded), and `prepack` rebuilds `dist/` on every pack.
`exports` maps `.` to `dist` via the types/default pair (`main` agrees), so
both Bun >= 1.2 and native Node >= 24 load the compiled output — no
source-consumption condition. Only `dist` ships (`files` is dist-only). The
two `@corbits/*` peers resolve from npm (`^0.1.0`), so installs are git-free.
Relative imports in `src/` carry explicit `.js` suffixes so the emitted ESM
runs under Node without a rewrite step — never add a build-time rewrite
script or a bundler.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ xAI Grok PKCE OAuth config and token mapping to slot into `@corbits/oauth-core`'

## Runtime support

Bun >= 1.2 runs the published TypeScript source. Node >= 24 is an engines floor for tooling; native Node does not load this extensionless TypeScript source as-is. `@intx/inference` and `@intx/types` are peer dependencies and must resolve to the host's own copy.
The published tarball ships compiled `dist/` (ESM + declarations), so both Bun >= 1.2 and Node >= 24 run it. `@intx/inference` and `@intx/types` are peer dependencies and must resolve to the host's own copy.

## Quickstart

Expand Down
84 changes: 20 additions & 64 deletions bun.lock

Large diffs are not rendered by default.

20 changes: 14 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,44 @@
"author": "Sawyer Cutler <sawyer@dirtroad.dev>",
"type": "module",
"sideEffects": false,
"types": "./dist/index.d.ts",
"main": "./dist/index.js",
"files": [
"src",
"!src/**/*.test.ts",
"dist",
"README.md",
"LICENSE"
],
"publishConfig": {
"access": "public"
},
"exports": {
".": "./src/index.ts"
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"scripts": {
"typecheck": "tsc --noEmit",
"build": "tsc -p tsconfig.build.json",
"prepack": "bun run build",
"lint": "eslint .",
"format": "prettier --write .",
"format:check": "prettier --check .",
"test": "bun test",
"check": "bun run typecheck && bun run lint && bun run format:check && bun run test"
},
"dependencies": {
"@corbits/oauth-core": "github:corbitsdev/corbits-oauth-core#3028f8604155eee63f5a1711f0d4022d7984e3f7",
"@corbits/openai-responses": "github:corbitsdev/corbits-openai-responses",
"arktype": "2.2.3"
"arktype": "^2.2.3"
},
"peerDependencies": {
"@corbits/oauth-core": "^0.1.0",
"@corbits/openai-responses": "^0.1.0",
"@intx/inference": ">=0.4.0",
"@intx/types": ">=0.4.0"
},
"devDependencies": {
"@corbits/oauth-core": "^0.1.0",
"@corbits/openai-responses": "^0.1.0",
"@eslint/js": "9.34.0",
"@intx/inference": "0.4.0",
"@intx/types": "0.4.0",
Expand Down
6 changes: 3 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from "./constants";
export * from "./constants.js";

export {
xaiOAuthConfig,
Expand All @@ -7,9 +7,9 @@ export {
refreshXaiTokens,
xaiUserIdFromAccessToken,
type XaiTokens,
} from "./oauth";
} from "./oauth.js";

export {
createXaiResponsesAdapter,
xaiResponsesQuirks,
} from "./responses-adapter";
} from "./responses-adapter.js";
2 changes: 1 addition & 1 deletion src/oauth.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test";
import { xaiUserIdFromAccessToken } from "./index";
import { xaiUserIdFromAccessToken } from "./index.js";

function jwtWithPayload(payload: unknown): string {
const header = Buffer.from(JSON.stringify({ alg: "none" })).toString(
Expand Down
2 changes: 1 addition & 1 deletion src/oauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
XAI_SCOPES,
XAI_TOKEN_TIMEOUT_MS,
XAI_TOKEN_URL,
} from "./constants";
} from "./constants.js";

/** Tokens issued by xAI's OAuth server: the shared base shape plus an `idToken`. */
export type XaiTokens = BaseTokens & { idToken?: string };
Expand Down
2 changes: 1 addition & 1 deletion src/responses-adapter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { BEARER_CREDENTIAL_SENTINEL } from "@intx/inference";
import type { ConversationTurn, LastCycleSource } from "@intx/types/runtime";
import { type } from "arktype";
import { describe, expect, test } from "bun:test";
import { createXaiResponsesAdapter } from "./index";
import { createXaiResponsesAdapter } from "./index.js";

// Pinned literally rather than imported: neither the CLI-proxy path nor the
// client-identification header values are on the package's public surface,
Expand Down
2 changes: 1 addition & 1 deletion src/responses-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
XAI_SESSION_ID_OPTION,
XAI_USER_AGENT,
XAI_USER_ID_OPTION,
} from "./constants";
} from "./constants.js";

// Mirrors the grok CLI's own /v1/responses request (captured live): the
// system prompt rides as a leading `system` input message with plain string
Expand Down
17 changes: 17 additions & 0 deletions tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"allowImportingTsExtensions": false,
"composite": false,
"module": "NodeNext",
"moduleResolution": "NodeNext",
"noEmit": false,
"declaration": true,
"declarationMap": false,
"sourceMap": false,
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"],
"exclude": ["src/**/*.test.ts"]
}
Loading