defiant-jazz 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -28,15 +28,21 @@ await refine("Hello world", "dylan");
28
28
  ```
29
29
 
30
30
  Set `ANTHROPIC_API_KEY` or `OPENAI_API_KEY` in your environment and you're done —
31
- whichever is present is used automatically (Anthropic first if both are set).
31
+ whichever one is present is used. If both are set, the library won't pick for
32
+ you; pass `provider` instead (see [Choosing a provider](#choosing-a-provider)).
32
33
 
33
34
  **Default models: `claude-sonnet-5` (Anthropic), `gpt-4o-mini` (OpenAI).**
34
35
  Sonnet 5 was chosen over Opus 5 after a head-to-head comparison found
35
36
  matching output quality at 40% of the cost — see
36
37
  [model-comparison.md](model-comparison.md) for the full writeup, including a
37
38
  documented regression on Haiku 4.5 that ruled it out as a default. Override
38
- with `model` on `createDefiantJazz()` or per call; see
39
- [Choosing a provider](#choosing-a-provider).
39
+ with `model` on `createDefiantJazz()` or per call. The defaults are also
40
+ exported, so you can check what a zero-config call will run:
41
+
42
+ ```typescript
43
+ import { DEFAULT_MODELS } from 'defiant-jazz';
44
+ // { anthropic: 'claude-sonnet-5', openai: 'gpt-4o-mini' }
45
+ ```
40
46
 
41
47
  ## Lore
42
48
 
@@ -91,7 +97,28 @@ await claude.dylan("Hello world");
91
97
  await gpt.dylan("Hello world");
92
98
  ```
93
99
 
94
- `refine` is a shared default instance using auto-detected credentials. Use
100
+ How the provider is chosen:
101
+
102
+ - `provider` set → that provider. Its key comes from `apiKey`, or from
103
+ `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` if `apiKey` is omitted.
104
+ - `provider` omitted, exactly one env key set → that provider.
105
+ - `provider` omitted, both env keys set → throws. The library never decides
106
+ whose account gets billed.
107
+ - `apiKey` passed without `provider` → throws, so a key is never sent to the
108
+ wrong service.
109
+
110
+ Only those two env var names are read. To use a key stored under a different
111
+ name, read it yourself and pass it as `apiKey`:
112
+
113
+ ```typescript
114
+ const gpt = createDefiantJazz({
115
+ provider: 'openai',
116
+ apiKey: process.env.MY_TEAM_OPENAI_KEY,
117
+ });
118
+ ```
119
+
120
+ `refine` is a shared default instance that follows the same rules; point it at
121
+ a provider with `refine.configure({ provider: 'openai' })`. Use
95
122
  `createDefiantJazz()` whenever you need an isolated instance — a specific
96
123
  provider, different API keys per request, a non-default model, testing.
97
124
 
package/dist/client.js CHANGED
@@ -12,14 +12,23 @@ function resolveProvider(options) {
12
12
  }
13
13
  return { provider: options.provider, apiKey };
14
14
  }
15
+ // No explicit provider. Only infer one when there's exactly one candidate;
16
+ // never guess between two, since that picks whose account gets billed.
15
17
  if (options.apiKey) {
16
- return { provider: "anthropic", apiKey: options.apiKey };
18
+ throw new Error("apiKey requires provider so the key isn't sent to the wrong service. " +
19
+ "Pass { provider: 'anthropic' } or { provider: 'openai' } alongside it.");
17
20
  }
18
- if (process.env.ANTHROPIC_API_KEY) {
19
- return { provider: "anthropic", apiKey: process.env.ANTHROPIC_API_KEY };
21
+ const anthropicKey = process.env.ANTHROPIC_API_KEY;
22
+ const openaiKey = process.env.OPENAI_API_KEY;
23
+ if (anthropicKey && openaiKey) {
24
+ throw new Error("Both ANTHROPIC_API_KEY and OPENAI_API_KEY are set. " +
25
+ "Pass { provider: 'anthropic' } or { provider: 'openai' } to choose.");
20
26
  }
21
- if (process.env.OPENAI_API_KEY) {
22
- return { provider: "openai", apiKey: process.env.OPENAI_API_KEY };
27
+ if (anthropicKey) {
28
+ return { provider: "anthropic", apiKey: anthropicKey };
29
+ }
30
+ if (openaiKey) {
31
+ return { provider: "openai", apiKey: openaiKey };
23
32
  }
24
33
  throw new Error("No API key found. Set ANTHROPIC_API_KEY or OPENAI_API_KEY " +
25
34
  "(or pass apiKey/provider to configure()/createDefiantJazz()).");
@@ -0,0 +1,7 @@
1
+ import type { Provider } from "./types.js";
2
+ /**
3
+ * The model each provider uses when `model` is not set. Exported so callers
4
+ * can see what a zero-config call will run (and be billed for) without
5
+ * reading the docs. See model-comparison.md for why Sonnet 5 is the default.
6
+ */
7
+ export declare const DEFAULT_MODELS: Readonly<Record<Provider, string>>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The model each provider uses when `model` is not set. Exported so callers
3
+ * can see what a zero-config call will run (and be billed for) without
4
+ * reading the docs. See model-comparison.md for why Sonnet 5 is the default.
5
+ */
6
+ export const DEFAULT_MODELS = Object.freeze({
7
+ anthropic: "claude-sonnet-5",
8
+ openai: "gpt-4o-mini",
9
+ });
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { createDefiantJazz, type DefiantJazz } from "./client.js";
2
+ import { DEFAULT_MODELS } from "./defaults.js";
2
3
  import { CHARACTERS } from "./prompt.js";
3
4
  import type { CharacterKey, DefiantJazzOptions, Effort, RefineOptions, RefineResult, TokenUsage } from "./types.js";
4
5
  export type { CharacterKey, DefiantJazzOptions, Effort, RefineOptions, RefineResult, TokenUsage, };
5
- export { CHARACTERS, createDefiantJazz };
6
+ export { CHARACTERS, DEFAULT_MODELS, createDefiantJazz };
6
7
  /**
7
8
  * Configure the default `refine` instance with an API key and optional
8
9
  * model/provider overrides. Prefer `createDefiantJazz()` for an isolated
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createDefiantJazz } from "./client.js";
2
+ import { DEFAULT_MODELS } from "./defaults.js";
2
3
  import { CHARACTERS } from "./prompt.js";
3
- export { CHARACTERS, createDefiantJazz };
4
+ export { CHARACTERS, DEFAULT_MODELS, createDefiantJazz };
4
5
  let defaultInstance = null;
5
6
  function getDefaultInstance() {
6
7
  if (!defaultInstance) {
@@ -1,5 +1,6 @@
1
1
  import Anthropic from "@anthropic-ai/sdk";
2
- const DEFAULT_MODEL = "claude-sonnet-5";
2
+ import { DEFAULT_MODELS } from "../defaults.js";
3
+ const DEFAULT_MODEL = DEFAULT_MODELS.anthropic;
3
4
  const DEFAULT_MAX_TOKENS = 4096;
4
5
  export function createAnthropicClient(apiKey) {
5
6
  return new Anthropic({ apiKey });
@@ -1,5 +1,6 @@
1
1
  import OpenAI from "openai";
2
- const DEFAULT_MODEL = "gpt-4o-mini";
2
+ import { DEFAULT_MODELS } from "../defaults.js";
3
+ const DEFAULT_MODEL = DEFAULT_MODELS.openai;
3
4
  const DEFAULT_MAX_TOKENS = 4096;
4
5
  export function createOpenAiClient(apiKey) {
5
6
  return new OpenAI({ apiKey });
package/dist/types.d.ts CHANGED
@@ -17,7 +17,11 @@ export interface RefineResult {
17
17
  usage?: TokenUsage;
18
18
  }
19
19
  export interface DefiantJazzOptions {
20
- /** Explicit provider. Defaults to whichever API key is set (Anthropic first). */
20
+ /**
21
+ * Which API to call. Optional only when exactly one of `ANTHROPIC_API_KEY`
22
+ * or `OPENAI_API_KEY` is set and `apiKey` is not passed; when the choice
23
+ * would be ambiguous, the library throws rather than guess.
24
+ */
21
25
  provider?: Provider;
22
26
  apiKey?: string;
23
27
  model?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "defiant-jazz",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Transform quotes into Severance character voices using Claude or OpenAI",
5
5
  "license": "MIT",
6
6
  "author": "pelikenjones",