roe-typescript 0.1.1 → 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
@@ -139,10 +139,252 @@ client.agents.jobs.downloadReference(jobId, resourceId)
139
139
  client.agents.jobs.deleteData(jobId)
140
140
  ```
141
141
 
142
+ ### Policies
143
+
144
+ ```typescript
145
+ client.policies.list() // List policies
146
+ client.policies.retrieve("policy-uuid") // Get policy
147
+ client.policies.create({ name, content, ... }) // Create policy
148
+ client.policies.update("policy-uuid", { ... }) // Update policy
149
+ client.policies.delete("policy-uuid") // Delete policy
150
+ ```
151
+
152
+ ### Policy Versions
153
+
154
+ ```typescript
155
+ client.policies.versions.list(policyId)
156
+ client.policies.versions.retrieve(policyId, versionId)
157
+ client.policies.versions.create({ policyId, content, ... })
158
+ ```
159
+
160
+ ## Rori Agents (Agentic Workflows)
161
+
162
+ Rori agents are autonomous investigation agents that follow policies (SOPs), use tools, and produce structured verdicts. Unlike extraction engines which transform data, Rori agents reason over evidence, apply policy rules, and return dispositions. All Rori agents are policy-aware — you define the rules, they run the investigation.
163
+
164
+ ### Policies
165
+
166
+ Policies define the rules, instructions, and disposition classifications that Rori agents follow. Creating a policy atomically creates the policy and its first version in one call:
167
+
168
+ ```typescript
169
+ const policy = await client.policies.create({
170
+ name: "AML Investigation Policy",
171
+ content: {
172
+ guidelines: {
173
+ categories: [
174
+ {
175
+ title: "Structuring",
176
+ rules: [
177
+ {
178
+ title: "Cash structuring below reporting thresholds",
179
+ description: "Multiple deposits just under $10,000 within short timeframes",
180
+ flag: "RED_FLAG",
181
+ },
182
+ ],
183
+ },
184
+ {
185
+ title: "Layering",
186
+ rules: [
187
+ {
188
+ title: "Rapid movement between accounts",
189
+ description: "Funds transferred through multiple accounts to obscure origin",
190
+ flag: "RED_FLAG",
191
+ sub_rules: [
192
+ { title: "Cross-border wire transfers with no business purpose" },
193
+ { title: "Shell company intermediaries" },
194
+ ],
195
+ },
196
+ ],
197
+ },
198
+ ],
199
+ },
200
+ instructions: "Investigate the alert against each category. Use available data sources to gather evidence.",
201
+ dispositions: {
202
+ classifications: [
203
+ { name: "Suspicious", description: "Activity warrants SAR filing" },
204
+ { name: "Not Suspicious", description: "Activity has legitimate explanation" },
205
+ { name: "Needs Escalation", description: "Requires senior analyst review" },
206
+ ],
207
+ },
208
+ summary_template: {
209
+ template: "Investigation of {{subject}} found {{verdict}} based on {{findings_count}} findings.",
210
+ },
211
+ },
212
+ });
213
+ ```
214
+
215
+ Iterate on policies by creating new versions:
216
+
217
+ ```typescript
218
+ // Create a new version (automatically becomes the current version)
219
+ const newVersion = await client.policies.versions.create({
220
+ policyId: policy.id,
221
+ content: { /* Updated policy content */ },
222
+ versionName: "v2 - added layering rules",
223
+ });
224
+
225
+ // List all versions
226
+ const versions = await client.policies.versions.list(policy.id);
227
+
228
+ // Retrieve a specific version
229
+ const version = await client.policies.versions.retrieve(policy.id, newVersion.id);
230
+
231
+ // Update policy metadata
232
+ await client.policies.update(policy.id, { name: "Updated Policy Name" });
233
+
234
+ // List all policies
235
+ const policies = await client.policies.list();
236
+
237
+ // Delete a policy
238
+ await client.policies.delete(policy.id);
239
+ ```
240
+
241
+ ### Policy Content Reference
242
+
243
+ | Field | Type | Description |
244
+ |-------|------|-------------|
245
+ | `guidelines` | object | Categories → Rules → Sub-rules hierarchy |
246
+ | `guidelines.categories[].title` | string | Category name |
247
+ | `guidelines.categories[].rules[].title` | string | Rule name |
248
+ | `guidelines.categories[].rules[].description` | string | Rule details |
249
+ | `guidelines.categories[].rules[].flag` | string | `"RED_FLAG"` or `"GREEN_FLAG"` |
250
+ | `guidelines.categories[].rules[].sub_rules[].title` | string | Sub-rule name |
251
+ | `instructions` | string | Free-text investigation instructions |
252
+ | `dispositions.classifications[].name` | string | Outcome label (e.g., "Suspicious") |
253
+ | `dispositions.classifications[].description` | string | When to apply this outcome |
254
+ | `summary_template.template` | string | Handlebars template for report generation |
255
+ | `optional.sar_narrative_template.template` | string | SAR narrative template (AML-specific) |
256
+
257
+ ### Product Compliance
258
+
259
+ Analyze product listings against your compliance policy:
260
+
261
+ ```typescript
262
+ const agent = await client.agents.create({
263
+ name: "Product Compliance",
264
+ engineClassId: "ProductPolicyEngine",
265
+ inputDefinitions: [
266
+ { key: "product_listings", data_type: "text/plain", description: "Product listing to analyze" },
267
+ ],
268
+ engineConfig: {
269
+ policy_version_id: policy.current_version_id!,
270
+ product_listings: "${product_listings}",
271
+ },
272
+ });
273
+
274
+ const outputs = await client.agents.runSync(agent.id, {
275
+ product_listings: "Nike Air Max 90, brand new, $45 — ships from Shenzhen",
276
+ });
277
+ ```
278
+
279
+ ### AML Investigation
280
+
281
+ Investigate anti-money laundering alerts:
282
+
283
+ ```typescript
284
+ const agent = await client.agents.create({
285
+ name: "AML Investigation",
286
+ engineClassId: "AMLInvestigationEngine",
287
+ inputDefinitions: [
288
+ { key: "alert_data", data_type: "text/plain", description: "Alert data and context" },
289
+ ],
290
+ engineConfig: {
291
+ policy_version_id: policy.current_version_id!,
292
+ alert_data: "${alert_data}",
293
+ },
294
+ });
295
+
296
+ const job = await client.agents.run({
297
+ agentId: agent.id,
298
+ inputs: { alert_data: "Customer John Doe, 5 cash deposits of $9,500 in 3 days" },
299
+ });
300
+ const result = await job.wait();
301
+ ```
302
+
303
+ ### Fraud Investigation
304
+
305
+ Investigate fraud alerts and suspicious activity:
306
+
307
+ ```typescript
308
+ const agent = await client.agents.create({
309
+ name: "Fraud Investigation",
310
+ engineClassId: "FraudInvestigationEngine",
311
+ inputDefinitions: [
312
+ { key: "alert_data", data_type: "text/plain", description: "Alert data and context" },
313
+ ],
314
+ engineConfig: {
315
+ policy_version_id: policy.current_version_id!,
316
+ alert_data: "${alert_data}",
317
+ },
318
+ });
319
+
320
+ const job = await client.agents.run({
321
+ agentId: agent.id,
322
+ inputs: { alert_data: "Chargeback spike: 47 disputes in 24h from merchant ACME-1234" },
323
+ });
324
+ const result = await job.wait();
325
+ ```
326
+
327
+ ### Merchant Risk
328
+
329
+ Analyze merchant risk profiles:
330
+
331
+ ```typescript
332
+ const agent = await client.agents.create({
333
+ name: "Merchant Risk Analysis",
334
+ engineClassId: "MerchantRiskEngine",
335
+ inputDefinitions: [
336
+ { key: "merchant_context", data_type: "text/plain", description: "Merchant name and context" },
337
+ ],
338
+ engineConfig: {
339
+ policy_version_id: policy.current_version_id!,
340
+ merchant_context: "${merchant_context}",
341
+ },
342
+ });
343
+
344
+ const job = await client.agents.run({
345
+ agentId: agent.id,
346
+ inputs: { merchant_context: "ACME Corp - Online electronics retailer, MCC 5732" },
347
+ });
348
+ const result = await job.wait();
349
+ ```
350
+
351
+ ### Agent Configuration Options
352
+
353
+ All Rori agents accept these options in `engineConfig`:
354
+
355
+ | Option | Type | Default | Description |
356
+ |--------|------|---------|-------------|
357
+ | `policy_version_id` | string | — | Policy version UUID (required) |
358
+ | `context_sources` | array | `[]` | External data sources (SQL connections, APIs) |
359
+ | `enable_planning` | boolean | `true` | Enable autonomous tool-use planning |
360
+ | `enable_memory` | boolean | `false` | Retain context across runs for the same entity |
361
+ | `reasoning_effort` | string | `"medium"` | `"low"`, `"medium"`, or `"high"` |
362
+
363
+ Example with advanced configuration:
364
+
365
+ ```typescript
366
+ const agent = await client.agents.create({
367
+ name: "AML Investigation (Advanced)",
368
+ engineClassId: "AMLInvestigationEngine",
369
+ inputDefinitions: [
370
+ { key: "alert_data", data_type: "text/plain", description: "Alert data and context" },
371
+ ],
372
+ engineConfig: {
373
+ policy_version_id: policy.current_version_id!,
374
+ alert_data: "${alert_data}",
375
+ reasoning_effort: "high",
376
+ context_sources: [
377
+ { type: "sql", name: "Transactions DB", connection_id: "conn-uuid" },
378
+ ],
379
+ },
380
+ });
381
+ ```
382
+
142
383
  ## Supported Models
143
384
 
144
385
  | Model | Value |
145
386
  |-------|-------|
387
+ | GPT-5.4 | `gpt-5.4-2026-03-05` |
146
388
  | GPT-5.2 | `gpt-5.2-2025-12-11` |
147
389
  | GPT-5.1 | `gpt-5.1-2025-11-13` |
148
390
  | GPT-5 | `gpt-5-2025-08-07` |
@@ -152,24 +394,25 @@ client.agents.jobs.deleteData(jobId)
152
394
  | O3 Pro | `o3-pro-2025-06-10` |
153
395
  | O3 | `o3-2025-04-16` |
154
396
  | O4 Mini | `o4-mini-2025-04-16` |
155
- | GPT-4o | `gpt-4o-2024-11-20` |
156
- | Grok 4 | `grok-4-0709` |
157
- | Claude Sonnet 4.5 | `claude-sonnet-4-5-20250929` |
158
- | Claude Sonnet 4 | `claude-sonnet-4-20250514` |
159
- | Claude 3.7 Sonnet | `claude-3-7-sonnet-20250219` |
160
- | Claude Haiku 4.5 | `claude-haiku-4-5-20251001` |
161
- | Claude 3.5 Haiku | `claude-3-5-haiku-20241022` |
397
+ | Claude Opus 4.6 | `claude-opus-4-6` |
398
+ | Claude Sonnet 4.6 | `claude-sonnet-4-6` |
162
399
  | Claude Opus 4.5 | `claude-opus-4-5-20251101` |
400
+ | Claude Sonnet 4.5 | `claude-sonnet-4-5-20250929` |
163
401
  | Claude Opus 4.1 | `claude-opus-4-1-20250805` |
164
402
  | Claude Opus 4 | `claude-opus-4-20250514` |
403
+ | Claude Sonnet 4 | `claude-sonnet-4-20250514` |
404
+ | Claude Haiku 4.5 | `claude-haiku-4-5-20251001` |
165
405
  | Gemini 3 Pro | `gemini-3-pro-preview` |
406
+ | Gemini 3 Flash | `gemini-3-flash-preview` |
166
407
  | Gemini 2.5 Pro | `gemini-2.5-pro` |
167
408
  | Gemini 2.5 Flash | `gemini-2.5-flash` |
409
+ | Grok 4 | `grok-4-0709` |
410
+ | Grok 4.1 Fast Reasoning | `grok-4-1-fast-reasoning` |
168
411
 
169
412
  ## Engine Classes
170
413
 
171
414
  | Engine | ID |
172
- |--------|-----|
415
+ |--------|----|
173
416
  | Multimodal Extraction | `MultimodalExtractionEngine` |
174
417
  | Document Insights | `PDFExtractionEngine` |
175
418
  | Document Segmentation | `PDFPageSelectionEngine` |
@@ -178,10 +421,12 @@ client.agents.jobs.deleteData(jobId)
178
421
  | Web Search | `URLFinderEngine` |
179
422
  | Perplexity Search | `PerplexitySearchEngine` |
180
423
  | Maps Search | `GoogleMapsEntityExtractionEngine` |
181
- | Merchant Risk | `MerchantRiskAnalysisEngine` |
182
- | Product Policy | `ProductPolicyEngine` |
183
424
  | LinkedIn Crawler | `LinkedInScraperEngine` |
184
425
  | Social Media | `SocialScraperEngine` |
426
+ | Product Compliance | `ProductPolicyEngine` |
427
+ | Merchant Risk | `MerchantRiskEngine` |
428
+ | AML Investigation | `AMLInvestigationEngine` |
429
+ | Fraud Investigation | `FraudInvestigationEngine` |
185
430
 
186
431
  ## Links
187
432
 
@@ -0,0 +1,39 @@
1
+ import { RoeConfig } from "../config.js";
2
+ import { RoeHTTPClient } from "../utils/httpClient.js";
3
+ import { PaginatedResponse } from "../models/responses.js";
4
+ import { Policy, PolicyVersion } from "../models/policy.js";
5
+ export declare class PolicyVersionsAPI {
6
+ private readonly policiesApi;
7
+ constructor(policiesApi: PoliciesAPI);
8
+ private get http();
9
+ list(policyId: string): Promise<PolicyVersion[]>;
10
+ retrieve(policyId: string, versionId: string): Promise<PolicyVersion>;
11
+ create(params: {
12
+ policyId: string;
13
+ content: Record<string, unknown>;
14
+ versionName?: string;
15
+ baseVersionId?: string;
16
+ }): Promise<PolicyVersion>;
17
+ }
18
+ export declare class PoliciesAPI {
19
+ readonly config: RoeConfig;
20
+ readonly httpClient: RoeHTTPClient;
21
+ readonly versions: PolicyVersionsAPI;
22
+ constructor(config: RoeConfig, httpClient: RoeHTTPClient);
23
+ list(params?: {
24
+ page?: number;
25
+ pageSize?: number;
26
+ }): Promise<PaginatedResponse<Policy>>;
27
+ retrieve(policyId: string): Promise<Policy>;
28
+ create(params: {
29
+ name: string;
30
+ content: Record<string, unknown>;
31
+ description?: string;
32
+ versionName?: string;
33
+ }): Promise<Policy>;
34
+ update(policyId: string, updates: {
35
+ name?: string;
36
+ description?: string;
37
+ }): Promise<Policy>;
38
+ delete(policyId: string): Promise<void>;
39
+ }
@@ -0,0 +1,90 @@
1
+ import { PaginationHelper } from "../utils/pagination.js";
2
+ import { isUuidString } from "../utils/fileDetection.js";
3
+ import { BadRequestError, RoeAPIException } from "../exceptions.js";
4
+ /**
5
+ * Validates that a value is a valid UUID string.
6
+ * @throws BadRequestError if the value is not a valid UUID
7
+ */
8
+ function validateUuid(value, fieldName) {
9
+ if (!isUuidString(value)) {
10
+ throw new BadRequestError(`Invalid ${fieldName}: "${value}" is not a valid UUID`, 400);
11
+ }
12
+ }
13
+ export class PolicyVersionsAPI {
14
+ constructor(policiesApi) {
15
+ this.policiesApi = policiesApi;
16
+ }
17
+ get http() {
18
+ return this.policiesApi.httpClient;
19
+ }
20
+ async list(policyId) {
21
+ validateUuid(policyId, "policyId");
22
+ const data = await this.http.get(`/v1/policies/${policyId}/versions/`);
23
+ if (Array.isArray(data))
24
+ return data;
25
+ return data.results ?? [];
26
+ }
27
+ async retrieve(policyId, versionId) {
28
+ validateUuid(policyId, "policyId");
29
+ validateUuid(versionId, "versionId");
30
+ return this.http.get(`/v1/policies/${policyId}/versions/${versionId}/`);
31
+ }
32
+ async create(params) {
33
+ validateUuid(params.policyId, "policyId");
34
+ if (params.baseVersionId !== undefined)
35
+ validateUuid(params.baseVersionId, "baseVersionId");
36
+ const payload = { content: params.content };
37
+ if (params.versionName !== undefined)
38
+ payload.version_name = params.versionName;
39
+ if (params.baseVersionId !== undefined)
40
+ payload.base_version_id = params.baseVersionId;
41
+ const data = await this.http.post({
42
+ url: `/v1/policies/${params.policyId}/versions/`,
43
+ json: payload,
44
+ });
45
+ if (!data.id) {
46
+ throw new RoeAPIException(`Unexpected response from server: ${JSON.stringify(data)}`);
47
+ }
48
+ // POST returns partial data; re-fetch to get the full version
49
+ return this.retrieve(params.policyId, data.id);
50
+ }
51
+ }
52
+ export class PoliciesAPI {
53
+ constructor(config, httpClient) {
54
+ this.config = config;
55
+ this.httpClient = httpClient;
56
+ this.versions = new PolicyVersionsAPI(this);
57
+ }
58
+ async list(params) {
59
+ const query = PaginationHelper.buildQueryParams(this.config.organizationId, params?.page, params?.pageSize);
60
+ return this.httpClient.get("/v1/policies/", query);
61
+ }
62
+ async retrieve(policyId) {
63
+ validateUuid(policyId, "policyId");
64
+ return this.httpClient.get(`/v1/policies/${policyId}/`);
65
+ }
66
+ async create(params) {
67
+ const payload = {
68
+ name: params.name,
69
+ content: params.content,
70
+ description: params.description ?? "",
71
+ organization_id: this.config.organizationId,
72
+ };
73
+ if (params.versionName !== undefined)
74
+ payload.version_name = params.versionName;
75
+ return this.httpClient.post({ url: "/v1/policies/", json: payload });
76
+ }
77
+ async update(policyId, updates) {
78
+ validateUuid(policyId, "policyId");
79
+ const payload = {};
80
+ if (updates.name !== undefined)
81
+ payload.name = updates.name;
82
+ if (updates.description !== undefined)
83
+ payload.description = updates.description;
84
+ return this.httpClient.put(`/v1/policies/${policyId}/`, payload);
85
+ }
86
+ async delete(policyId) {
87
+ validateUuid(policyId, "policyId");
88
+ await this.httpClient.delete(`/v1/policies/${policyId}/`);
89
+ }
90
+ }
package/dist/client.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AgentsAPI } from "./api/agents.js";
2
+ import { PoliciesAPI } from "./api/policies.js";
2
3
  import { RoeAuth } from "./auth.js";
3
4
  import { RoeConfig, RoeConfigInput } from "./config.js";
4
5
  import { RoeHTTPClient } from "./utils/httpClient.js";
@@ -7,7 +8,9 @@ export declare class RoeClient {
7
8
  readonly auth: RoeAuth;
8
9
  readonly httpClient: RoeHTTPClient;
9
10
  private readonly _agents;
11
+ private readonly _policies;
10
12
  constructor(input?: RoeConfigInput);
11
13
  get agents(): AgentsAPI;
14
+ get policies(): PoliciesAPI;
12
15
  close(): void;
13
16
  }
package/dist/client.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AgentsAPI } from "./api/agents.js";
2
+ import { PoliciesAPI } from "./api/policies.js";
2
3
  import { RoeAuth } from "./auth.js";
3
4
  import { RoeConfig } from "./config.js";
4
5
  import { RoeHTTPClient } from "./utils/httpClient.js";
@@ -8,10 +9,14 @@ export class RoeClient {
8
9
  this.auth = new RoeAuth(this.config);
9
10
  this.httpClient = new RoeHTTPClient(this.config, this.auth);
10
11
  this._agents = new AgentsAPI(this.config, this.httpClient);
12
+ this._policies = new PoliciesAPI(this.config, this.httpClient);
11
13
  }
12
14
  get agents() {
13
15
  return this._agents;
14
16
  }
17
+ get policies() {
18
+ return this._policies;
19
+ }
15
20
  close() {
16
21
  this.httpClient.close();
17
22
  }
@@ -43,6 +43,13 @@ export function extractErrorMessage(data, statusCode) {
43
43
  if (typeof data === "string") {
44
44
  return data;
45
45
  }
46
+ // DRF ValidationError returns a plain list like ["error message"]
47
+ if (Array.isArray(data)) {
48
+ if (data.length > 0) {
49
+ return data.map(String).join("; ");
50
+ }
51
+ return `HTTP ${statusCode} error`;
52
+ }
46
53
  if (typeof data === "object" && data !== null) {
47
54
  // Try common error message field names
48
55
  const obj = data;
package/dist/index.d.ts CHANGED
@@ -4,7 +4,9 @@ export type { RoeConfigInput } from "./config.js";
4
4
  export { RoeAuth } from "./auth.js";
5
5
  export * from "./exceptions.js";
6
6
  export * from "./api/agents.js";
7
+ export * from "./api/policies.js";
7
8
  export * from "./models/agent.js";
9
+ export * from "./models/policy.js";
8
10
  export * from "./models/job.js";
9
11
  export * from "./models/responses.js";
10
12
  export * from "./models/file.js";
package/dist/index.js CHANGED
@@ -3,7 +3,9 @@ export { RoeConfig } from "./config.js";
3
3
  export { RoeAuth } from "./auth.js";
4
4
  export * from "./exceptions.js";
5
5
  export * from "./api/agents.js";
6
+ export * from "./api/policies.js";
6
7
  export * from "./models/agent.js";
8
+ export * from "./models/policy.js";
7
9
  export * from "./models/job.js";
8
10
  export * from "./models/responses.js";
9
11
  export * from "./models/file.js";
@@ -0,0 +1,19 @@
1
+ export type Policy = {
2
+ id: string;
3
+ name: string;
4
+ description: string;
5
+ organization_id: string;
6
+ current_version_id: string | null;
7
+ created_at: string;
8
+ updated_at: string;
9
+ };
10
+ export type PolicyVersion = {
11
+ id: string;
12
+ version_name: string;
13
+ content: Record<string, unknown>;
14
+ created_at: string;
15
+ updated_at: string;
16
+ policy: Policy | null;
17
+ created_by: Record<string, unknown> | null;
18
+ base_version_id: string | null;
19
+ };
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roe-typescript",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "TypeScript SDK for the Roe AI API (feature parity with roe-python).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",