@statewavedev/sdk 0.8.0 → 0.10.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 +136 -14
- package/dist/client.d.ts +33 -4
- package/dist/client.js +138 -26
- package/dist/types.d.ts +218 -73
- package/dist/types.js +10 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,14 @@ 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
|
+
|
|
15
|
+
> **New to Statewave?** This SDK is a thin client for a running **Statewave
|
|
16
|
+
> server**. If you don't have one yet, the
|
|
17
|
+
> [Getting Started guide](https://github.com/smaramwbc/statewave-docs/blob/main/getting-started.md)
|
|
18
|
+
> brings one up with Docker Compose in about 5 minutes. Every example below
|
|
19
|
+
> assumes a server reachable at `http://localhost:8100`.
|
|
20
|
+
|
|
13
21
|
## Install
|
|
14
22
|
|
|
15
23
|
```bash
|
|
@@ -33,7 +41,7 @@ const swAuth = new StatewaveClient({
|
|
|
33
41
|
|
|
34
42
|
// Record an episode
|
|
35
43
|
await sw.createEpisode({
|
|
36
|
-
|
|
44
|
+
subjectId: "user-42",
|
|
37
45
|
source: "support-chat",
|
|
38
46
|
type: "conversation",
|
|
39
47
|
payload: {
|
|
@@ -46,31 +54,31 @@ await sw.createEpisode({
|
|
|
46
54
|
|
|
47
55
|
// Compile memories (idempotent)
|
|
48
56
|
const result = await sw.compileMemories("user-42");
|
|
49
|
-
console.log(`Created ${result.
|
|
57
|
+
console.log(`Created ${result.memoriesCreated} memories`);
|
|
50
58
|
|
|
51
59
|
// Retrieve ranked, token-bounded context
|
|
52
60
|
const ctx = await sw.getContext({
|
|
53
|
-
|
|
61
|
+
subjectId: "user-42",
|
|
54
62
|
task: "Help with billing",
|
|
55
|
-
|
|
63
|
+
maxTokens: 300,
|
|
56
64
|
});
|
|
57
|
-
console.log(ctx.
|
|
65
|
+
console.log(ctx.assembledContext);
|
|
58
66
|
|
|
59
67
|
// Batch ingestion (up to 100)
|
|
60
68
|
await sw.createEpisodesBatch([
|
|
61
|
-
{
|
|
62
|
-
{
|
|
69
|
+
{ subjectId: "user-42", source: "crm", type: "note", payload: { text: "Prefers email" } },
|
|
70
|
+
{ subjectId: "user-42", source: "crm", type: "note", payload: { text: "Enterprise plan" } },
|
|
63
71
|
]);
|
|
64
72
|
|
|
65
73
|
// Search memories
|
|
66
74
|
const facts = await sw.searchMemories({
|
|
67
|
-
|
|
75
|
+
subjectId: "user-42",
|
|
68
76
|
kind: "profile_fact",
|
|
69
77
|
});
|
|
70
78
|
|
|
71
79
|
// Semantic search (requires embeddings)
|
|
72
80
|
const results = await sw.searchMemories({
|
|
73
|
-
|
|
81
|
+
subjectId: "user-42",
|
|
74
82
|
query: "billing",
|
|
75
83
|
semantic: true,
|
|
76
84
|
});
|
|
@@ -78,7 +86,7 @@ const results = await sw.searchMemories({
|
|
|
78
86
|
// List all known subjects
|
|
79
87
|
const subjects = await sw.listSubjects();
|
|
80
88
|
for (const s of subjects.subjects) {
|
|
81
|
-
console.log(`${s.
|
|
89
|
+
console.log(`${s.subjectId}: ${s.episodeCount} episodes, ${s.memoryCount} memories`);
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
// Get timeline
|
|
@@ -89,6 +97,113 @@ console.log(`${timeline.episodes.length} episodes, ${timeline.memories.length} m
|
|
|
89
97
|
await sw.deleteSubject("user-42");
|
|
90
98
|
```
|
|
91
99
|
|
|
100
|
+
## Governance & audit (v0.8)
|
|
101
|
+
|
|
102
|
+
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.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { StatewaveClient } from "@statewavedev/sdk";
|
|
106
|
+
|
|
107
|
+
const sw = new StatewaveClient({
|
|
108
|
+
baseUrl: "http://localhost:8100",
|
|
109
|
+
apiKey: "your-key",
|
|
110
|
+
tenantId: "acme",
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Per-request opt-in for an immutable audit receipt of the assembly.
|
|
114
|
+
// callerId / callerType feed the sensitivity-label policy engine —
|
|
115
|
+
// when the tenant config sets require_caller_identity=true, missing
|
|
116
|
+
// values 401.
|
|
117
|
+
const bundle = await sw.getContext({
|
|
118
|
+
subjectId: "user-42",
|
|
119
|
+
task: "What plan is this customer on?",
|
|
120
|
+
emitReceipt: true,
|
|
121
|
+
callerId: "agent-7",
|
|
122
|
+
callerType: "support_agent",
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (bundle.receiptId) {
|
|
126
|
+
// Receipts are ULID-addressable, tenant-scoped, append-only.
|
|
127
|
+
const receipt = await sw.getReceipt(bundle.receiptId);
|
|
128
|
+
// output.contextHash is a SHA-256 of the bytes delivered to the
|
|
129
|
+
// agent — recompute from bundle.assembledContext to verify integrity.
|
|
130
|
+
console.log(receipt.output.contextHash);
|
|
131
|
+
console.log(`${receipt.selectedEntries.length} entries influenced this bundle`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// List receipts for a subject, cursor-paginated, newest-first.
|
|
135
|
+
const { receipts, nextCursor } = await sw.listReceipts({
|
|
136
|
+
subjectId: "user-42",
|
|
137
|
+
limit: 10,
|
|
138
|
+
});
|
|
139
|
+
for (const r of receipts) {
|
|
140
|
+
console.log(r.receiptId, r.task);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Set per-memory sensitivity labels (server normalizes — dedup, lowercase, trim).
|
|
144
|
+
// Memories with labels become subject to any active policy bundle for the tenant.
|
|
145
|
+
const updated = await sw.setMemoryLabels({
|
|
146
|
+
memoryId: "mem-uuid",
|
|
147
|
+
sensitivityLabels: ["pii", "financial"],
|
|
148
|
+
});
|
|
149
|
+
console.log(updated.sensitivityLabels); // → ["financial", "pii"]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
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.
|
|
153
|
+
|
|
154
|
+
## Support-agent endpoints
|
|
155
|
+
|
|
156
|
+
Statewave's support wedge — customer health scoring, SLA tracking, resolution state, and structured escalation briefs — is exposed through ergonomic SDK methods (server v0.6+).
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import { StatewaveClient } from "@statewavedev/sdk";
|
|
160
|
+
|
|
161
|
+
const sw = new StatewaveClient("http://localhost:8100");
|
|
162
|
+
|
|
163
|
+
// Customer health score (0–100) with the explainable factors behind it.
|
|
164
|
+
const health = await sw.getHealth("customer:globex");
|
|
165
|
+
console.log(`${health.score}/100 — ${health.state}`);
|
|
166
|
+
for (const f of health.factors) {
|
|
167
|
+
console.log(` ${f.signal}: ${f.impact >= 0 ? "+" : ""}${f.impact} (${f.detail})`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// SLA metrics — first-response / resolution times and breach counts.
|
|
171
|
+
// Thresholds are optional; they default server-side to 5 min / 24 h.
|
|
172
|
+
const sla = await sw.getSLA({
|
|
173
|
+
subjectId: "customer:globex",
|
|
174
|
+
firstResponseThresholdMinutes: 10,
|
|
175
|
+
resolutionThresholdHours: 48,
|
|
176
|
+
});
|
|
177
|
+
console.log(`${sla.resolvedSessions}/${sla.totalSessions} resolved, ${sla.resolutionBreachCount} SLA breaches`);
|
|
178
|
+
|
|
179
|
+
// Track resolution state for a session (upserts by subject + session).
|
|
180
|
+
await sw.createResolution({
|
|
181
|
+
subjectId: "customer:globex",
|
|
182
|
+
sessionId: "ticket-8842",
|
|
183
|
+
status: "resolved",
|
|
184
|
+
resolutionSummary: "Issued refund for the duplicate charge",
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// List resolutions, optionally filtered by status.
|
|
188
|
+
const openItems = await sw.listResolutions({
|
|
189
|
+
subjectId: "customer:globex",
|
|
190
|
+
status: "open",
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Generate a handoff context pack for escalation or shift change.
|
|
194
|
+
// `handoffNotes` is a pre-rendered markdown brief for human or LLM use.
|
|
195
|
+
const handoff = await sw.createHandoff({
|
|
196
|
+
subjectId: "customer:globex",
|
|
197
|
+
sessionId: "ticket-8842",
|
|
198
|
+
reason: "escalation",
|
|
199
|
+
callerId: "agent-7",
|
|
200
|
+
callerType: "support_agent",
|
|
201
|
+
});
|
|
202
|
+
console.log(handoff.handoffNotes);
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
`getHealth`, `getSLA`, `createResolution`, `listResolutions`, and `createHandoff` respect the same auth, tenant-scoping, and retry behaviour as the rest of the client. `createHandoff` shares `getContext`'s caller-identity gate — when the tenant config sets `require_caller_identity: true`, both `callerId` and `callerType` are mandatory.
|
|
206
|
+
|
|
92
207
|
## Error handling
|
|
93
208
|
|
|
94
209
|
```typescript
|
|
@@ -122,17 +237,24 @@ See [Privacy & Data Flow](https://github.com/smaramwbc/statewave-docs/blob/main/
|
|
|
122
237
|
All response types are fully typed:
|
|
123
238
|
|
|
124
239
|
- `Episode` — raw interaction record
|
|
125
|
-
- `Memory` — compiled memory with provenance
|
|
240
|
+
- `Memory` — compiled memory with provenance + optional `sensitivityLabels`
|
|
126
241
|
- `CompileResult` — compilation response
|
|
127
242
|
- `SearchResult` — search response
|
|
128
|
-
- `ContextBundle` — assembled context with facts, episodes, provenance
|
|
243
|
+
- `ContextBundle` — assembled context with facts, episodes, provenance, optional `receiptId` / `receiptEmitted`
|
|
129
244
|
- `Timeline` — chronological subject history
|
|
130
245
|
- `DeleteResult` — deletion confirmation
|
|
131
246
|
- `BatchCreateResult` — batch ingestion response
|
|
132
247
|
- `SubjectSummary` — subject with episode/memory counts
|
|
133
248
|
- `ListSubjectsResult` — paginated subject listing
|
|
134
|
-
|
|
135
|
-
|
|
249
|
+
- `Receipt` + `ReceiptSelectedEntry` + `ReceiptPolicy` + `ReceiptOutput` — state-assembly audit artifact (v0.8) and its nested shapes
|
|
250
|
+
- `ReceiptList` — cursor-paginated receipt listing
|
|
251
|
+
- `Health` + `HealthFactor` — customer health score and its explainable factors
|
|
252
|
+
- `SLASummary` + `SessionSLA` — SLA metrics, aggregate and per-session
|
|
253
|
+
- `Handoff` + `ResolutionSummaryItem` — handoff context pack and its prior-resolution items
|
|
254
|
+
- `Resolution` — resolution tracking record
|
|
255
|
+
- `HealthState` / `ResolutionStatus` — string-literal status unions
|
|
256
|
+
|
|
257
|
+
Param types: `CreateEpisodeParams`, `SearchMemoriesParams`, `GetContextParams`, `ListReceiptsParams`, `SetMemoryLabelsParams`, `GetSLAParams`, `CreateHandoffParams`, `CreateResolutionParams`, `ListResolutionsParams`
|
|
136
258
|
|
|
137
259
|
## Running tests
|
|
138
260
|
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BatchCreateResult, ClientOptions, CompileJob, CompileResult, ContextBundle, CreateEpisodeParams, DeleteResult, Episode, GetContextParams, ListReceiptsParams, ListSubjectsResult, Memory, Receipt, ReceiptList, SearchMemoriesParams, SearchResult, SetMemoryLabelsParams, Timeline } from "./types.js";
|
|
1
|
+
import type { BatchCreateResult, ClientOptions, CompileJob, CompileResult, ContextBundle, CreateEpisodeParams, CreateHandoffParams, CreateResolutionParams, DeleteResult, Episode, GetContextParams, GetSLAParams, Handoff, Health, ListReceiptsParams, ListResolutionsParams, ListSubjectsResult, Memory, Receipt, ReceiptList, Resolution, SLASummary, SearchMemoriesParams, SearchResult, SetMemoryLabelsParams, Timeline } from "./types.js";
|
|
2
2
|
/** Structured error from the Statewave API. */
|
|
3
3
|
export declare class StatewaveAPIError extends Error {
|
|
4
4
|
readonly statusCode: number;
|
|
@@ -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
|
|
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
|
|
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,10 +43,39 @@ 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 `
|
|
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>;
|
|
50
|
+
/**
|
|
51
|
+
* Compute the customer health score (0–100) for a subject, with the
|
|
52
|
+
* explainable factors that drove it. Backs proactive risk triage.
|
|
53
|
+
*/
|
|
54
|
+
getHealth(subjectId: string): Promise<Health>;
|
|
55
|
+
/**
|
|
56
|
+
* Compute SLA metrics for a subject — first-response and resolution
|
|
57
|
+
* times plus breach flags, aggregated across the subject's sessions.
|
|
58
|
+
* Both thresholds fall back to the server defaults (5 minutes /
|
|
59
|
+
* 24 hours) when omitted.
|
|
60
|
+
*/
|
|
61
|
+
getSLA(params: GetSLAParams): Promise<SLASummary>;
|
|
62
|
+
/**
|
|
63
|
+
* Generate a handoff context pack — a structured escalation brief for
|
|
64
|
+
* shift change or agent transfer. Same caller-identity gate as
|
|
65
|
+
* `getContext`: when the tenant sets `require_caller_identity: true`,
|
|
66
|
+
* both `callerId` and `callerType` are mandatory.
|
|
67
|
+
*/
|
|
68
|
+
createHandoff(params: CreateHandoffParams): Promise<Handoff>;
|
|
69
|
+
/**
|
|
70
|
+
* Create or update a resolution record for a support session.
|
|
71
|
+
* Upserts by `subjectId` + `sessionId`.
|
|
72
|
+
*/
|
|
73
|
+
createResolution(params: CreateResolutionParams): Promise<Resolution>;
|
|
74
|
+
/**
|
|
75
|
+
* List resolution records for a subject, optionally filtered to a
|
|
76
|
+
* single status.
|
|
77
|
+
*/
|
|
78
|
+
listResolutions(params: ListResolutionsParams): Promise<Resolution[]>;
|
|
50
79
|
getTimeline(subjectId: string): Promise<Timeline>;
|
|
51
80
|
deleteSubject(subjectId: string): Promise<DeleteResult>;
|
|
52
81
|
listSubjects(params?: {
|
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
|
-
|
|
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
|
-
|
|
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", {
|
|
108
|
+
return this.post("/v1/memories/compile", { subjectId });
|
|
70
109
|
}
|
|
71
|
-
/** Submit async compilation — returns immediately with a
|
|
110
|
+
/** Submit async compilation — returns immediately with a jobId. */
|
|
72
111
|
async compileMemoriesAsync(subjectId) {
|
|
73
|
-
return this.post("/v1/memories/compile", {
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
147
|
+
subjectId: params.subjectId,
|
|
109
148
|
task: params.task,
|
|
110
|
-
...(params.
|
|
111
|
-
...(params.
|
|
112
|
-
...(params.
|
|
113
|
-
...(params.
|
|
114
|
-
...(params.
|
|
115
|
-
...(params.
|
|
116
|
-
|
|
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.
|
|
119
|
-
...(params.
|
|
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
|
|
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.
|
|
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.
|
|
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 `
|
|
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.
|
|
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)
|
|
@@ -156,6 +195,78 @@ export class StatewaveClient {
|
|
|
156
195
|
qs.set("limit", String(params.limit));
|
|
157
196
|
return this.get(`/v1/receipts?${qs}`);
|
|
158
197
|
}
|
|
198
|
+
// -- Support: health, SLA, handoff, resolutions ----------------------
|
|
199
|
+
/**
|
|
200
|
+
* Compute the customer health score (0–100) for a subject, with the
|
|
201
|
+
* explainable factors that drove it. Backs proactive risk triage.
|
|
202
|
+
*/
|
|
203
|
+
async getHealth(subjectId) {
|
|
204
|
+
return this.get(`/v1/subjects/${encodeURIComponent(subjectId)}/health`);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Compute SLA metrics for a subject — first-response and resolution
|
|
208
|
+
* times plus breach flags, aggregated across the subject's sessions.
|
|
209
|
+
* Both thresholds fall back to the server defaults (5 minutes /
|
|
210
|
+
* 24 hours) when omitted.
|
|
211
|
+
*/
|
|
212
|
+
async getSLA(params) {
|
|
213
|
+
const qs = new URLSearchParams();
|
|
214
|
+
if (params.firstResponseThresholdMinutes !== undefined) {
|
|
215
|
+
qs.set("first_response_threshold_minutes", String(params.firstResponseThresholdMinutes));
|
|
216
|
+
}
|
|
217
|
+
if (params.resolutionThresholdHours !== undefined) {
|
|
218
|
+
qs.set("resolution_threshold_hours", String(params.resolutionThresholdHours));
|
|
219
|
+
}
|
|
220
|
+
const query = qs.toString();
|
|
221
|
+
return this.get(`/v1/subjects/${encodeURIComponent(params.subjectId)}/sla${query ? `?${query}` : ""}`);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Generate a handoff context pack — a structured escalation brief for
|
|
225
|
+
* shift change or agent transfer. Same caller-identity gate as
|
|
226
|
+
* `getContext`: when the tenant sets `require_caller_identity: true`,
|
|
227
|
+
* both `callerId` and `callerType` are mandatory.
|
|
228
|
+
*/
|
|
229
|
+
async createHandoff(params) {
|
|
230
|
+
return this.post("/v1/handoff", {
|
|
231
|
+
subjectId: params.subjectId,
|
|
232
|
+
sessionId: params.sessionId,
|
|
233
|
+
...(params.reason !== undefined && { reason: params.reason }),
|
|
234
|
+
...(params.maxTokens !== undefined && { maxTokens: params.maxTokens }),
|
|
235
|
+
...(params.emitReceipt !== undefined && { emitReceipt: params.emitReceipt }),
|
|
236
|
+
...(params.queryId !== undefined && { queryId: params.queryId }),
|
|
237
|
+
...(params.taskId !== undefined && { taskId: params.taskId }),
|
|
238
|
+
...(params.parentReceiptId !== undefined && {
|
|
239
|
+
parentReceiptId: params.parentReceiptId,
|
|
240
|
+
}),
|
|
241
|
+
...(params.callerId !== undefined && { callerId: params.callerId }),
|
|
242
|
+
...(params.callerType !== undefined && { callerType: params.callerType }),
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Create or update a resolution record for a support session.
|
|
247
|
+
* Upserts by `subjectId` + `sessionId`.
|
|
248
|
+
*/
|
|
249
|
+
async createResolution(params) {
|
|
250
|
+
return this.post("/v1/resolutions", {
|
|
251
|
+
subjectId: params.subjectId,
|
|
252
|
+
sessionId: params.sessionId,
|
|
253
|
+
...(params.status !== undefined && { status: params.status }),
|
|
254
|
+
...(params.resolutionSummary !== undefined && {
|
|
255
|
+
resolutionSummary: params.resolutionSummary,
|
|
256
|
+
}),
|
|
257
|
+
...(params.metadata !== undefined && { metadata: params.metadata }),
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* List resolution records for a subject, optionally filtered to a
|
|
262
|
+
* single status.
|
|
263
|
+
*/
|
|
264
|
+
async listResolutions(params) {
|
|
265
|
+
const qs = new URLSearchParams({ subject_id: params.subjectId });
|
|
266
|
+
if (params.status !== undefined)
|
|
267
|
+
qs.set("status", params.status);
|
|
268
|
+
return this.get(`/v1/resolutions?${qs}`);
|
|
269
|
+
}
|
|
159
270
|
async getTimeline(subjectId) {
|
|
160
271
|
return this.get(`/v1/timeline?subject_id=${encodeURIComponent(subjectId)}`);
|
|
161
272
|
}
|
|
@@ -180,16 +291,17 @@ export class StatewaveClient {
|
|
|
180
291
|
}
|
|
181
292
|
async request(method, path, body) {
|
|
182
293
|
let lastError;
|
|
294
|
+
const wireBody = body === undefined ? undefined : toWire(body);
|
|
183
295
|
for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {
|
|
184
296
|
let resp;
|
|
185
297
|
try {
|
|
186
298
|
const headers = { ...this.defaultHeaders };
|
|
187
|
-
if (
|
|
299
|
+
if (wireBody !== undefined)
|
|
188
300
|
headers["Content-Type"] = "application/json";
|
|
189
301
|
resp = await fetch(`${this.baseUrl}${path}`, {
|
|
190
302
|
method,
|
|
191
303
|
headers,
|
|
192
|
-
body:
|
|
304
|
+
body: wireBody !== undefined ? JSON.stringify(wireBody) : undefined,
|
|
193
305
|
});
|
|
194
306
|
}
|
|
195
307
|
catch (err) {
|
|
@@ -202,7 +314,7 @@ export class StatewaveClient {
|
|
|
202
314
|
throw new StatewaveConnectionError(lastError.message);
|
|
203
315
|
}
|
|
204
316
|
if (resp.ok) {
|
|
205
|
-
return resp.json();
|
|
317
|
+
return fromWire(await resp.json());
|
|
206
318
|
}
|
|
207
319
|
// Check if retryable status
|
|
208
320
|
if (this.retryConfig.retryOnStatus.includes(resp.status) && attempt < this.retryConfig.maxRetries) {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,24 +1,33 @@
|
|
|
1
|
-
/**
|
|
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
|
-
|
|
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
|
-
|
|
19
|
+
createdAt: string;
|
|
11
20
|
}
|
|
12
21
|
export interface Memory {
|
|
13
22
|
id: string;
|
|
14
|
-
|
|
23
|
+
subjectId: string;
|
|
15
24
|
kind: string;
|
|
16
25
|
content: string;
|
|
17
26
|
summary: string;
|
|
18
27
|
confidence: number;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
sensitivityLabels?: string[];
|
|
39
|
+
createdAt: string;
|
|
40
|
+
updatedAt: string;
|
|
32
41
|
}
|
|
33
42
|
export interface CompileResult {
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
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
|
-
|
|
49
|
-
|
|
57
|
+
assembledContext: string;
|
|
58
|
+
tokenEstimate: number;
|
|
50
59
|
/** ULID of the state-assembly receipt, when one was emitted. */
|
|
51
|
-
|
|
60
|
+
receiptId?: string | null;
|
|
52
61
|
/** True iff a receipt was successfully written for this call. */
|
|
53
|
-
|
|
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
|
-
|
|
73
|
+
memoryId?: string;
|
|
65
74
|
/** Present when type === "memory". */
|
|
66
75
|
kind?: string;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
84
|
+
episodeId?: string;
|
|
76
85
|
source?: string;
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
93
|
+
policyBundleHash: string | null;
|
|
94
|
+
filtersApplied: unknown[];
|
|
95
|
+
filtersSkipped: unknown[];
|
|
87
96
|
mode: "log_only" | "enforce";
|
|
88
97
|
}
|
|
89
98
|
export interface ReceiptOutput {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
101
|
-
|
|
109
|
+
receiptId: string;
|
|
110
|
+
parentReceiptId: string | null;
|
|
102
111
|
mode: "retrieval" | string;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
112
|
+
queryId: string | null;
|
|
113
|
+
taskId: string | null;
|
|
114
|
+
tenantId: string | null;
|
|
115
|
+
subjectId: string;
|
|
107
116
|
task: string;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
117
|
+
asOf: string;
|
|
118
|
+
createdAt: string;
|
|
119
|
+
selectedEntries: ReceiptSelectedEntry[];
|
|
111
120
|
policy: ReceiptPolicy;
|
|
112
121
|
output: ReceiptOutput;
|
|
113
122
|
region: string | null;
|
|
114
|
-
|
|
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
|
-
|
|
128
|
+
nextCursor: string | null;
|
|
120
129
|
}
|
|
121
130
|
export interface ListReceiptsParams {
|
|
122
|
-
|
|
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
|
-
|
|
138
|
+
subjectId: string;
|
|
130
139
|
episodes: Episode[];
|
|
131
140
|
memories: Memory[];
|
|
132
141
|
}
|
|
133
142
|
export interface DeleteResult {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
143
|
+
subjectId: string;
|
|
144
|
+
episodesDeleted: number;
|
|
145
|
+
memoriesDeleted: number;
|
|
137
146
|
}
|
|
138
147
|
export interface BatchCreateResult {
|
|
139
|
-
|
|
148
|
+
episodesCreated: number;
|
|
140
149
|
episodes: Episode[];
|
|
141
150
|
}
|
|
142
151
|
export interface SubjectSummary {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
152
|
+
subjectId: string;
|
|
153
|
+
episodeCount: number;
|
|
154
|
+
memoryCount: number;
|
|
146
155
|
}
|
|
147
156
|
export interface ListSubjectsResult {
|
|
148
157
|
subjects: SubjectSummary[];
|
|
@@ -150,59 +159,195 @@ export interface ListSubjectsResult {
|
|
|
150
159
|
}
|
|
151
160
|
/** Status of an async compile job. */
|
|
152
161
|
export interface CompileJob {
|
|
153
|
-
|
|
162
|
+
jobId: string;
|
|
154
163
|
status: "pending" | "running" | "completed" | "failed";
|
|
155
|
-
|
|
156
|
-
|
|
164
|
+
subjectId: string;
|
|
165
|
+
memoriesCreated?: number;
|
|
157
166
|
memories?: Memory[];
|
|
158
167
|
error?: string;
|
|
159
168
|
}
|
|
169
|
+
/** Support health-state bucket. */
|
|
170
|
+
export type HealthState = "healthy" | "watch" | "at_risk";
|
|
171
|
+
/** Resolution lifecycle status. */
|
|
172
|
+
export type ResolutionStatus = "open" | "resolved" | "unresolved";
|
|
173
|
+
/** One explainable factor behind a customer health score. */
|
|
174
|
+
export interface HealthFactor {
|
|
175
|
+
/** Stable signal identifier, e.g. `sla_resolution_breaches`. */
|
|
176
|
+
signal: string;
|
|
177
|
+
/** Signed score contribution — a negative impact drags the score down. */
|
|
178
|
+
impact: number;
|
|
179
|
+
/** Human-readable explanation of the factor. */
|
|
180
|
+
detail: string;
|
|
181
|
+
}
|
|
182
|
+
/** Customer health score (0–100) with the factors that drove it. */
|
|
183
|
+
export interface Health {
|
|
184
|
+
subjectId: string;
|
|
185
|
+
score: number;
|
|
186
|
+
state: HealthState;
|
|
187
|
+
factors: HealthFactor[];
|
|
188
|
+
}
|
|
189
|
+
/** SLA metrics for a single support session. */
|
|
190
|
+
export interface SessionSLA {
|
|
191
|
+
sessionId: string;
|
|
192
|
+
/** `resolved` | `open`. */
|
|
193
|
+
status: string;
|
|
194
|
+
firstMessageAt: string | null;
|
|
195
|
+
firstResponseAt: string | null;
|
|
196
|
+
resolvedAt: string | null;
|
|
197
|
+
firstResponseSeconds: number | null;
|
|
198
|
+
resolutionSeconds: number | null;
|
|
199
|
+
openDurationSeconds: number | null;
|
|
200
|
+
firstResponseBreached: boolean;
|
|
201
|
+
resolutionBreached: boolean;
|
|
202
|
+
}
|
|
203
|
+
/** Aggregate SLA metrics for a subject across all of its sessions. */
|
|
204
|
+
export interface SLASummary {
|
|
205
|
+
subjectId: string;
|
|
206
|
+
totalSessions: number;
|
|
207
|
+
resolvedSessions: number;
|
|
208
|
+
openSessions: number;
|
|
209
|
+
avgFirstResponseSeconds: number | null;
|
|
210
|
+
avgResolutionSeconds: number | null;
|
|
211
|
+
firstResponseBreachCount: number;
|
|
212
|
+
resolutionBreachCount: number;
|
|
213
|
+
sessions: SessionSLA[];
|
|
214
|
+
}
|
|
215
|
+
/** A prior resolution surfaced inside a handoff brief. */
|
|
216
|
+
export interface ResolutionSummaryItem {
|
|
217
|
+
sessionId: string;
|
|
218
|
+
status: string;
|
|
219
|
+
summary: string | null;
|
|
220
|
+
resolvedAt: string | null;
|
|
221
|
+
}
|
|
222
|
+
/** Structured escalation brief — the handoff context pack. */
|
|
223
|
+
export interface Handoff {
|
|
224
|
+
subjectId: string;
|
|
225
|
+
sessionId: string;
|
|
226
|
+
reason: string;
|
|
227
|
+
generatedAt: string;
|
|
228
|
+
customerSummary: string;
|
|
229
|
+
activeIssue: string;
|
|
230
|
+
attemptedSteps: string[];
|
|
231
|
+
keyFacts: string[];
|
|
232
|
+
resolutionHistory: ResolutionSummaryItem[];
|
|
233
|
+
recentContext: string[];
|
|
234
|
+
healthScore: number | null;
|
|
235
|
+
healthState: HealthState | null;
|
|
236
|
+
healthFactors: HealthFactor[];
|
|
237
|
+
/** Pre-rendered markdown brief, ready for human or LLM consumption. */
|
|
238
|
+
handoffNotes: string;
|
|
239
|
+
tokenEstimate: number;
|
|
240
|
+
provenance: Record<string, unknown>;
|
|
241
|
+
/** ULID of the state-assembly receipt, when one was emitted. */
|
|
242
|
+
receiptId?: string | null;
|
|
243
|
+
/** True iff a receipt was successfully written for this call. */
|
|
244
|
+
receiptEmitted?: boolean;
|
|
245
|
+
}
|
|
246
|
+
/** Resolution tracking record for a support session. */
|
|
247
|
+
export interface Resolution {
|
|
248
|
+
id: string;
|
|
249
|
+
subjectId: string;
|
|
250
|
+
sessionId: string;
|
|
251
|
+
status: ResolutionStatus;
|
|
252
|
+
resolutionSummary: string | null;
|
|
253
|
+
resolvedAt: string | null;
|
|
254
|
+
metadata: Record<string, unknown>;
|
|
255
|
+
createdAt: string;
|
|
256
|
+
updatedAt: string;
|
|
257
|
+
}
|
|
160
258
|
export interface CreateEpisodeParams {
|
|
161
|
-
|
|
259
|
+
subjectId: string;
|
|
162
260
|
source: string;
|
|
163
261
|
type: string;
|
|
164
262
|
payload: Record<string, unknown>;
|
|
165
263
|
metadata?: Record<string, unknown>;
|
|
166
264
|
provenance?: Record<string, unknown>;
|
|
167
|
-
|
|
265
|
+
sessionId?: string;
|
|
168
266
|
}
|
|
169
267
|
export interface SearchMemoriesParams {
|
|
170
|
-
|
|
268
|
+
subjectId: string;
|
|
171
269
|
kind?: string;
|
|
172
270
|
query?: string;
|
|
173
271
|
semantic?: boolean;
|
|
174
272
|
limit?: number;
|
|
175
273
|
}
|
|
176
274
|
export interface GetContextParams {
|
|
177
|
-
|
|
275
|
+
subjectId: string;
|
|
178
276
|
task: string;
|
|
179
|
-
|
|
180
|
-
|
|
277
|
+
maxTokens?: number;
|
|
278
|
+
sessionId?: string;
|
|
181
279
|
/**
|
|
182
280
|
* Opt in to emitting a state-assembly receipt for this call. The
|
|
183
281
|
* tenant config can also force emission on or off independently of
|
|
184
282
|
* this flag. See `docs/state-assembly-receipts.md` in the server
|
|
185
283
|
* repository.
|
|
186
284
|
*/
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
285
|
+
emitReceipt?: boolean;
|
|
286
|
+
queryId?: string;
|
|
287
|
+
taskId?: string;
|
|
288
|
+
parentReceiptId?: string;
|
|
191
289
|
/**
|
|
192
290
|
* Caller identity consumed by the sensitivity-label policy layer
|
|
193
291
|
* (#50). When the tenant config sets `require_caller_identity:
|
|
194
|
-
* true`, both `
|
|
292
|
+
* true`, both `callerId` and `callerType` are mandatory.
|
|
195
293
|
*/
|
|
196
|
-
|
|
197
|
-
|
|
294
|
+
callerId?: string;
|
|
295
|
+
callerType?: string;
|
|
198
296
|
}
|
|
199
297
|
export interface SetMemoryLabelsParams {
|
|
200
|
-
|
|
298
|
+
memoryId: string;
|
|
201
299
|
/**
|
|
202
300
|
* Replacement label list. Server normalizes (dedup + lowercase +
|
|
203
301
|
* trim) and caps at 32 entries. Empty list clears all labels.
|
|
204
302
|
*/
|
|
205
|
-
|
|
303
|
+
sensitivityLabels: string[];
|
|
304
|
+
}
|
|
305
|
+
export interface GetSLAParams {
|
|
306
|
+
subjectId: string;
|
|
307
|
+
/** First-response SLA threshold in minutes (server default: 5). */
|
|
308
|
+
firstResponseThresholdMinutes?: number;
|
|
309
|
+
/** Resolution SLA threshold in hours (server default: 24). */
|
|
310
|
+
resolutionThresholdHours?: number;
|
|
311
|
+
}
|
|
312
|
+
export interface CreateHandoffParams {
|
|
313
|
+
subjectId: string;
|
|
314
|
+
/** Session being handed off. */
|
|
315
|
+
sessionId: string;
|
|
316
|
+
/** Why the handoff is happening (server default: "escalation"). */
|
|
317
|
+
reason?: string;
|
|
318
|
+
/** Token budget for the assembled brief. */
|
|
319
|
+
maxTokens?: number;
|
|
320
|
+
/**
|
|
321
|
+
* Opt in to emitting a state-assembly receipt for this call. The
|
|
322
|
+
* tenant config can also force emission on or off independently of
|
|
323
|
+
* this flag.
|
|
324
|
+
*/
|
|
325
|
+
emitReceipt?: boolean;
|
|
326
|
+
queryId?: string;
|
|
327
|
+
taskId?: string;
|
|
328
|
+
parentReceiptId?: string;
|
|
329
|
+
/**
|
|
330
|
+
* Caller identity consumed by the sensitivity-label policy layer
|
|
331
|
+
* (#50). When the tenant config sets `require_caller_identity: true`,
|
|
332
|
+
* both `callerId` and `callerType` are mandatory.
|
|
333
|
+
*/
|
|
334
|
+
callerId?: string;
|
|
335
|
+
callerType?: string;
|
|
336
|
+
}
|
|
337
|
+
export interface CreateResolutionParams {
|
|
338
|
+
subjectId: string;
|
|
339
|
+
sessionId: string;
|
|
340
|
+
/** Lifecycle status (server default: "open"). */
|
|
341
|
+
status?: ResolutionStatus;
|
|
342
|
+
/** Short human summary of how the session was resolved. */
|
|
343
|
+
resolutionSummary?: string;
|
|
344
|
+
/** Free-form caller-owned bag; inner keys round-trip verbatim. */
|
|
345
|
+
metadata?: Record<string, unknown>;
|
|
346
|
+
}
|
|
347
|
+
export interface ListResolutionsParams {
|
|
348
|
+
subjectId: string;
|
|
349
|
+
/** Filter to a single status. Omit to list every resolution. */
|
|
350
|
+
status?: ResolutionStatus;
|
|
206
351
|
}
|
|
207
352
|
export interface ClientOptions {
|
|
208
353
|
baseUrl?: string;
|
package/dist/types.js
CHANGED
|
@@ -1,2 +1,11 @@
|
|
|
1
|
-
/**
|
|
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 {};
|