@rudra-js/anthropic 0.5.0 → 0.7.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
@@ -10,7 +10,7 @@ An Anthropic adapter for
10
10
  ## Install
11
11
 
12
12
  ```sh
13
- npm install @rudra-js/anthropic @rudra-js/core zod@^4
13
+ npm install @rudra-js/anthropic @rudra-js/core
14
14
  ```
15
15
 
16
16
  ```ts
@@ -1,35 +1,14 @@
1
1
  import type { ComponentProvider } from '@rudra-js/core';
2
2
  export interface AnthropicProviderOptions {
3
3
  apiKey: string;
4
- /** Defaults to the current Claude model this package was written against. */
5
4
  model?: string;
6
5
  maxTokens?: number;
7
6
  baseUrl?: string;
8
- /**
9
- * Required when the key is identity-linked rather than workspace-scoped —
10
- * such a key belongs to a person across several workspaces, so the API cannot
11
- * infer which one a request acts in and rejects it with a 400.
12
- */
13
7
  workspaceId?: string;
14
- /**
15
- * Sent as the request's `thinking`. Defaults to `{ type: 'disabled' }`,
16
- * because core budgets 1500ms for the whole call and a model that reasons
17
- * before answering does not finish inside it. Pass `null` to send nothing,
18
- * which is what a model that rejects an explicit `disabled` needs, and raise
19
- * `modelTimeoutMs` to match when you do.
20
- */
21
8
  thinking?: {
22
9
  type: 'adaptive' | 'disabled';
23
10
  } | null;
24
- /** Injected so the adapter is testable without a network or an SDK. */
25
11
  fetch?: typeof globalThis.fetch;
26
12
  }
27
- /**
28
- * Adapts the Anthropic Messages API to `ComponentProvider`.
29
- *
30
- * The tool schema is derived from the schema core exports rather than restated
31
- * here: a second copy is a second vocabulary, and the drift would throw below
32
- * and reach the generator as `provider-error` events.
33
- */
34
13
  export declare function createAnthropicProvider(options: AnthropicProviderOptions): ComponentProvider;
35
14
  //# sourceMappingURL=anthropic-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-provider.d.ts","sourceRoot":"","sources":["../src/anthropic-provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EAIlB,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,UAAU,GAAG,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IACpD,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAyCD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAgI5F"}
1
+ {"version":3,"file":"anthropic-provider.d.ts","sourceRoot":"","sources":["../src/anthropic-provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EAIlB,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IAEf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,UAAU,GAAG,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IAEpD,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAoCD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAmG5F"}
@@ -1,10 +1,5 @@
1
1
  import { z } from 'zod';
2
2
  const TOOL_NAME = 'emit_component_spec';
3
- /**
4
- * A model that reasons before answering draws on the same output budget as the
5
- * tool call, and a cap close to what a spec needs leaves no room for it. The
6
- * default is well above a typical spec's size rather than tuned to it.
7
- */
8
3
  const DEFAULT_MAX_TOKENS = 8192;
9
4
  function describeShape(input) {
10
5
  if (input === null)
@@ -28,22 +23,10 @@ function isToolUseBlock(candidate) {
28
23
  candidate['type'] === 'tool_use' &&
29
24
  candidate['name'] === TOOL_NAME);
30
25
  }
31
- /**
32
- * Adapts the Anthropic Messages API to `ComponentProvider`.
33
- *
34
- * The tool schema is derived from the schema core exports rather than restated
35
- * here: a second copy is a second vocabulary, and the drift would throw below
36
- * and reach the generator as `provider-error` events.
37
- */
38
26
  export function createAnthropicProvider(options) {
39
27
  const model = options.model ?? 'claude-sonnet-5';
40
28
  const thinking = options.thinking === undefined ? { type: 'disabled' } : options.thinking;
41
29
  const call = options.fetch ?? globalThis.fetch;
42
- // Trimmed so a caller-supplied `baseUrl` ending in `/` cannot turn into
43
- // `//v1/messages`. Done with a loop rather than `/\/+$/`: that pattern
44
- // backtracks on a string of many trailing slashes, which is a denial of
45
- // service in a published package even though the value comes from the caller
46
- // rather than from a request.
47
30
  let baseUrl = options.baseUrl ?? 'https://api.anthropic.com';
48
31
  while (baseUrl.endsWith('/'))
49
32
  baseUrl = baseUrl.slice(0, -1);
@@ -52,10 +35,6 @@ export function createAnthropicProvider(options) {
52
35
  name: 'anthropic',
53
36
  model,
54
37
  async generate(request) {
55
- // The half of obligation three that `fetch` does not cover. The real
56
- // `fetch` rejects an already-aborted signal on its own, but `fetch` is an
57
- // injected seam here, and a caller's own transport has no such duty — so
58
- // without this, a call the caller has already given up on goes out.
59
38
  request.signal.throwIfAborted();
60
39
  const response = await send(call, `${baseUrl}/v1/messages`, {
61
40
  method: 'POST',
@@ -65,26 +44,17 @@ export function createAnthropicProvider(options) {
65
44
  'anthropic-version': '2023-06-01',
66
45
  ...(options.workspaceId ? { 'anthropic-workspace-id': options.workspaceId } : {}),
67
46
  },
68
- // The caller's deadline, handed straight to the transport: the contract
69
- // asks an adapter to stop, not merely to stop caring about the answer.
70
47
  signal: request.signal,
71
48
  body: JSON.stringify({
72
49
  model,
73
50
  max_tokens: maxTokens,
74
51
  ...(thinking ? { thinking } : {}),
75
- // Marked as the cached prefix. Anything per-shopper interpolated here
76
- // would destroy the prompt cache hit rate.
77
52
  system: [{ type: 'text', text: request.system, cache_control: { type: 'ephemeral' } }],
78
53
  messages: [{ role: 'user', content: request.user }],
79
54
  tools: [
80
55
  {
81
56
  name: TOOL_NAME,
82
57
  description: 'Return the component specification.',
83
- // "input" — a tool's input_schema describes what the model must
84
- // produce as the tool call's argument, not core's own output. The
85
- // two are not the same: "output" carries additionalProperties:
86
- // false on every block and "input" does not. Pinned in
87
- // tests/tool-schema.test.ts.
88
58
  input_schema: z.toJSONSchema(request.schema, { io: 'input' }),
89
59
  },
90
60
  ],
@@ -92,40 +62,25 @@ export function createAnthropicProvider(options) {
92
62
  }),
93
63
  });
94
64
  if (!response.ok) {
95
- // Status and the vendor's error category only. Its message quotes the
96
- // request back, and for this framework that can be a shopper's own search
97
- // terms — which an adopter's `console.error(err)` would then capture.
98
65
  const category = await errorCategory(response);
99
66
  throw new Error(`anthropic responded ${response.status}${category}`);
100
67
  }
101
68
  const parsed = await response.json();
102
- // `response.json()` yields whatever the body held, and `null` is valid
103
- // JSON — reading `stop_reason` off it would throw a TypeError naming this
104
- // adapter rather than the vendor that sent it.
105
69
  if (typeof parsed !== 'object' || parsed === null) {
106
70
  throw new Error(`anthropic returned ${parsed === null ? 'null' : typeof parsed}, not an object`);
107
71
  }
108
72
  const body = parsed;
109
- // Before the tool-block lookup: both are ordinary 200s with no tool_use,
110
- // and reporting them as "no tool use" blames the model for a budget or a
111
- // policy this adapter controls.
112
73
  if (body.stop_reason === 'max_tokens') {
113
74
  throw new Error(`anthropic stopped at the max_tokens budget (${maxTokens}) before returning a tool use`);
114
75
  }
115
76
  if (body.stop_reason === 'refusal') {
116
77
  throw new Error('anthropic refused to answer (stop_reason: refusal)');
117
78
  }
118
- // `content` and each of its entries are untrusted shapes from here on:
119
- // a malformed response should name the vendor, not crash on the
120
- // adapter's own `.find`/`.type` access.
121
79
  const blocks = Array.isArray(body.content) ? body.content : [];
122
80
  const block = blocks.find(isToolUseBlock);
123
81
  if (!block) {
124
82
  throw new Error(`anthropic returned no ${TOOL_NAME} tool use`);
125
83
  }
126
- // Parsed against the caller's own schema. generatedSpecSchema has no
127
- // refinements, so this catches type and enum violations — a block kind
128
- // outside the closed set, a non-string headline — not refinement logic.
129
84
  const asSent = request.schema.safeParse(block.input);
130
85
  const usable = asSent.success ? asSent : request.schema.safeParse(onlyValue(block.input));
131
86
  if (!usable.success) {
@@ -138,21 +93,11 @@ export function createAnthropicProvider(options) {
138
93
  },
139
94
  };
140
95
  }
141
- /**
142
- * Calls the transport, and says what went wrong when it never answered.
143
- *
144
- * `fetch` reports every transport fault as the same `TypeError: fetch failed`
145
- * and hides the reason in `cause` — so a refused connection, a DNS failure and
146
- * a socket reset are indistinguishable in a log. An operator needs to tell
147
- * those apart, and none of them carries request content.
148
- */
149
96
  async function send(call, url, init) {
150
97
  try {
151
98
  return await call(url, init);
152
99
  }
153
100
  catch (error) {
154
- // The caller's own deadline. It means something specific upstream, so it
155
- // travels unchanged.
156
101
  if (init.signal?.aborted)
157
102
  throw error;
158
103
  const cause = error instanceof Error ? (error.cause ?? error) : error;
@@ -162,7 +107,6 @@ async function send(call, url, init) {
162
107
  throw new Error(`anthropic did not answer: ${detail}`, { cause: error });
163
108
  }
164
109
  }
165
- /** The vendor's error category, never its message — the message quotes the request. */
166
110
  async function errorCategory(response) {
167
111
  try {
168
112
  const body = JSON.parse(await response.text());
@@ -170,16 +114,12 @@ async function errorCategory(response) {
170
114
  return typeof type === 'string' ? ` (${type})` : '';
171
115
  }
172
116
  catch {
173
- // A body that is unreadable or not JSON tells us nothing extra. The status
174
- // is still in the message.
175
117
  return '';
176
118
  }
177
119
  }
178
120
  function toUsage(usage) {
179
121
  if (!usage)
180
122
  return undefined;
181
- // A JSON body is untrusted: `"input_tokens": "11"` must not become part of
182
- // a cost figure that downstream code adds instead of concatenates.
183
123
  const numberAt = (key) => {
184
124
  const value = usage[key];
185
125
  return typeof value === 'number' ? value : undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-provider.js","sourceRoot":"","sources":["../src/anthropic-provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"anthropic-provider.js","sourceRoot":"","sources":["../src/anthropic-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsBxB,MAAM,SAAS,GAAG,qBAAqB,CAAC;AAExC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAQhC,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,eAAe,KAAK,CAAC,MAAM,EAAE,CAAC;IAC/D,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,OAAO,KAAK,CAAC,CAAC;IAE3D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,uBAAuB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1F,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1F,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACrD,CAAC;AAED,SAAS,cAAc,CAAC,SAAkB;IACxC,OAAO,CACL,OAAO,SAAS,KAAK,QAAQ;QAC7B,SAAS,KAAK,IAAI;QACjB,SAAqC,CAAC,MAAM,CAAC,KAAK,UAAU;QAC5D,SAAqC,CAAC,MAAM,CAAC,KAAK,SAAS,CAC7D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAiC;IACvE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,iBAAiB,CAAC;IACjD,MAAM,QAAQ,GACZ,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAmB,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACpF,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IAE/C,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,2BAA2B,CAAC;IAC7D,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;IAE1D,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,KAAK;QAEL,KAAK,CAAC,QAAQ,CAAC,OAAwB;YACrC,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;YAEhC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,GAAG,OAAO,cAAc,EAAE;gBAC1D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,WAAW,EAAE,OAAO,CAAC,MAAM;oBAC3B,mBAAmB,EAAE,YAAY;oBACjC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,wBAAwB,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAClF;gBAED,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK;oBACL,UAAU,EAAE,SAAS;oBACrB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAEjC,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC;oBACtF,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;oBACnD,KAAK,EAAE;wBACL;4BACE,IAAI,EAAE,SAAS;4BACf,WAAW,EAAE,qCAAqC;4BAElD,YAAY,EAAE,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;yBAC9D;qBACF;oBACD,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;iBAC/C,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC;gBAE/C,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC,CAAC;YACvE,CAAC;YAED,MAAM,MAAM,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAE9C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBAClD,MAAM,IAAI,KAAK,CACb,sBAAsB,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,iBAAiB,CAChF,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,GAAG,MAIZ,CAAC;YAEF,IAAI,IAAI,CAAC,WAAW,KAAK,YAAY,EAAE,CAAC;gBACtC,MAAM,IAAI,KAAK,CACb,+CAA+C,SAAS,+BAA+B,CACxF,CAAC;YACJ,CAAC;YACD,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;YACxE,CAAC;YAED,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAE1C,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,yBAAyB,SAAS,WAAW,CAAC,CAAC;YACjE,CAAC;YAED,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACrD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;YAE1F,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CACb,wBAAwB,SAAS,0CAA0C;oBACzE,WAAW,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAC1C,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CACxB,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;YACzB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAElC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;QAC/C,CAAC;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,IAAI,CAAC,IAA6B,EAAE,GAAW,EAAE,IAAiB;IAC/E,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,MAAM,KAAK,CAAC;QAEtC,MAAM,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACtE,MAAM,MAAM,GACV,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK;YACnD,CAAC,CAAC,MAAM,CAAE,KAA2B,CAAC,IAAI,CAAC;YAC3C,CAAC,CAAC,MAAM,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAE7D,MAAM,IAAI,KAAK,CAAC,6BAA6B,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,QAAkB;IAC7C,IAAI,CAAC;QACH,MAAM,IAAI,GAAY,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QACxD,MAAM,IAAI,GAAI,IAAuC,EAAE,KAAK,EAAE,IAAI,CAAC;QACnE,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,OAAO,CAAC,KAA0C;IACzD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAE7B,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAsB,EAAE;QACnD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACzB,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACvD,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;IAC7C,MAAM,YAAY,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC/C,MAAM,eAAe,GAAG,QAAQ,CAAC,yBAAyB,CAAC,CAAC;IAC5D,MAAM,gBAAgB,GAAG,QAAQ,CAAC,6BAA6B,CAAC,CAAC;IAEjE,MAAM,MAAM,GAAG;QACb,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QACrD,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC;QACvD,GAAG,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC;QAC7D,GAAG,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC;KAChE,CAAC;IAEF,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7D,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
- /** @rudra-js/anthropic — an Anthropic adapter for `@rudra-js/core`. */
2
1
  export { createAnthropicProvider, type AnthropicProviderOptions } from './anthropic-provider.js';
3
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,OAAO,EAAE,uBAAuB,EAAE,KAAK,wBAAwB,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,KAAK,wBAAwB,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,2 @@
1
- /** @rudra-js/anthropic — an Anthropic adapter for `@rudra-js/core`. */
2
1
  export { createAnthropicProvider } from './anthropic-provider.js';
3
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,OAAO,EAAE,uBAAuB,EAAiC,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAiC,MAAM,yBAAyB,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rudra-js/anthropic",
3
- "version": "0.5.0",
4
- "description": "An Anthropic adapter for @rudra-js/core, with no vendor SDK and no dependencies",
3
+ "version": "0.7.0",
4
+ "description": "An Anthropic adapter for @rudra-js/core, with no vendor SDK",
5
5
  "keywords": [
6
6
  "anthropic",
7
7
  "claude",
@@ -46,12 +46,14 @@
46
46
  "publishConfig": {
47
47
  "access": "public"
48
48
  },
49
+ "dependencies": {
50
+ "zod": "^4.0.0"
51
+ },
49
52
  "peerDependencies": {
50
- "@rudra-js/core": "^0.5.0",
51
- "zod": "^4.5.0"
53
+ "@rudra-js/core": "^0.7.0"
52
54
  },
53
55
  "devDependencies": {
54
- "@rudra-js/core": "0.5.0",
55
- "zod": "^4.5.4"
56
+ "@rudra-js/core": "0.7.0",
57
+ "@types/node": "^26.4.1"
56
58
  }
57
59
  }
@@ -8,35 +8,20 @@ import type {
8
8
 
9
9
  export interface AnthropicProviderOptions {
10
10
  apiKey: string;
11
- /** Defaults to the current Claude model this package was written against. */
11
+
12
12
  model?: string;
13
13
  maxTokens?: number;
14
14
  baseUrl?: string;
15
- /**
16
- * Required when the key is identity-linked rather than workspace-scoped —
17
- * such a key belongs to a person across several workspaces, so the API cannot
18
- * infer which one a request acts in and rejects it with a 400.
19
- */
15
+
20
16
  workspaceId?: string;
21
- /**
22
- * Sent as the request's `thinking`. Defaults to `{ type: 'disabled' }`,
23
- * because core budgets 1500ms for the whole call and a model that reasons
24
- * before answering does not finish inside it. Pass `null` to send nothing,
25
- * which is what a model that rejects an explicit `disabled` needs, and raise
26
- * `modelTimeoutMs` to match when you do.
27
- */
17
+
28
18
  thinking?: { type: 'adaptive' | 'disabled' } | null;
29
- /** Injected so the adapter is testable without a network or an SDK. */
19
+
30
20
  fetch?: typeof globalThis.fetch;
31
21
  }
32
22
 
33
23
  const TOOL_NAME = 'emit_component_spec';
34
24
 
35
- /**
36
- * A model that reasons before answering draws on the same output budget as the
37
- * tool call, and a cap close to what a spec needs leaves no room for it. The
38
- * default is well above a typical spec's size rather than tuned to it.
39
- */
40
25
  const DEFAULT_MAX_TOKENS = 8192;
41
26
 
42
27
  interface ToolUseBlock {
@@ -69,23 +54,12 @@ function isToolUseBlock(candidate: unknown): candidate is ToolUseBlock {
69
54
  );
70
55
  }
71
56
 
72
- /**
73
- * Adapts the Anthropic Messages API to `ComponentProvider`.
74
- *
75
- * The tool schema is derived from the schema core exports rather than restated
76
- * here: a second copy is a second vocabulary, and the drift would throw below
77
- * and reach the generator as `provider-error` events.
78
- */
79
57
  export function createAnthropicProvider(options: AnthropicProviderOptions): ComponentProvider {
80
58
  const model = options.model ?? 'claude-sonnet-5';
81
59
  const thinking =
82
60
  options.thinking === undefined ? { type: 'disabled' as const } : options.thinking;
83
61
  const call = options.fetch ?? globalThis.fetch;
84
- // Trimmed so a caller-supplied `baseUrl` ending in `/` cannot turn into
85
- // `//v1/messages`. Done with a loop rather than `/\/+$/`: that pattern
86
- // backtracks on a string of many trailing slashes, which is a denial of
87
- // service in a published package even though the value comes from the caller
88
- // rather than from a request.
62
+
89
63
  let baseUrl = options.baseUrl ?? 'https://api.anthropic.com';
90
64
  while (baseUrl.endsWith('/')) baseUrl = baseUrl.slice(0, -1);
91
65
  const maxTokens = options.maxTokens ?? DEFAULT_MAX_TOKENS;
@@ -95,10 +69,6 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Comp
95
69
  model,
96
70
 
97
71
  async generate(request: ProviderRequest): Promise<ProviderResult> {
98
- // The half of obligation three that `fetch` does not cover. The real
99
- // `fetch` rejects an already-aborted signal on its own, but `fetch` is an
100
- // injected seam here, and a caller's own transport has no such duty — so
101
- // without this, a call the caller has already given up on goes out.
102
72
  request.signal.throwIfAborted();
103
73
 
104
74
  const response = await send(call, `${baseUrl}/v1/messages`, {
@@ -109,26 +79,20 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Comp
109
79
  'anthropic-version': '2023-06-01',
110
80
  ...(options.workspaceId ? { 'anthropic-workspace-id': options.workspaceId } : {}),
111
81
  },
112
- // The caller's deadline, handed straight to the transport: the contract
113
- // asks an adapter to stop, not merely to stop caring about the answer.
82
+
114
83
  signal: request.signal,
115
84
  body: JSON.stringify({
116
85
  model,
117
86
  max_tokens: maxTokens,
118
87
  ...(thinking ? { thinking } : {}),
119
- // Marked as the cached prefix. Anything per-shopper interpolated here
120
- // would destroy the prompt cache hit rate.
88
+
121
89
  system: [{ type: 'text', text: request.system, cache_control: { type: 'ephemeral' } }],
122
90
  messages: [{ role: 'user', content: request.user }],
123
91
  tools: [
124
92
  {
125
93
  name: TOOL_NAME,
126
94
  description: 'Return the component specification.',
127
- // "input" — a tool's input_schema describes what the model must
128
- // produce as the tool call's argument, not core's own output. The
129
- // two are not the same: "output" carries additionalProperties:
130
- // false on every block and "input" does not. Pinned in
131
- // tests/tool-schema.test.ts.
95
+
132
96
  input_schema: z.toJSONSchema(request.schema, { io: 'input' }),
133
97
  },
134
98
  ],
@@ -137,9 +101,6 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Comp
137
101
  });
138
102
 
139
103
  if (!response.ok) {
140
- // Status and the vendor's error category only. Its message quotes the
141
- // request back, and for this framework that can be a shopper's own search
142
- // terms — which an adopter's `console.error(err)` would then capture.
143
104
  const category = await errorCategory(response);
144
105
 
145
106
  throw new Error(`anthropic responded ${response.status}${category}`);
@@ -147,9 +108,6 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Comp
147
108
 
148
109
  const parsed: unknown = await response.json();
149
110
 
150
- // `response.json()` yields whatever the body held, and `null` is valid
151
- // JSON — reading `stop_reason` off it would throw a TypeError naming this
152
- // adapter rather than the vendor that sent it.
153
111
  if (typeof parsed !== 'object' || parsed === null) {
154
112
  throw new Error(
155
113
  `anthropic returned ${parsed === null ? 'null' : typeof parsed}, not an object`,
@@ -162,9 +120,6 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Comp
162
120
  stop_reason?: string;
163
121
  };
164
122
 
165
- // Before the tool-block lookup: both are ordinary 200s with no tool_use,
166
- // and reporting them as "no tool use" blames the model for a budget or a
167
- // policy this adapter controls.
168
123
  if (body.stop_reason === 'max_tokens') {
169
124
  throw new Error(
170
125
  `anthropic stopped at the max_tokens budget (${maxTokens}) before returning a tool use`,
@@ -174,9 +129,6 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Comp
174
129
  throw new Error('anthropic refused to answer (stop_reason: refusal)');
175
130
  }
176
131
 
177
- // `content` and each of its entries are untrusted shapes from here on:
178
- // a malformed response should name the vendor, not crash on the
179
- // adapter's own `.find`/`.type` access.
180
132
  const blocks = Array.isArray(body.content) ? body.content : [];
181
133
  const block = blocks.find(isToolUseBlock);
182
134
 
@@ -184,9 +136,6 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Comp
184
136
  throw new Error(`anthropic returned no ${TOOL_NAME} tool use`);
185
137
  }
186
138
 
187
- // Parsed against the caller's own schema. generatedSpecSchema has no
188
- // refinements, so this catches type and enum violations — a block kind
189
- // outside the closed set, a non-string headline — not refinement logic.
190
139
  const asSent = request.schema.safeParse(block.input);
191
140
  const usable = asSent.success ? asSent : request.schema.safeParse(onlyValue(block.input));
192
141
 
@@ -206,20 +155,10 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Comp
206
155
  };
207
156
  }
208
157
 
209
- /**
210
- * Calls the transport, and says what went wrong when it never answered.
211
- *
212
- * `fetch` reports every transport fault as the same `TypeError: fetch failed`
213
- * and hides the reason in `cause` — so a refused connection, a DNS failure and
214
- * a socket reset are indistinguishable in a log. An operator needs to tell
215
- * those apart, and none of them carries request content.
216
- */
217
158
  async function send(call: typeof globalThis.fetch, url: string, init: RequestInit) {
218
159
  try {
219
160
  return await call(url, init);
220
161
  } catch (error) {
221
- // The caller's own deadline. It means something specific upstream, so it
222
- // travels unchanged.
223
162
  if (init.signal?.aborted) throw error;
224
163
 
225
164
  const cause = error instanceof Error ? (error.cause ?? error) : error;
@@ -232,15 +171,12 @@ async function send(call: typeof globalThis.fetch, url: string, init: RequestIni
232
171
  }
233
172
  }
234
173
 
235
- /** The vendor's error category, never its message — the message quotes the request. */
236
174
  async function errorCategory(response: Response): Promise<string> {
237
175
  try {
238
176
  const body: unknown = JSON.parse(await response.text());
239
177
  const type = (body as { error?: { type?: unknown } })?.error?.type;
240
178
  return typeof type === 'string' ? ` (${type})` : '';
241
179
  } catch {
242
- // A body that is unreadable or not JSON tells us nothing extra. The status
243
- // is still in the message.
244
180
  return '';
245
181
  }
246
182
  }
@@ -248,8 +184,6 @@ async function errorCategory(response: Response): Promise<string> {
248
184
  function toUsage(usage: Record<string, unknown> | undefined): TokenUsage | undefined {
249
185
  if (!usage) return undefined;
250
186
 
251
- // A JSON body is untrusted: `"input_tokens": "11"` must not become part of
252
- // a cost figure that downstream code adds instead of concatenates.
253
187
  const numberAt = (key: string): number | undefined => {
254
188
  const value = usage[key];
255
189
  return typeof value === 'number' ? value : undefined;
package/src/index.ts CHANGED
@@ -1,3 +1 @@
1
- /** @rudra-js/anthropic — an Anthropic adapter for `@rudra-js/core`. */
2
-
3
1
  export { createAnthropicProvider, type AnthropicProviderOptions } from './anthropic-provider.js';