@spectyra/sdk 0.1.0 → 0.1.2

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
@@ -1,8 +1,22 @@
1
- # Spectyra SDK
1
+ # Spectyra SDK (`@spectyra/sdk`)
2
2
 
3
- **SDK-first agent runtime control: routing, budgets, tool gating, telemetry**
3
+ SDK-first agent runtime control for **routing**, **budgets**, **tool gating**, and **telemetry**.
4
4
 
5
- Spectyra SDK provides agent runtime control for Claude Agent SDK and other agent frameworks. Control model selection, budgets, tool permissions, and telemetry—all without requiring a proxy.
5
+ This package is designed for **agent frameworks** (including Claude Agent SDK patterns) and for teams who want:
6
+
7
+ - **Better first actions** (e.g. “run tests first” becomes a strict tool action)
8
+ - **Less looping / file thrashing** in coding flows
9
+ - **Budget + tool policy control** without rewriting your agent
10
+ - Optional **API control plane** mode for centralized governance and telemetry
11
+
12
+ ---
13
+
14
+ ## Requirements
15
+
16
+ - **Node.js 18+**
17
+ - ESM environment (this package ships as ESM)
18
+
19
+ ---
6
20
 
7
21
  ## Installation
8
22
 
@@ -14,230 +28,252 @@ pnpm add @spectyra/sdk
14
28
  yarn add @spectyra/sdk
15
29
  ```
16
30
 
17
- ## Two Integration Styles
31
+ ---
18
32
 
19
- ### A) Local SDK Mode (Default)
33
+ ## What Spectyra does (and does not do)
20
34
 
21
- **No proxy required.** SDK makes local decisions about agent options.
35
+ - **Does**: return an options object (model/budget/tools/permissions) and/or call Spectyra API to get them
36
+ - **Does**: provide a “behavior kernel” (operating rules) that keeps agents grounded (especially for coding)
37
+ - **Does not**: replace your LLM provider call by default
38
+ - **Does not**: require a proxy (proxy is a separate product for IDE-level routing)
22
39
 
23
- ```typescript
24
- import { createSpectyra } from '@spectyra/sdk';
25
-
26
- // Local mode - works offline, no API calls
27
- const spectyra = createSpectyra({ mode: "local" });
28
-
29
- // One line integration with Claude Agent SDK
30
- const options = spectyra.agentOptions(ctx, prompt);
31
- const result = await agent.query({ prompt, options });
32
- ```
40
+ If you’re using an agent framework, the integration is:
33
41
 
34
- ### B) API Control Plane Mode (Enterprise)
42
+ > **Where you would pass agent options, get them from Spectyra instead.**
35
43
 
36
- SDK calls Spectyra API to fetch agent options and stream events for telemetry.
44
+ ---
37
45
 
38
- ```typescript
39
- import { createSpectyra } from '@spectyra/sdk';
46
+ ## Quick Start (Local Mode)
40
47
 
41
- const spectyra = createSpectyra({
42
- mode: "api",
43
- endpoint: "https://spectyra.up.railway.app/v1",
44
- apiKey: process.env.SPECTYRA_API_KEY,
45
- });
46
-
47
- // Fetch options from remote API
48
- const response = await spectyra.agentOptionsRemote(ctx, promptMeta);
49
- const result = await agent.query({ prompt, options: response.options });
50
-
51
- // Stream events for telemetry
52
- for await (const event of agentStream) {
53
- await spectyra.sendAgentEvent(ctx, event);
54
- }
55
- ```
48
+ Local mode is synchronous and requires **no API**.
56
49
 
57
- ## Quick Start: Local Mode
50
+ ```ts
51
+ import { createSpectyra } from "@spectyra/sdk";
58
52
 
59
- ```typescript
60
- import { createSpectyra } from '@spectyra/sdk';
61
- import { Agent } from '@anthropic-ai/sdk/agent';
62
-
63
- // Create Spectyra instance (local mode - default)
64
53
  const spectyra = createSpectyra({ mode: "local" });
65
54
 
66
- // Create context for this agent run
67
55
  const ctx = {
68
56
  runId: crypto.randomUUID(),
69
57
  budgetUsd: 2.5,
70
58
  tags: { project: "my-app" },
71
59
  };
72
60
 
73
- // Get agent options (synchronous, local decision)
74
- const prompt = "Fix the bug in src/utils.ts";
61
+ const prompt = "Fix the failing tests. Run tests first and paste output.";
75
62
  const options = spectyra.agentOptions(ctx, prompt);
76
63
 
77
- // Use with Claude Agent SDK
78
- const agent = new Agent({
79
- apiKey: process.env.ANTHROPIC_API_KEY,
80
- ...options, // Model, budget, tools, permissions
81
- });
82
-
83
- const result = await agent.query({ prompt });
64
+ // Pass options into your agent framework
65
+ // agent.query({ prompt, options })
66
+ console.log(options);
84
67
  ```
85
68
 
86
- ## Quick Start: API Mode
69
+ ---
70
+
71
+ ## Quick Start (API Mode / Control Plane)
72
+
73
+ API mode fetches options from your Spectyra deployment and can stream events for telemetry.
87
74
 
88
- ```typescript
89
- import { createSpectyra } from '@spectyra/sdk';
75
+ ```ts
76
+ import { createSpectyra } from "@spectyra/sdk";
90
77
 
91
78
  const spectyra = createSpectyra({
92
79
  mode: "api",
93
- endpoint: "https://spectyra.up.railway.app/v1",
80
+ endpoint: process.env.SPECTYRA_ENDPOINT || "https://spectyra.up.railway.app/v1",
94
81
  apiKey: process.env.SPECTYRA_API_KEY,
95
82
  });
96
83
 
97
- const ctx = {
98
- runId: crypto.randomUUID(),
99
- budgetUsd: 5.0,
100
- };
84
+ const ctx = { runId: crypto.randomUUID(), budgetUsd: 5.0 };
101
85
 
102
- // Fetch options from remote API
103
86
  const promptMeta = {
104
- promptChars: prompt.length,
87
+ promptChars: 10000,
105
88
  path: "code",
106
89
  repoId: "my-repo",
107
90
  language: "typescript",
108
91
  };
109
92
 
110
93
  const response = await spectyra.agentOptionsRemote(ctx, promptMeta);
111
- // response.run_id is set automatically
94
+ // response.options is safe to pass into your agent
95
+ ```
112
96
 
113
- // Use options with agent
114
- const agent = new Agent({
115
- apiKey: process.env.ANTHROPIC_API_KEY,
116
- ...response.options,
117
- });
97
+ **Required env vars (API mode):**
118
98
 
119
- // Stream events for telemetry
120
- const stream = agent.queryStream({ prompt });
121
- await spectyra.observeAgentStream(ctx, stream);
122
- ```
99
+ - `SPECTYRA_API_KEY`
100
+ - `SPECTYRA_ENDPOINT` (optional; defaults to Spectyra hosted URL)
123
101
 
124
- ## API Reference
102
+ ---
125
103
 
126
- ### `createSpectyra(config?: SpectyraConfig)`
104
+ ## “Run tests first” behavior (coding flows)
127
105
 
128
- Create a Spectyra SDK instance.
106
+ Spectyra’s coding flow state compiler is designed to turn “run tests/lint” into an unambiguous first action.
129
107
 
130
- **Config:**
131
- - `mode?: "local" | "api"` - Default: `"local"`
132
- - `endpoint?: string` - Required for API mode
133
- - `apiKey?: string` - Required for API mode
134
- - `defaults?: { budgetUsd?: number; models?: { small?, medium?, large? } }`
108
+ If the user asks:
135
109
 
136
- **Returns:** `SpectyraInstance`
110
+ > “Run the full test suite and paste output”
137
111
 
138
- ### `agentOptions(ctx: SpectyraCtx, prompt: string | PromptMeta): ClaudeAgentOptions`
112
+ Spectyra’s generated operating rules require:
139
113
 
140
- Get agent options locally (synchronous, offline).
114
+ - **Call the tool immediately** (`run_terminal_cmd`)
115
+ - **Do NOT read_file first**
116
+ - **Do not narrate** (“Checking …” autopilot stops)
141
117
 
142
- **Context:**
143
- - `runId?: string` - Run identifier
144
- - `budgetUsd?: number` - Budget for this run
145
- - `tags?: Record<string, string>` - Tags for analytics
118
+ This behavior is enforced in the SCC compiler and is measurable in Spectyra Studio / governance metrics.
146
119
 
147
- **Returns:** Claude Agent SDK-compatible options
120
+ ---
148
121
 
149
- ### `agentOptionsRemote(ctx: SpectyraCtx, promptMeta: PromptMeta): Promise<AgentOptionsResponse>`
122
+ ## Claude Agent SDK integration pattern (options injection)
150
123
 
151
- Fetch agent options from remote API (asynchronous).
124
+ Spectyra does not replace the agent; it produces options that guide it.
152
125
 
153
- **PromptMeta:**
154
- - `promptChars: number` - Prompt character count
155
- - `path?: "code" | "talk"` - Path type
156
- - `repoId?: string` - Repository identifier
157
- - `language?: string` - Programming language
158
- - `filesChanged?: number` - Number of files changed
126
+ ```ts
127
+ import { createSpectyra } from "@spectyra/sdk";
128
+ // import { Agent } from "@anthropic-ai/sdk/agent";
159
129
 
160
- **Returns:** Options with `run_id` and `reasons`
130
+ const spectyra = createSpectyra({ mode: "local" });
131
+
132
+ const ctx = { runId: crypto.randomUUID(), budgetUsd: 2.5 };
133
+ const prompt = "Fix the build; run tests first.";
134
+
135
+ const options = spectyra.agentOptions(ctx, prompt);
136
+
137
+ // const agent = new Agent({ apiKey: process.env.ANTHROPIC_API_KEY, ...options });
138
+ // const result = await agent.query({ prompt });
139
+ ```
140
+
141
+ ---
142
+
143
+ ## API Reference (high-signal)
144
+
145
+ ### `createSpectyra(config?: SpectyraConfig)`
146
+
147
+ Creates a Spectyra instance.
148
+
149
+ - `mode?: "local" | "api"` (default `"local"`)
150
+ - `endpoint?: string` (required for `"api"`)
151
+ - `apiKey?: string` (required for `"api"`)
152
+ - `defaults?: { budgetUsd?: number; models?: { small?: string; medium?: string; large?: string } }`
153
+
154
+ ### `agentOptions(ctx: SpectyraCtx, prompt: string | PromptMeta): ClaudeAgentOptions`
155
+
156
+ Returns agent options synchronously (local heuristics).
157
+
158
+ ### `agentOptionsRemote(ctx: SpectyraCtx, promptMeta: PromptMeta): Promise<AgentOptionsResponse>`
159
+
160
+ Fetches agent options from Spectyra API.
161
161
 
162
162
  ### `sendAgentEvent(ctx: SpectyraCtx, event: any): Promise<void>`
163
163
 
164
- Send agent event for telemetry (best-effort, non-blocking).
164
+ Best-effort telemetry event.
165
165
 
166
166
  ### `observeAgentStream(ctx: SpectyraCtx, stream: AsyncIterable<any>): Promise<void>`
167
167
 
168
- Observe agent stream and forward events automatically.
168
+ Observes an agent stream and forwards events automatically.
169
169
 
170
- ## Agent Options
170
+ ---
171
171
 
172
- The SDK returns Claude Agent SDK-compatible options:
172
+ ## Agent options shape (what you pass to the agent)
173
173
 
174
- ```typescript
174
+ ```ts
175
175
  interface ClaudeAgentOptions {
176
- model?: string; // e.g., "claude-3-5-sonnet-latest"
177
- maxBudgetUsd?: number; // Budget limit
178
- allowedTools?: string[]; // e.g., ["Read", "Edit", "Bash"]
179
- permissionMode?: "acceptEdits"; // Permission mode
180
- canUseTool?: (tool, input) => boolean; // Tool gate function
176
+ model?: string;
177
+ maxBudgetUsd?: number;
178
+ allowedTools?: string[];
179
+ permissionMode?: "acceptEdits";
180
+ canUseTool?: (tool: string, input: any) => boolean;
181
181
  }
182
182
  ```
183
183
 
184
- ## Local Decision Logic
184
+ ---
185
+
186
+ ## Local mode decision logic (defaults)
187
+
188
+ Local mode uses conservative heuristics:
189
+
190
+ - **Prompt length < 6k chars** → `claude-3-5-haiku-latest`
191
+ - **Prompt length < 20k chars** → `claude-3-5-sonnet-latest`
192
+ - **Prompt length ≥ 20k chars** → `claude-3-7-sonnet-latest`
193
+
194
+ Defaults:
185
195
 
186
- In local mode, the SDK uses simple heuristics:
196
+ - Budget: `$2.5`
197
+ - Tools: `["Read", "Edit", "Bash", "Glob"]`
198
+ - Permissions: `"acceptEdits"`
187
199
 
188
- - **Prompt length < 6k chars** → Small tier → `claude-3-5-haiku-latest`
189
- - **Prompt length < 20k chars** → Medium tier → `claude-3-5-sonnet-latest`
190
- - **Prompt length ≥ 20k chars** → Large tier → `claude-3-7-sonnet-latest`
200
+ ---
191
201
 
192
- Default budget: $2.5 per run
193
- Default tools: `["Read", "Edit", "Bash", "Glob"]`
194
- Default permissions: `"acceptEdits"`
202
+ ## Tool gating (local)
195
203
 
196
- ## Tool Gating
204
+ The default `canUseTool` gate:
197
205
 
198
- The SDK includes a default `canUseTool` gate that:
199
- - Allows: Read, Edit, Bash (safe commands), Glob
200
- - ❌ Denies: Bash commands containing `curl`, `wget`, `ssh`, `scp`, `nc`, `telnet`
206
+ - Allows: Read/Edit/Glob and safe Bash
207
+ - Blocks obvious exfiltration/networking commands (e.g. `curl`, `wget`, `ssh`, `scp`, `nc`, `telnet`)
201
208
 
202
- You can override this by providing your own `canUseTool` function in the options.
209
+ You can override tool gating by replacing `canUseTool` in your agent options.
203
210
 
204
- ## Remote Chat Optimization (Optional)
211
+ ---
205
212
 
206
- For chat optimization (not agentic), use the legacy client:
213
+ ## Legacy: Remote chat optimization (`SpectyraClient`)
207
214
 
208
- ```typescript
209
- import { SpectyraClient } from '@spectyra/sdk';
215
+ `SpectyraClient` exists for legacy chat-style integration. It is **deprecated** for agentic usage; prefer `createSpectyra()`.
216
+
217
+ ```ts
218
+ import { SpectyraClient } from "@spectyra/sdk";
210
219
 
211
220
  const client = new SpectyraClient({
212
- apiUrl: 'https://spectyra.up.railway.app/v1',
221
+ apiUrl: "https://spectyra.up.railway.app/v1",
213
222
  spectyraKey: process.env.SPECTYRA_API_KEY,
214
- provider: 'openai',
215
- providerKey: process.env.OPENAI_API_KEY, // BYOK
223
+ provider: "openai",
224
+ providerKey: process.env.OPENAI_API_KEY,
216
225
  });
217
226
 
218
227
  const response = await client.chat({
219
- model: 'gpt-4o-mini',
220
- messages: [{ role: 'user', content: 'Hello' }],
221
- path: 'talk',
228
+ model: "gpt-4o-mini",
229
+ messages: [{ role: "user", content: "Hello" }],
230
+ path: "talk",
222
231
  optimization_level: 3,
223
232
  });
224
233
  ```
225
234
 
226
- **Note:** `SpectyraClient` is deprecated. For agentic use cases, use `createSpectyra()`.
235
+ ---
236
+
237
+ ## Testing your install (what we recommend)
238
+
239
+ Local mode can be validated without any API keys:
240
+
241
+ ```bash
242
+ node -e "import('@spectyra/sdk').then(m=>console.log('✅ exports:',Object.keys(m)))"
243
+ ```
244
+
245
+ For deeper tests, see `TESTING.md` in the repo.
246
+
247
+ ---
248
+
249
+ ## Troubleshooting
250
+
251
+ ### NPM page says “No README”
252
+
253
+ NPM displays the README from the published tarball. If your currently published version shows no README, publish a new version where `README.md` is included at the package root.
254
+
255
+ You can verify packaging locally:
256
+
257
+ ```bash
258
+ cd packages/sdk
259
+ npm pack --dry-run
260
+ ```
261
+
262
+ Look for `README.md` in the tarball contents.
227
263
 
228
- ## Examples
264
+ ### API mode returns 403 “SDK access is disabled”
229
265
 
230
- See `examples/` directory:
231
- - `claude-agent-local.ts` - Local mode with Claude Agent SDK
232
- - `claude-agent-remote.ts` - API mode with telemetry
233
- - `chat-remote.ts` - Chat optimization (legacy)
266
+ Your org’s SDK access is controlled by admin settings. Enable SDK access for the org in Spectyra Admin.
267
+
268
+ ---
234
269
 
235
270
  ## BYOK (Bring Your Own Key)
236
271
 
237
- - Provider API keys are **never stored** server-side
238
- - Keys are only used for the duration of the request
239
- - You maintain full control over provider billing
240
- - Agent options/events endpoints don't require provider keys
272
+ - Provider keys are never stored server-side
273
+ - Used only for the duration of a request
274
+ - You control provider billing
275
+
276
+ ---
241
277
 
242
278
  ## License
243
279
 
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Standalone shared types for @spectyra/sdk.
3
+ *
4
+ * This file intentionally duplicates a minimal subset of types that previously
5
+ * came from @spectyra/shared, so consumers can install only @spectyra/sdk.
6
+ */
7
+ export type Path = "talk" | "code";
8
+ export type Mode = "baseline" | "optimized";
9
+ /**
10
+ * Canonical ChatMessage type
11
+ * Supports tool role for agent workflows
12
+ */
13
+ export interface ChatMessage {
14
+ role: "system" | "user" | "assistant" | "tool";
15
+ content: string;
16
+ }
17
+ export interface Usage {
18
+ input_tokens: number;
19
+ output_tokens: number;
20
+ total_tokens: number;
21
+ estimated?: boolean;
22
+ }
23
+ /**
24
+ * Claude Agent Options
25
+ * Compatible with Claude SDK agent options
26
+ */
27
+ export interface ClaudeAgentOptions {
28
+ model?: string;
29
+ maxBudgetUsd?: number;
30
+ cwd?: string;
31
+ allowedTools?: string[];
32
+ permissionMode?: "default" | "acceptEdits" | "bypassPermissions";
33
+ canUseTool?: (toolName: string, toolInput: any) => boolean | Promise<boolean>;
34
+ }
35
+ /**
36
+ * Agent Decision
37
+ * Result of policy engine deciding agent options
38
+ */
39
+ export interface AgentDecision {
40
+ options: ClaudeAgentOptions;
41
+ reasons: string[];
42
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Standalone shared types for @spectyra/sdk.
3
+ *
4
+ * This file intentionally duplicates a minimal subset of types that previously
5
+ * came from @spectyra/shared, so consumers can install only @spectyra/sdk.
6
+ */
7
+ export {};
package/dist/types.d.ts CHANGED
@@ -84,42 +84,6 @@ export interface PromptMeta {
84
84
  */
85
85
  testCommand?: string;
86
86
  }
87
- export interface ClaudeAgentOptions {
88
- /**
89
- * Model name (e.g., "claude-3-5-sonnet-latest")
90
- */
91
- model?: string;
92
- /**
93
- * Maximum budget in USD for this run
94
- */
95
- maxBudgetUsd?: number;
96
- /**
97
- * Working directory
98
- */
99
- cwd?: string;
100
- /**
101
- * Allowed tool names
102
- */
103
- allowedTools?: string[];
104
- /**
105
- * Permission mode
106
- */
107
- permissionMode?: "default" | "acceptEdits" | "bypassPermissions";
108
- /**
109
- * Tool usage gate function
110
- */
111
- canUseTool?: (toolName: string, toolInput: any) => boolean | Promise<boolean>;
112
- }
113
- export interface AgentDecision {
114
- /**
115
- * Generated agent options
116
- */
117
- options: ClaudeAgentOptions;
118
- /**
119
- * Decision reasons (for debugging)
120
- */
121
- reasons: string[];
122
- }
123
87
  export interface AgentOptionsRequest {
124
88
  run_id?: string;
125
89
  prompt_meta: PromptMeta;
@@ -140,18 +104,8 @@ export interface AgentEventRequest {
140
104
  export interface AgentEventResponse {
141
105
  ok: boolean;
142
106
  }
143
- export type Path = "talk" | "code";
144
- export type Mode = "baseline" | "optimized";
145
- export interface ChatMessage {
146
- role: "system" | "user" | "assistant";
147
- content: string;
148
- }
149
- export interface Usage {
150
- input_tokens: number;
151
- output_tokens: number;
152
- total_tokens: number;
153
- estimated?: boolean;
154
- }
107
+ import type { Path, Mode, ChatMessage, Usage, ClaudeAgentOptions, AgentDecision } from "./sharedTypes.js";
108
+ export type { Path, Mode, ChatMessage, Usage, ClaudeAgentOptions, AgentDecision };
155
109
  export interface ChatResponse {
156
110
  id: string;
157
111
  created_at: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spectyra/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Spectyra SDK for real-time LLM optimization",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",