@getmarrow/sdk 1.1.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 +65 -0
- package/dist/client.d.ts +23 -0
- package/dist/client.js +141 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.js +36 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +10 -0
- package/dist/types.d.ts +78 -0
- package/dist/types.js +2 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# @marrow/sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for [Marrow](https://getmarrow.ai) — decision intelligence for AI agents.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @marrow/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Marrow } from '@marrow/sdk'
|
|
15
|
+
|
|
16
|
+
const marrow = new Marrow({ apiKey: 'mrw_your_key' })
|
|
17
|
+
|
|
18
|
+
// Before a decision
|
|
19
|
+
const { decisionId, insight, insights } = await marrow.think({
|
|
20
|
+
action: 'deploying new feature',
|
|
21
|
+
type: 'deployment'
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
// After completion
|
|
25
|
+
await marrow.commit({
|
|
26
|
+
decisionId,
|
|
27
|
+
success: true,
|
|
28
|
+
outcome: 'deploy successful'
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// Get patterns
|
|
32
|
+
const patterns = await marrow.patterns()
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## What's new in v1.1.0
|
|
36
|
+
|
|
37
|
+
### Query your agent's patterns
|
|
38
|
+
```typescript
|
|
39
|
+
const patterns = await marrow.agentPatterns({ type: 'deploy' })
|
|
40
|
+
// Returns failure rates, recurring decisions, behavioral drift
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Health score
|
|
44
|
+
```typescript
|
|
45
|
+
const analytics = await marrow.analytics()
|
|
46
|
+
console.log(analytics.healthScore) // { score: 78, label: 'Good', ... }
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### PII detection signal
|
|
50
|
+
```typescript
|
|
51
|
+
const { sanitized } = await marrow.think({ action: '...', type: '...' })
|
|
52
|
+
if (sanitized) console.log('PII was detected and stripped')
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Upgrade nudges (free tier)
|
|
56
|
+
```typescript
|
|
57
|
+
const { upgradeHint } = await marrow.think({ action: '...', type: '...' })
|
|
58
|
+
if (upgradeHint) console.log(upgradeHint.message)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Features
|
|
62
|
+
- Zero dependencies (fetch-based)
|
|
63
|
+
- Auto-retry on 429 with exponential backoff
|
|
64
|
+
- TypeScript types included
|
|
65
|
+
- Browser + Node compatible
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marrow SDK — HTTP client (fetch-based, no heavy deps)
|
|
3
|
+
*/
|
|
4
|
+
import { MarrowConfig, ThinkParams, ThinkResult, CommitParams, Pattern, AgentPatternsResult, HealthScore } from './types.js';
|
|
5
|
+
export declare class Marrow {
|
|
6
|
+
private apiKey;
|
|
7
|
+
private baseUrl;
|
|
8
|
+
constructor(config?: MarrowConfig);
|
|
9
|
+
think(params: ThinkParams): Promise<ThinkResult>;
|
|
10
|
+
commit(params: CommitParams): Promise<void>;
|
|
11
|
+
agentPatterns(params?: {
|
|
12
|
+
type?: string;
|
|
13
|
+
limit?: number;
|
|
14
|
+
}): Promise<AgentPatternsResult>;
|
|
15
|
+
analytics(): Promise<{
|
|
16
|
+
healthScore: HealthScore;
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
}>;
|
|
19
|
+
patterns(): Promise<Pattern[]>;
|
|
20
|
+
private post;
|
|
21
|
+
private get;
|
|
22
|
+
private request;
|
|
23
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Marrow = void 0;
|
|
4
|
+
const errors_js_1 = require("./errors.js");
|
|
5
|
+
const DEFAULT_BASE_URL = 'https://api.getmarrow.ai';
|
|
6
|
+
const MAX_RETRIES = 3;
|
|
7
|
+
class Marrow {
|
|
8
|
+
apiKey;
|
|
9
|
+
baseUrl;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
const key = config?.apiKey || (typeof process !== 'undefined' ? process.env?.MARROW_API_KEY : undefined);
|
|
12
|
+
if (!key) {
|
|
13
|
+
throw new errors_js_1.AuthError('API key required. Pass apiKey in config or set MARROW_API_KEY env var.');
|
|
14
|
+
}
|
|
15
|
+
this.apiKey = key;
|
|
16
|
+
this.baseUrl = config?.baseUrl || DEFAULT_BASE_URL;
|
|
17
|
+
}
|
|
18
|
+
async think(params) {
|
|
19
|
+
const body = {
|
|
20
|
+
action: params.action,
|
|
21
|
+
type: params.type,
|
|
22
|
+
};
|
|
23
|
+
if (params.previousDecisionId)
|
|
24
|
+
body.previous_decision_id = params.previousDecisionId;
|
|
25
|
+
if (params.previousSuccess !== undefined)
|
|
26
|
+
body.previous_success = params.previousSuccess;
|
|
27
|
+
if (params.previousOutcome)
|
|
28
|
+
body.previous_outcome = params.previousOutcome;
|
|
29
|
+
const res = await this.post('/v1/agent/think', body);
|
|
30
|
+
const data = res.data || res;
|
|
31
|
+
const intel = (data.intelligence || {});
|
|
32
|
+
return {
|
|
33
|
+
decisionId: String(data.decision_id || ''),
|
|
34
|
+
insight: intel.insight ? String(intel.insight) : null,
|
|
35
|
+
insights: (intel.insights || []),
|
|
36
|
+
clusterId: intel.cluster_id ? String(intel.cluster_id) : null,
|
|
37
|
+
successRate: Number(intel.success_rate || 0),
|
|
38
|
+
similarCount: Number(intel.similar_count || 0),
|
|
39
|
+
sanitized: Boolean(data.sanitized),
|
|
40
|
+
upgradeHint: data.upgrade_hint ? data.upgrade_hint : undefined,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
async commit(params) {
|
|
44
|
+
await this.post('/v1/agent/commit', {
|
|
45
|
+
decision_id: params.decisionId,
|
|
46
|
+
success: params.success,
|
|
47
|
+
outcome: params.outcome,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async agentPatterns(params) {
|
|
51
|
+
const qs = new URLSearchParams();
|
|
52
|
+
if (params?.type)
|
|
53
|
+
qs.set('type', params.type);
|
|
54
|
+
if (params?.limit)
|
|
55
|
+
qs.set('limit', String(params.limit));
|
|
56
|
+
const res = await this.get(`/v1/agent/patterns${qs.toString() ? '?' + qs.toString() : ''}`);
|
|
57
|
+
const data = res.data || res;
|
|
58
|
+
return {
|
|
59
|
+
failurePatterns: (data.failure_patterns || []),
|
|
60
|
+
recurringDecisions: (data.recurring_decisions || []),
|
|
61
|
+
behavioralDrift: (data.behavioral_drift || {}),
|
|
62
|
+
topFailureTypes: (data.top_failure_types || []),
|
|
63
|
+
generatedAt: String(data.generated_at || ''),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
async analytics() {
|
|
67
|
+
const res = await this.get('/v1/analytics');
|
|
68
|
+
const data = res.data || res;
|
|
69
|
+
const hs = (data.health_score || {});
|
|
70
|
+
return {
|
|
71
|
+
...data,
|
|
72
|
+
healthScore: {
|
|
73
|
+
score: Number(hs.score || 0),
|
|
74
|
+
label: String(hs.label || ''),
|
|
75
|
+
breakdown: (hs.breakdown || {}),
|
|
76
|
+
trend: String(hs.trend || ''),
|
|
77
|
+
vsLastWeek: String(hs.vs_last_week || ''),
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
async patterns() {
|
|
82
|
+
const res = await this.get('/v1/patterns');
|
|
83
|
+
const data = (res.data || []);
|
|
84
|
+
return data.map(p => ({
|
|
85
|
+
patternId: String(p.pattern_id || p.id || ''),
|
|
86
|
+
signature: String(p.signature || p.pattern_signature || ''),
|
|
87
|
+
frequency: Number(p.frequency || 0),
|
|
88
|
+
confidence: Number(p.confidence || 0),
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
async post(path, body) {
|
|
92
|
+
return this.request('POST', path, body);
|
|
93
|
+
}
|
|
94
|
+
async get(path) {
|
|
95
|
+
return this.request('GET', path);
|
|
96
|
+
}
|
|
97
|
+
async request(method, path, body) {
|
|
98
|
+
let lastError = null;
|
|
99
|
+
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
100
|
+
try {
|
|
101
|
+
const opts = {
|
|
102
|
+
method,
|
|
103
|
+
headers: {
|
|
104
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
105
|
+
...(body ? { 'Content-Type': 'application/json' } : {}),
|
|
106
|
+
},
|
|
107
|
+
...(body ? { body: JSON.stringify(body) } : {}),
|
|
108
|
+
};
|
|
109
|
+
const res = await fetch(`${this.baseUrl}${path}`, opts);
|
|
110
|
+
if (res.ok) {
|
|
111
|
+
return res.json();
|
|
112
|
+
}
|
|
113
|
+
if (res.status === 429) {
|
|
114
|
+
const retryAfter = parseInt(res.headers.get('Retry-After') || '60', 10);
|
|
115
|
+
if (attempt < MAX_RETRIES - 1) {
|
|
116
|
+
await new Promise(r => setTimeout(r, retryAfter * 1000 * (attempt + 1)));
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
throw new errors_js_1.RateLimitError(retryAfter);
|
|
120
|
+
}
|
|
121
|
+
const text = await res.text();
|
|
122
|
+
if (res.status === 401)
|
|
123
|
+
throw new errors_js_1.AuthError(text);
|
|
124
|
+
if (res.status === 400)
|
|
125
|
+
throw new errors_js_1.ValidationError(text);
|
|
126
|
+
throw new errors_js_1.MarrowError(`API error (${res.status}): ${text}`, res.status);
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
if (e instanceof errors_js_1.MarrowError)
|
|
130
|
+
throw e;
|
|
131
|
+
lastError = e instanceof Error ? e : new Error(String(e));
|
|
132
|
+
if (attempt < MAX_RETRIES - 1) {
|
|
133
|
+
await new Promise(r => setTimeout(r, 1000 * (attempt + 1)));
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
throw lastError || new errors_js_1.MarrowError('Request failed after retries');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.Marrow = Marrow;
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare class MarrowError extends Error {
|
|
2
|
+
statusCode?: number | undefined;
|
|
3
|
+
constructor(message: string, statusCode?: number | undefined);
|
|
4
|
+
}
|
|
5
|
+
export declare class AuthError extends MarrowError {
|
|
6
|
+
constructor(message?: string);
|
|
7
|
+
}
|
|
8
|
+
export declare class ValidationError extends MarrowError {
|
|
9
|
+
constructor(message: string);
|
|
10
|
+
}
|
|
11
|
+
export declare class RateLimitError extends MarrowError {
|
|
12
|
+
retryAfter: number;
|
|
13
|
+
constructor(retryAfter?: number);
|
|
14
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RateLimitError = exports.ValidationError = exports.AuthError = exports.MarrowError = void 0;
|
|
4
|
+
class MarrowError extends Error {
|
|
5
|
+
statusCode;
|
|
6
|
+
constructor(message, statusCode) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.statusCode = statusCode;
|
|
9
|
+
this.name = 'MarrowError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.MarrowError = MarrowError;
|
|
13
|
+
class AuthError extends MarrowError {
|
|
14
|
+
constructor(message = 'Invalid API key') {
|
|
15
|
+
super(message, 401);
|
|
16
|
+
this.name = 'AuthError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.AuthError = AuthError;
|
|
20
|
+
class ValidationError extends MarrowError {
|
|
21
|
+
constructor(message) {
|
|
22
|
+
super(message, 400);
|
|
23
|
+
this.name = 'ValidationError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.ValidationError = ValidationError;
|
|
27
|
+
class RateLimitError extends MarrowError {
|
|
28
|
+
retryAfter;
|
|
29
|
+
constructor(retryAfter = 60) {
|
|
30
|
+
super(`Rate limited. Retry after ${retryAfter}s`);
|
|
31
|
+
this.name = 'RateLimitError';
|
|
32
|
+
this.statusCode = 429;
|
|
33
|
+
this.retryAfter = retryAfter;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.RateLimitError = RateLimitError;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { Marrow } from './client.js';
|
|
2
|
+
export { MarrowError, AuthError, ValidationError, RateLimitError } from './errors.js';
|
|
3
|
+
export type { MarrowConfig, ThinkParams, ThinkResult, CommitParams, Pattern, ActionableInsight, AgentPatternsResult, UpgradeHint, HealthScore } from './types.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RateLimitError = exports.ValidationError = exports.AuthError = exports.MarrowError = exports.Marrow = void 0;
|
|
4
|
+
var client_js_1 = require("./client.js");
|
|
5
|
+
Object.defineProperty(exports, "Marrow", { enumerable: true, get: function () { return client_js_1.Marrow; } });
|
|
6
|
+
var errors_js_1 = require("./errors.js");
|
|
7
|
+
Object.defineProperty(exports, "MarrowError", { enumerable: true, get: function () { return errors_js_1.MarrowError; } });
|
|
8
|
+
Object.defineProperty(exports, "AuthError", { enumerable: true, get: function () { return errors_js_1.AuthError; } });
|
|
9
|
+
Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return errors_js_1.ValidationError; } });
|
|
10
|
+
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return errors_js_1.RateLimitError; } });
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export interface MarrowConfig {
|
|
2
|
+
apiKey?: string;
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface ThinkParams {
|
|
6
|
+
action: string;
|
|
7
|
+
type: string;
|
|
8
|
+
previousDecisionId?: string;
|
|
9
|
+
previousSuccess?: boolean;
|
|
10
|
+
previousOutcome?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ThinkResult {
|
|
13
|
+
decisionId: string;
|
|
14
|
+
insight: string | null;
|
|
15
|
+
insights: ActionableInsight[];
|
|
16
|
+
clusterId: string | null;
|
|
17
|
+
successRate: number;
|
|
18
|
+
similarCount: number;
|
|
19
|
+
sanitized: boolean;
|
|
20
|
+
upgradeHint?: UpgradeHint;
|
|
21
|
+
}
|
|
22
|
+
export interface ActionableInsight {
|
|
23
|
+
type: 'frequency' | 'failure_pattern' | 'workflow_gap' | 'hive_trend';
|
|
24
|
+
summary: string;
|
|
25
|
+
action: string;
|
|
26
|
+
severity: 'info' | 'warning' | 'critical';
|
|
27
|
+
count: number;
|
|
28
|
+
}
|
|
29
|
+
export interface CommitParams {
|
|
30
|
+
decisionId: string;
|
|
31
|
+
success: boolean;
|
|
32
|
+
outcome: string;
|
|
33
|
+
}
|
|
34
|
+
export interface Pattern {
|
|
35
|
+
patternId: string;
|
|
36
|
+
signature: string;
|
|
37
|
+
frequency: number;
|
|
38
|
+
confidence: number;
|
|
39
|
+
}
|
|
40
|
+
export interface AgentPatternsResult {
|
|
41
|
+
failurePatterns: Array<{
|
|
42
|
+
decisionType: string;
|
|
43
|
+
failureRate: number;
|
|
44
|
+
count: number;
|
|
45
|
+
lastSeen: string;
|
|
46
|
+
}>;
|
|
47
|
+
recurringDecisions: Array<{
|
|
48
|
+
decisionType: string;
|
|
49
|
+
frequency: number;
|
|
50
|
+
avgConfidence: number;
|
|
51
|
+
trend: string;
|
|
52
|
+
}>;
|
|
53
|
+
behavioralDrift: {
|
|
54
|
+
successRate7d: number;
|
|
55
|
+
successRate30d: number;
|
|
56
|
+
drift: string;
|
|
57
|
+
direction: string;
|
|
58
|
+
};
|
|
59
|
+
topFailureTypes: string[];
|
|
60
|
+
generatedAt: string;
|
|
61
|
+
}
|
|
62
|
+
export interface UpgradeHint {
|
|
63
|
+
message: string;
|
|
64
|
+
tier: string;
|
|
65
|
+
url: string;
|
|
66
|
+
}
|
|
67
|
+
export interface HealthScore {
|
|
68
|
+
score: number;
|
|
69
|
+
label: string;
|
|
70
|
+
breakdown: {
|
|
71
|
+
successRate: number;
|
|
72
|
+
decisionVelocity: number;
|
|
73
|
+
patternDiscovery: number;
|
|
74
|
+
improvementTrend: string;
|
|
75
|
+
};
|
|
76
|
+
trend: string;
|
|
77
|
+
vsLastWeek: string;
|
|
78
|
+
}
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@getmarrow/sdk",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "TypeScript SDK for Marrow — decision intelligence for AI agents",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "vitest run",
|
|
10
|
+
"prepublishOnly": "npm run build"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"marrow",
|
|
14
|
+
"sdk",
|
|
15
|
+
"ai",
|
|
16
|
+
"decision",
|
|
17
|
+
"intelligence"
|
|
18
|
+
],
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"typescript": "^5.7.0",
|
|
22
|
+
"vitest": "^1.6.0"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=18.0.0"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"README.md"
|
|
30
|
+
]
|
|
31
|
+
}
|