@reclaimprotocol/agent 0.1.39 → 0.1.41
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 +32 -0
- package/lib/config/store.d.ts +7 -0
- package/lib/consts.d.ts +5 -0
- package/lib/consts.js +10 -0
- package/lib/mcp/api/operations.gen.d.ts +7 -0
- package/lib/mcp/api/operations.gen.js +54 -4
- package/lib/mcp/api/tools.js +4 -0
- package/lib/mcp/instructions.js +10 -8
- package/lib/mcp/server.js +6 -1
- package/lib/mcp/start.js +27 -1
- package/lib/mcp/tools/agent/example-app.d.ts +5 -1
- package/lib/mcp/tools/agent/example-app.js +87 -24
- package/lib/mcp/tools/agent/propose.js +7 -0
- package/lib/mcp/tools/agent/start-integration.d.ts +2 -0
- package/lib/mcp/tools/agent/start-integration.js +7 -0
- package/lib/mcp/tools/authenticate/authenticate.js +3 -0
- package/lib/mcp/tools/authenticate/eth-key.d.ts +15 -0
- package/lib/mcp/tools/authenticate/eth-key.js +72 -6
- package/lib/mcp/tools/authenticate/issue-org-keypair.d.ts +3 -2
- package/lib/mcp/tools/authenticate/issue-org-keypair.js +83 -18
- package/lib/mcp/tools/authenticate/issue-org-token.js +9 -2
- package/lib/telemetry/index.d.ts +9 -0
- package/lib/telemetry/index.js +13 -0
- package/lib/telemetry/telemetry.d.ts +54 -0
- package/lib/telemetry/telemetry.js +175 -0
- package/lib/telemetry/tool-call.d.ts +24 -0
- package/lib/telemetry/tool-call.js +102 -0
- package/package.json +2 -2
- package/skill/SKILL.builder.md +30 -11
- package/skill/SKILL.old.md +23 -5
- package/skill/builder-mode.md +29 -164
- package/skill/old-mode.md +40 -95
- package/skill/start-integration.md +12 -9
- package/skill/verification-client-integration.md +39 -9
- package/src/config/store.ts +4 -0
- package/src/consts.ts +11 -0
- package/src/mcp/api/operations.gen.ts +56 -4
- package/src/mcp/api/tools.ts +4 -0
- package/src/mcp/instructions.ts +10 -8
- package/src/mcp/server.ts +6 -1
- package/src/mcp/start.ts +34 -0
- package/src/mcp/tools/agent/example-app.ts +97 -30
- package/src/mcp/tools/agent/propose.ts +8 -0
- package/src/mcp/tools/agent/start-integration.ts +10 -0
- package/src/mcp/tools/authenticate/authenticate.ts +3 -0
- package/src/mcp/tools/authenticate/eth-key.ts +114 -6
- package/src/mcp/tools/authenticate/issue-org-keypair.ts +97 -19
- package/src/mcp/tools/authenticate/issue-org-token.ts +13 -2
- package/src/telemetry/index.ts +18 -0
- package/src/telemetry/telemetry.ts +206 -0
- package/src/telemetry/tool-call.ts +115 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { isProblemError } from '@reclaimprotocol/client/api'
|
|
2
|
+
import { currentTelemetry } from './index.ts'
|
|
3
|
+
|
|
4
|
+
const GOAL_MAX = 300
|
|
5
|
+
const USER_REQUEST_MAX = 500
|
|
6
|
+
const DOMAIN_MAX = 200
|
|
7
|
+
const DATA_POINTS_MAX = 20
|
|
8
|
+
const DATA_POINT_MAX = 200
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Times a tool call and records it. Call `end()` once when the call
|
|
12
|
+
* finishes. It never throws, so it can't change the outcome of the call.
|
|
13
|
+
*/
|
|
14
|
+
export function startToolCall(tool: string, args: unknown) {
|
|
15
|
+
const startedAt = Date.now()
|
|
16
|
+
return {
|
|
17
|
+
end(err?: unknown) {
|
|
18
|
+
try {
|
|
19
|
+
const telemetry = currentTelemetry()
|
|
20
|
+
if(!telemetry) {
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const input = allowlistedInput(tool, args)
|
|
25
|
+
telemetry.track('tool_call', {
|
|
26
|
+
tool,
|
|
27
|
+
ok: err === undefined,
|
|
28
|
+
...(err === undefined ? {} : { errorCode: errorCode(err) }),
|
|
29
|
+
durationMs: Date.now() - startedAt,
|
|
30
|
+
mode: telemetry.mode,
|
|
31
|
+
...(input ? { input } : {}),
|
|
32
|
+
})
|
|
33
|
+
} catch{
|
|
34
|
+
// Telemetry must never affect a tool call.
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* A category for the error, such as `http_401`. It's never the message,
|
|
42
|
+
* because messages can contain URLs, tokens, or file paths.
|
|
43
|
+
*/
|
|
44
|
+
export function errorCode(err: unknown): string {
|
|
45
|
+
if(isProblemError(err)) {
|
|
46
|
+
return `http_${err.output.statusCode}`
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if(isRecord(err) && err.isBoom === true && isRecord(err.output)) {
|
|
50
|
+
return `http_${String(err.output.statusCode)}`
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if(err instanceof Error) {
|
|
54
|
+
if(err.name === 'ZodError') {
|
|
55
|
+
return 'invalid_input'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if(err.name === 'TimeoutError' || err.name === 'AbortError') {
|
|
59
|
+
return 'timeout'
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return 'error'
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The only arguments Reclaim records, and only for these tools. They are the
|
|
68
|
+
* developer's own description of what they want to build, which tells us
|
|
69
|
+
* which providers to add. Every other argument is dropped here, so a new tool
|
|
70
|
+
* records nothing until you add it to this list on purpose.
|
|
71
|
+
*/
|
|
72
|
+
export function allowlistedInput(tool: string, args: unknown) {
|
|
73
|
+
if(!isRecord(args)) {
|
|
74
|
+
return undefined
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
switch (tool) {
|
|
78
|
+
case 'start_integration':
|
|
79
|
+
return compact({
|
|
80
|
+
goal: cut(args.goal, GOAL_MAX),
|
|
81
|
+
userRequest: cut(args.userRequest, USER_REQUEST_MAX),
|
|
82
|
+
})
|
|
83
|
+
case 'propose_provider':
|
|
84
|
+
return compact({ userRequest: cut(args.userRequest, USER_REQUEST_MAX) })
|
|
85
|
+
case 'discover_resolve': {
|
|
86
|
+
const query = isRecord(args.query) ? args.query : {}
|
|
87
|
+
const dataPoints = Array.isArray(query.dataPoints)
|
|
88
|
+
? query.dataPoints
|
|
89
|
+
.slice(0, DATA_POINTS_MAX)
|
|
90
|
+
.map((p) => cut(p, DATA_POINT_MAX))
|
|
91
|
+
.filter((p) => p !== undefined)
|
|
92
|
+
: undefined
|
|
93
|
+
return compact({
|
|
94
|
+
domain: cut(query.domain, DOMAIN_MAX),
|
|
95
|
+
dataPoints: dataPoints?.length ? dataPoints : undefined,
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
default:
|
|
100
|
+
return undefined
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function cut(value: unknown, max: number): string | undefined {
|
|
105
|
+
return typeof value === 'string' && value ? value.slice(0, max) : undefined
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Returns the object, or undefined when every field is undefined. */
|
|
109
|
+
function compact<T extends object>(obj: T): T | undefined {
|
|
110
|
+
return Object.values(obj).some((v) => v !== undefined) ? obj : undefined
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
114
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
115
|
+
}
|