@statewavedev/sdk 0.8.0 → 0.9.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,6 +10,8 @@ Official TypeScript SDK for [Statewave](https://github.com/smaramwbc/statewave)
10
10
  >
11
11
  > 📋 **Issues & feature requests:** [statewave/issues](https://github.com/smaramwbc/statewave/issues) (centralized tracker)
12
12
 
13
+ > ⚠️ **v0.9.0 is a breaking change.** The entire SDK surface — request params *and* response fields — is now idiomatic **camelCase** (`subjectId`, `maxTokens`, `createdAt`, `receiptId`, …). The wire protocol is unchanged; the client maps to/from the server's snake_case transparently. `payload`, `metadata`, and `provenance` are passed through verbatim — their inner keys are never rewritten. See [CHANGELOG](CHANGELOG.md#090) for the full rename table and migration steps.
14
+
13
15
  ## Install
14
16
 
15
17
  ```bash
@@ -33,7 +35,7 @@ const swAuth = new StatewaveClient({
33
35
 
34
36
  // Record an episode
35
37
  await sw.createEpisode({
36
- subject_id: "user-42",
38
+ subjectId: "user-42",
37
39
  source: "support-chat",
38
40
  type: "conversation",
39
41
  payload: {
@@ -46,31 +48,31 @@ await sw.createEpisode({
46
48
 
47
49
  // Compile memories (idempotent)
48
50
  const result = await sw.compileMemories("user-42");
49
- console.log(`Created ${result.memories_created} memories`);
51
+ console.log(`Created ${result.memoriesCreated} memories`);
50
52
 
51
53
  // Retrieve ranked, token-bounded context
52
54
  const ctx = await sw.getContext({
53
- subject_id: "user-42",
55
+ subjectId: "user-42",
54
56
  task: "Help with billing",
55
- max_tokens: 300,
57
+ maxTokens: 300,
56
58
  });
57
- console.log(ctx.assembled_context);
59
+ console.log(ctx.assembledContext);
58
60
 
59
61
  // Batch ingestion (up to 100)
60
62
  await sw.createEpisodesBatch([
61
- { subject_id: "user-42", source: "crm", type: "note", payload: { text: "Prefers email" } },
62
- { subject_id: "user-42", source: "crm", type: "note", payload: { text: "Enterprise plan" } },
63
+ { subjectId: "user-42", source: "crm", type: "note", payload: { text: "Prefers email" } },
64
+ { subjectId: "user-42", source: "crm", type: "note", payload: { text: "Enterprise plan" } },
63
65
  ]);
64
66
 
65
67
  // Search memories
66
68
  const facts = await sw.searchMemories({
67
- subject_id: "user-42",
69
+ subjectId: "user-42",
68
70
  kind: "profile_fact",
69
71
  });
70
72
 
71
73
  // Semantic search (requires embeddings)
72
74
  const results = await sw.searchMemories({
73
- subject_id: "user-42",
75
+ subjectId: "user-42",
74
76
  query: "billing",
75
77
  semantic: true,
76
78
  });
@@ -78,7 +80,7 @@ const results = await sw.searchMemories({
78
80
  // List all known subjects
79
81
  const subjects = await sw.listSubjects();
80
82
  for (const s of subjects.subjects) {
81
- console.log(`${s.subject_id}: ${s.episode_count} episodes, ${s.memory_count} memories`);
83
+ console.log(`${s.subjectId}: ${s.episodeCount} episodes, ${s.memoryCount} memories`);
82
84
  }
83
85
 
84
86
  // Get timeline
@@ -89,6 +91,60 @@ console.log(`${timeline.episodes.length} episodes, ${timeline.memories.length} m
89
91
  await sw.deleteSubject("user-42");
90
92
  ```
91
93
 
94
+ ## Governance & audit (v0.8)
95
+
96
+ The SDK surfaces the [state-assembly receipts](https://github.com/smaramwbc/statewave-docs/blob/main/receipts.md) and [sensitivity-labels / policy](https://github.com/smaramwbc/statewave-docs/blob/main/sensitivity-labels.md) layer added in server v0.8.
97
+
98
+ ```typescript
99
+ import { StatewaveClient } from "@statewavedev/sdk";
100
+
101
+ const sw = new StatewaveClient({
102
+ baseUrl: "http://localhost:8100",
103
+ apiKey: "your-key",
104
+ tenantId: "acme",
105
+ });
106
+
107
+ // Per-request opt-in for an immutable audit receipt of the assembly.
108
+ // callerId / callerType feed the sensitivity-label policy engine —
109
+ // when the tenant config sets require_caller_identity=true, missing
110
+ // values 401.
111
+ const bundle = await sw.getContext({
112
+ subjectId: "user-42",
113
+ task: "What plan is this customer on?",
114
+ emitReceipt: true,
115
+ callerId: "agent-7",
116
+ callerType: "support_agent",
117
+ });
118
+
119
+ if (bundle.receiptId) {
120
+ // Receipts are ULID-addressable, tenant-scoped, append-only.
121
+ const receipt = await sw.getReceipt(bundle.receiptId);
122
+ // output.contextHash is a SHA-256 of the bytes delivered to the
123
+ // agent — recompute from bundle.assembledContext to verify integrity.
124
+ console.log(receipt.output.contextHash);
125
+ console.log(`${receipt.selectedEntries.length} entries influenced this bundle`);
126
+ }
127
+
128
+ // List receipts for a subject, cursor-paginated, newest-first.
129
+ const { receipts, nextCursor } = await sw.listReceipts({
130
+ subjectId: "user-42",
131
+ limit: 10,
132
+ });
133
+ for (const r of receipts) {
134
+ console.log(r.receiptId, r.task);
135
+ }
136
+
137
+ // Set per-memory sensitivity labels (server normalizes — dedup, lowercase, trim).
138
+ // Memories with labels become subject to any active policy bundle for the tenant.
139
+ const updated = await sw.setMemoryLabels({
140
+ memoryId: "mem-uuid",
141
+ sensitivityLabels: ["pii", "financial"],
142
+ });
143
+ console.log(updated.sensitivityLabels); // → ["financial", "pii"]
144
+ ```
145
+
146
+ Receipts and the policy engine cooperate: every assembly call records its policy decisions into `receipt.policy.filtersApplied` (one entry per memory the policy fired on) and `receipt.policy.filtersSkipped` (per-rule summary of what didn't fire). In `log_only` mode (the tenant default) the receipt is the full audit trail without filtering; under `enforce` denied memories are dropped before they reach the assembly and the deny is still recorded. See [`receipts.md`](https://github.com/smaramwbc/statewave-docs/blob/main/receipts.md) and [`sensitivity-labels.md`](https://github.com/smaramwbc/statewave-docs/blob/main/sensitivity-labels.md) for the full schemas and policy YAML format.
147
+
92
148
  ## Error handling
93
149
 
94
150
  ```typescript
@@ -122,17 +178,19 @@ See [Privacy & Data Flow](https://github.com/smaramwbc/statewave-docs/blob/main/
122
178
  All response types are fully typed:
123
179
 
124
180
  - `Episode` — raw interaction record
125
- - `Memory` — compiled memory with provenance
181
+ - `Memory` — compiled memory with provenance + optional `sensitivityLabels`
126
182
  - `CompileResult` — compilation response
127
183
  - `SearchResult` — search response
128
- - `ContextBundle` — assembled context with facts, episodes, provenance
184
+ - `ContextBundle` — assembled context with facts, episodes, provenance, optional `receiptId` / `receiptEmitted`
129
185
  - `Timeline` — chronological subject history
130
186
  - `DeleteResult` — deletion confirmation
131
187
  - `BatchCreateResult` — batch ingestion response
132
188
  - `SubjectSummary` — subject with episode/memory counts
133
189
  - `ListSubjectsResult` — paginated subject listing
190
+ - `Receipt` + `ReceiptSelectedEntry` + `ReceiptPolicy` + `ReceiptOutput` — state-assembly audit artifact (v0.8) and its nested shapes
191
+ - `ReceiptList` — cursor-paginated receipt listing
134
192
 
135
- Param types: `CreateEpisodeParams`, `SearchMemoriesParams`, `GetContextParams`
193
+ Param types: `CreateEpisodeParams`, `SearchMemoriesParams`, `GetContextParams`, `ListReceiptsParams`, `SetMemoryLabelsParams`
136
194
 
137
195
  ## Running tests
138
196
 
package/dist/client.d.ts CHANGED
@@ -19,7 +19,7 @@ export declare class StatewaveClient {
19
19
  createEpisode(params: CreateEpisodeParams): Promise<Episode>;
20
20
  createEpisodesBatch(episodes: CreateEpisodeParams[]): Promise<BatchCreateResult>;
21
21
  compileMemories(subjectId: string): Promise<CompileResult>;
22
- /** Submit async compilation — returns immediately with a job_id. */
22
+ /** Submit async compilation — returns immediately with a jobId. */
23
23
  compileMemoriesAsync(subjectId: string): Promise<CompileJob>;
24
24
  /** Poll the status of an async compile job. */
25
25
  getCompileStatus(jobId: string): Promise<CompileJob>;
@@ -31,7 +31,7 @@ export declare class StatewaveClient {
31
31
  searchMemories(params: SearchMemoriesParams): Promise<SearchResult>;
32
32
  getContext(params: GetContextParams): Promise<ContextBundle>;
33
33
  /**
34
- * Replace a memory's sensitivity_labels. Server normalizes
34
+ * Replace a memory's sensitivityLabels. Server normalizes
35
35
  * (dedup + lowercase + trim) and caps at 32 entries. Empty array
36
36
  * clears all labels — the memory becomes untagged and any policy
37
37
  * rule that depends on a label match falls through to default-allow.
@@ -43,7 +43,7 @@ export declare class StatewaveClient {
43
43
  getReceipt(receiptId: string): Promise<Receipt>;
44
44
  /**
45
45
  * List state-assembly receipts for a subject, newest first.
46
- * Cursor-paginated — pass back the previous response's `next_cursor`
46
+ * Cursor-paginated — pass back the previous response's `nextCursor`
47
47
  * to fetch the next page.
48
48
  */
49
49
  listReceipts(params: ListReceiptsParams): Promise<ReceiptList>;
package/dist/client.js CHANGED
@@ -1,3 +1,42 @@
1
+ /**
2
+ * Free-form bags whose contents are user-owned. Their *inner* keys are
3
+ * never rewritten in either direction so arbitrary caller data (which
4
+ * may itself contain snake_case or camelCase keys) round-trips
5
+ * byte-for-byte. The key names themselves are single words, so they are
6
+ * unchanged by case conversion regardless.
7
+ */
8
+ const OPAQUE_KEYS = new Set(["payload", "metadata", "provenance"]);
9
+ function snakeKeyToCamel(key) {
10
+ return key.replace(/_+([a-zA-Z0-9])/g, (_, c) => c.toUpperCase());
11
+ }
12
+ function camelKeyToSnake(key) {
13
+ return key.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
14
+ }
15
+ function isPlainObject(v) {
16
+ return v !== null && typeof v === "object" && !Array.isArray(v);
17
+ }
18
+ function mapKeys(value, convert) {
19
+ if (Array.isArray(value)) {
20
+ return value.map((v) => mapKeys(v, convert));
21
+ }
22
+ if (isPlainObject(value)) {
23
+ const out = {};
24
+ for (const [k, v] of Object.entries(value)) {
25
+ // Opaque bag: keep the verbatim value, don't recurse into it.
26
+ out[convert(k)] = OPAQUE_KEYS.has(k) ? v : mapKeys(v, convert);
27
+ }
28
+ return out;
29
+ }
30
+ return value;
31
+ }
32
+ /** Wire (snake_case) → public SDK shape (camelCase). */
33
+ function fromWire(value) {
34
+ return mapKeys(value, snakeKeyToCamel);
35
+ }
36
+ /** Public SDK shape (camelCase) → wire (snake_case). */
37
+ function toWire(value) {
38
+ return mapKeys(value, camelKeyToSnake);
39
+ }
1
40
  /** Structured error from the Statewave API. */
2
41
  export class StatewaveAPIError extends Error {
3
42
  statusCode;
@@ -47,7 +86,7 @@ export class StatewaveClient {
47
86
  }
48
87
  async createEpisode(params) {
49
88
  return this.post("/v1/episodes", {
50
- subject_id: params.subject_id,
89
+ subjectId: params.subjectId,
51
90
  source: params.source,
52
91
  type: params.type,
53
92
  payload: params.payload,
@@ -57,7 +96,7 @@ export class StatewaveClient {
57
96
  }
58
97
  async createEpisodesBatch(episodes) {
59
98
  return this.post("/v1/episodes/batch", { episodes: episodes.map(e => ({
60
- subject_id: e.subject_id,
99
+ subjectId: e.subjectId,
61
100
  source: e.source,
62
101
  type: e.type,
63
102
  payload: e.payload,
@@ -66,11 +105,11 @@ export class StatewaveClient {
66
105
  })) });
67
106
  }
68
107
  async compileMemories(subjectId) {
69
- return this.post("/v1/memories/compile", { subject_id: subjectId });
108
+ return this.post("/v1/memories/compile", { subjectId });
70
109
  }
71
- /** Submit async compilation — returns immediately with a job_id. */
110
+ /** Submit async compilation — returns immediately with a jobId. */
72
111
  async compileMemoriesAsync(subjectId) {
73
- return this.post("/v1/memories/compile", { subject_id: subjectId, async: true });
112
+ return this.post("/v1/memories/compile", { subjectId, async: true });
74
113
  }
75
114
  /** Poll the status of an async compile job. */
76
115
  async getCompileStatus(jobId) {
@@ -84,15 +123,15 @@ export class StatewaveClient {
84
123
  const start = Date.now();
85
124
  while (Date.now() - start < timeout) {
86
125
  await new Promise(r => setTimeout(r, pollInterval));
87
- const status = await this.getCompileStatus(job.job_id);
126
+ const status = await this.getCompileStatus(job.jobId);
88
127
  if (status.status === "completed" || status.status === "failed") {
89
128
  return status;
90
129
  }
91
130
  }
92
- throw new Error(`Compile job ${job.job_id} did not complete within ${timeout}ms`);
131
+ throw new Error(`Compile job ${job.jobId} did not complete within ${timeout}ms`);
93
132
  }
94
133
  async searchMemories(params) {
95
- const qs = new URLSearchParams({ subject_id: params.subject_id });
134
+ const qs = new URLSearchParams({ subject_id: params.subjectId });
96
135
  if (params.kind)
97
136
  qs.set("kind", params.kind);
98
137
  if (params.query)
@@ -105,34 +144,34 @@ export class StatewaveClient {
105
144
  }
106
145
  async getContext(params) {
107
146
  return this.post("/v1/context", {
108
- subject_id: params.subject_id,
147
+ subjectId: params.subjectId,
109
148
  task: params.task,
110
- ...(params.max_tokens !== undefined && { max_tokens: params.max_tokens }),
111
- ...(params.session_id !== undefined && { session_id: params.session_id }),
112
- ...(params.emit_receipt !== undefined && { emit_receipt: params.emit_receipt }),
113
- ...(params.query_id !== undefined && { query_id: params.query_id }),
114
- ...(params.task_id !== undefined && { task_id: params.task_id }),
115
- ...(params.parent_receipt_id !== undefined && {
116
- parent_receipt_id: params.parent_receipt_id,
149
+ ...(params.maxTokens !== undefined && { maxTokens: params.maxTokens }),
150
+ ...(params.sessionId !== undefined && { sessionId: params.sessionId }),
151
+ ...(params.emitReceipt !== undefined && { emitReceipt: params.emitReceipt }),
152
+ ...(params.queryId !== undefined && { queryId: params.queryId }),
153
+ ...(params.taskId !== undefined && { taskId: params.taskId }),
154
+ ...(params.parentReceiptId !== undefined && {
155
+ parentReceiptId: params.parentReceiptId,
117
156
  }),
118
- ...(params.caller_id !== undefined && { caller_id: params.caller_id }),
119
- ...(params.caller_type !== undefined && { caller_type: params.caller_type }),
157
+ ...(params.callerId !== undefined && { callerId: params.callerId }),
158
+ ...(params.callerType !== undefined && { callerType: params.callerType }),
120
159
  });
121
160
  }
122
161
  // -- Memory labels (#50) ----------------------------------------------
123
162
  /**
124
- * Replace a memory's sensitivity_labels. Server normalizes
163
+ * Replace a memory's sensitivityLabels. Server normalizes
125
164
  * (dedup + lowercase + trim) and caps at 32 entries. Empty array
126
165
  * clears all labels — the memory becomes untagged and any policy
127
166
  * rule that depends on a label match falls through to default-allow.
128
167
  */
129
168
  async setMemoryLabels(params) {
130
- return this.request("PATCH", `/v1/memories/${encodeURIComponent(params.memory_id)}/labels`, { sensitivity_labels: params.sensitivity_labels });
169
+ return this.request("PATCH", `/v1/memories/${encodeURIComponent(params.memoryId)}/labels`, { sensitivityLabels: params.sensitivityLabels });
131
170
  }
132
171
  /** Return just the assembled context string, ready to inject into a prompt. */
133
172
  async getContextString(params) {
134
173
  const bundle = await this.getContext(params);
135
- return bundle.assembled_context;
174
+ return bundle.assembledContext;
136
175
  }
137
176
  // -- Receipts --------------------------------------------------------
138
177
  /** Fetch a single state-assembly receipt by ULID. */
@@ -141,11 +180,11 @@ export class StatewaveClient {
141
180
  }
142
181
  /**
143
182
  * List state-assembly receipts for a subject, newest first.
144
- * Cursor-paginated — pass back the previous response's `next_cursor`
183
+ * Cursor-paginated — pass back the previous response's `nextCursor`
145
184
  * to fetch the next page.
146
185
  */
147
186
  async listReceipts(params) {
148
- const qs = new URLSearchParams({ subject_id: params.subject_id });
187
+ const qs = new URLSearchParams({ subject_id: params.subjectId });
149
188
  if (params.since !== undefined)
150
189
  qs.set("since", params.since);
151
190
  if (params.until !== undefined)
@@ -180,16 +219,17 @@ export class StatewaveClient {
180
219
  }
181
220
  async request(method, path, body) {
182
221
  let lastError;
222
+ const wireBody = body === undefined ? undefined : toWire(body);
183
223
  for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {
184
224
  let resp;
185
225
  try {
186
226
  const headers = { ...this.defaultHeaders };
187
- if (body)
227
+ if (wireBody !== undefined)
188
228
  headers["Content-Type"] = "application/json";
189
229
  resp = await fetch(`${this.baseUrl}${path}`, {
190
230
  method,
191
231
  headers,
192
- body: body ? JSON.stringify(body) : undefined,
232
+ body: wireBody !== undefined ? JSON.stringify(wireBody) : undefined,
193
233
  });
194
234
  }
195
235
  catch (err) {
@@ -202,7 +242,7 @@ export class StatewaveClient {
202
242
  throw new StatewaveConnectionError(lastError.message);
203
243
  }
204
244
  if (resp.ok) {
205
- return resp.json();
245
+ return fromWire(await resp.json());
206
246
  }
207
247
  // Check if retryable status
208
248
  if (this.retryConfig.retryOnStatus.includes(resp.status) && attempt < this.retryConfig.maxRetries) {
package/dist/types.d.ts CHANGED
@@ -1,24 +1,33 @@
1
- /** Statewave API types — mirrors the backend contract. */
1
+ /**
2
+ * Statewave API types.
3
+ *
4
+ * The public SDK surface is camelCase, idiomatic TypeScript. The
5
+ * Statewave HTTP API speaks snake_case on the wire; `StatewaveClient`
6
+ * transparently maps between the two in both directions, so callers
7
+ * never see a snake_case key. The free-form `payload`, `metadata`, and
8
+ * `provenance` bags are passed through verbatim — their inner keys are
9
+ * never rewritten, so arbitrary user data round-trips losslessly.
10
+ */
2
11
  export interface Episode {
3
12
  id: string;
4
- subject_id: string;
13
+ subjectId: string;
5
14
  source: string;
6
15
  type: string;
7
16
  payload: Record<string, unknown>;
8
17
  metadata: Record<string, unknown>;
9
18
  provenance: Record<string, unknown>;
10
- created_at: string;
19
+ createdAt: string;
11
20
  }
12
21
  export interface Memory {
13
22
  id: string;
14
- subject_id: string;
23
+ subjectId: string;
15
24
  kind: string;
16
25
  content: string;
17
26
  summary: string;
18
27
  confidence: number;
19
- valid_from: string;
20
- valid_to: string | null;
21
- source_episode_ids: string[];
28
+ validFrom: string;
29
+ validTo: string | null;
30
+ sourceEpisodeIds: string[];
22
31
  metadata: Record<string, unknown>;
23
32
  status: string;
24
33
  /**
@@ -26,31 +35,31 @@ export interface Memory {
26
35
  * policy layer (#50). Empty = untagged = policy default-allow.
27
36
  * Older servers without the policy layer omit the field.
28
37
  */
29
- sensitivity_labels?: string[];
30
- created_at: string;
31
- updated_at: string;
38
+ sensitivityLabels?: string[];
39
+ createdAt: string;
40
+ updatedAt: string;
32
41
  }
33
42
  export interface CompileResult {
34
- subject_id: string;
35
- memories_created: number;
43
+ subjectId: string;
44
+ memoriesCreated: number;
36
45
  memories: Memory[];
37
46
  }
38
47
  export interface SearchResult {
39
48
  memories: Memory[];
40
49
  }
41
50
  export interface ContextBundle {
42
- subject_id: string;
51
+ subjectId: string;
43
52
  task: string;
44
53
  facts: Memory[];
45
54
  episodes: Episode[];
46
55
  procedures: Memory[];
47
56
  provenance: Record<string, unknown>;
48
- assembled_context: string;
49
- token_estimate: number;
57
+ assembledContext: string;
58
+ tokenEstimate: number;
50
59
  /** ULID of the state-assembly receipt, when one was emitted. */
51
- receipt_id?: string | null;
60
+ receiptId?: string | null;
52
61
  /** True iff a receipt was successfully written for this call. */
53
- receipt_emitted?: boolean;
62
+ receiptEmitted?: boolean;
54
63
  }
55
64
  /**
56
65
  * One entry inside a state-assembly receipt. Strict-superset shape —
@@ -61,88 +70,88 @@ export interface ContextBundle {
61
70
  export interface ReceiptSelectedEntry {
62
71
  type: "memory" | "episode";
63
72
  /** Present when type === "memory". */
64
- memory_id?: string;
73
+ memoryId?: string;
65
74
  /** Present when type === "memory". */
66
75
  kind?: string;
67
- valid_from?: string | null;
68
- valid_to?: string | null;
69
- supersession_status?: "active" | "superseded" | "tombstoned";
70
- source_episode_ids?: string[];
71
- provenance_hash?: string;
72
- fact_key?: string | null;
73
- conflict_status?: "none" | "merged" | "overridden" | "unresolved";
76
+ validFrom?: string | null;
77
+ validTo?: string | null;
78
+ supersessionStatus?: "active" | "superseded" | "tombstoned";
79
+ sourceEpisodeIds?: string[];
80
+ provenanceHash?: string;
81
+ factKey?: string | null;
82
+ conflictStatus?: "none" | "merged" | "overridden" | "unresolved";
74
83
  /** Present when type === "episode". */
75
- episode_id?: string;
84
+ episodeId?: string;
76
85
  source?: string;
77
- event_type?: string;
78
- occurred_at?: string | null;
86
+ eventType?: string;
87
+ occurredAt?: string | null;
79
88
  /** Final position in the assembled bundle. */
80
89
  rank: number;
81
90
  score?: number | null;
82
91
  }
83
92
  export interface ReceiptPolicy {
84
- policy_bundle_hash: string | null;
85
- filters_applied: unknown[];
86
- filters_skipped: unknown[];
93
+ policyBundleHash: string | null;
94
+ filtersApplied: unknown[];
95
+ filtersSkipped: unknown[];
87
96
  mode: "log_only" | "enforce";
88
97
  }
89
98
  export interface ReceiptOutput {
90
- context_hash: string;
91
- context_size_bytes: number;
92
- canonicalization_version: number;
93
- token_estimate: number;
99
+ contextHash: string;
100
+ contextSizeBytes: number;
101
+ canonicalizationVersion: number;
102
+ tokenEstimate: number;
94
103
  }
95
104
  /**
96
105
  * Immutable per-retrieval audit artifact for a single context assembly.
97
106
  * See `docs/state-assembly-receipts.md` in the server repository.
98
107
  */
99
108
  export interface Receipt {
100
- receipt_id: string;
101
- parent_receipt_id: string | null;
109
+ receiptId: string;
110
+ parentReceiptId: string | null;
102
111
  mode: "retrieval" | string;
103
- query_id: string | null;
104
- task_id: string | null;
105
- tenant_id: string | null;
106
- subject_id: string;
112
+ queryId: string | null;
113
+ taskId: string | null;
114
+ tenantId: string | null;
115
+ subjectId: string;
107
116
  task: string;
108
- as_of: string;
109
- created_at: string;
110
- selected_entries: ReceiptSelectedEntry[];
117
+ asOf: string;
118
+ createdAt: string;
119
+ selectedEntries: ReceiptSelectedEntry[];
111
120
  policy: ReceiptPolicy;
112
121
  output: ReceiptOutput;
113
122
  region: string | null;
114
- receipt_signature: string | null;
123
+ receiptSignature: string | null;
115
124
  }
116
125
  export interface ReceiptList {
117
126
  receipts: Receipt[];
118
127
  /** Pass back as the `cursor` param to fetch the next page; null when no more. */
119
- next_cursor: string | null;
128
+ nextCursor: string | null;
120
129
  }
121
130
  export interface ListReceiptsParams {
122
- subject_id: string;
131
+ subjectId: string;
123
132
  since?: string;
124
133
  until?: string;
125
134
  cursor?: string;
126
135
  limit?: number;
127
136
  }
128
137
  export interface Timeline {
129
- subject_id: string;
138
+ subjectId: string;
130
139
  episodes: Episode[];
131
140
  memories: Memory[];
132
141
  }
133
142
  export interface DeleteResult {
134
- subject_id: string;
135
- episodes_deleted: number;
136
- memories_deleted: number;
143
+ subjectId: string;
144
+ episodesDeleted: number;
145
+ memoriesDeleted: number;
137
146
  }
138
147
  export interface BatchCreateResult {
139
- episodes_created: number;
148
+ episodesCreated: number;
140
149
  episodes: Episode[];
141
150
  }
142
151
  export interface SubjectSummary {
143
- subject_id: string;
144
- episode_count: number;
145
- memory_count: number;
152
+ subjectId: string;
153
+ episodeCount: number;
154
+ memoryCount: number;
146
155
  }
147
156
  export interface ListSubjectsResult {
148
157
  subjects: SubjectSummary[];
@@ -150,59 +159,59 @@ export interface ListSubjectsResult {
150
159
  }
151
160
  /** Status of an async compile job. */
152
161
  export interface CompileJob {
153
- job_id: string;
162
+ jobId: string;
154
163
  status: "pending" | "running" | "completed" | "failed";
155
- subject_id: string;
156
- memories_created?: number;
164
+ subjectId: string;
165
+ memoriesCreated?: number;
157
166
  memories?: Memory[];
158
167
  error?: string;
159
168
  }
160
169
  export interface CreateEpisodeParams {
161
- subject_id: string;
170
+ subjectId: string;
162
171
  source: string;
163
172
  type: string;
164
173
  payload: Record<string, unknown>;
165
174
  metadata?: Record<string, unknown>;
166
175
  provenance?: Record<string, unknown>;
167
- session_id?: string;
176
+ sessionId?: string;
168
177
  }
169
178
  export interface SearchMemoriesParams {
170
- subject_id: string;
179
+ subjectId: string;
171
180
  kind?: string;
172
181
  query?: string;
173
182
  semantic?: boolean;
174
183
  limit?: number;
175
184
  }
176
185
  export interface GetContextParams {
177
- subject_id: string;
186
+ subjectId: string;
178
187
  task: string;
179
- max_tokens?: number;
180
- session_id?: string;
188
+ maxTokens?: number;
189
+ sessionId?: string;
181
190
  /**
182
191
  * Opt in to emitting a state-assembly receipt for this call. The
183
192
  * tenant config can also force emission on or off independently of
184
193
  * this flag. See `docs/state-assembly-receipts.md` in the server
185
194
  * repository.
186
195
  */
187
- emit_receipt?: boolean;
188
- query_id?: string;
189
- task_id?: string;
190
- parent_receipt_id?: string;
196
+ emitReceipt?: boolean;
197
+ queryId?: string;
198
+ taskId?: string;
199
+ parentReceiptId?: string;
191
200
  /**
192
201
  * Caller identity consumed by the sensitivity-label policy layer
193
202
  * (#50). When the tenant config sets `require_caller_identity:
194
- * true`, both `caller_id` and `caller_type` are mandatory.
203
+ * true`, both `callerId` and `callerType` are mandatory.
195
204
  */
196
- caller_id?: string;
197
- caller_type?: string;
205
+ callerId?: string;
206
+ callerType?: string;
198
207
  }
199
208
  export interface SetMemoryLabelsParams {
200
- memory_id: string;
209
+ memoryId: string;
201
210
  /**
202
211
  * Replacement label list. Server normalizes (dedup + lowercase +
203
212
  * trim) and caps at 32 entries. Empty list clears all labels.
204
213
  */
205
- sensitivity_labels: string[];
214
+ sensitivityLabels: string[];
206
215
  }
207
216
  export interface ClientOptions {
208
217
  baseUrl?: string;
package/dist/types.js CHANGED
@@ -1,2 +1,11 @@
1
- /** Statewave API types — mirrors the backend contract. */
1
+ /**
2
+ * Statewave API types.
3
+ *
4
+ * The public SDK surface is camelCase, idiomatic TypeScript. The
5
+ * Statewave HTTP API speaks snake_case on the wire; `StatewaveClient`
6
+ * transparently maps between the two in both directions, so callers
7
+ * never see a snake_case key. The free-form `payload`, `metadata`, and
8
+ * `provenance` bags are passed through verbatim — their inner keys are
9
+ * never rewritten, so arbitrary user data round-trips losslessly.
10
+ */
2
11
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statewavedev/sdk",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Official TypeScript SDK for Statewave — the open-source memory runtime for AI agents.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",