@agentvalet/client 0.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 +144 -0
- package/dist/client.d.ts +111 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +269 -0
- package/dist/client.js.map +1 -0
- package/dist/env.d.ts +16 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +90 -0
- package/dist/env.js.map +1 -0
- package/dist/errors.d.ts +52 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +88 -0
- package/dist/errors.js.map +1 -0
- package/dist/http.d.ts +7 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +50 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# @agentvalet/client
|
|
2
|
+
|
|
3
|
+
Call approved SaaS platforms from any Node agent. Your agent never holds the
|
|
4
|
+
downstream credential — AgentValet signs a short-lived identity assertion,
|
|
5
|
+
checks the call against the owner's grants and policy, injects the credential
|
|
6
|
+
at call time, and writes an audit record.
|
|
7
|
+
|
|
8
|
+
**Not in an MCP host?** This is your package. If you *are* inside Claude Code,
|
|
9
|
+
Claude Desktop, Cursor, or another MCP-aware host, install
|
|
10
|
+
[`@agentvalet/mcp-server`](https://www.npmjs.com/package/@agentvalet/mcp-server)
|
|
11
|
+
instead and call `use_platform` — you get the same guarantees with no code.
|
|
12
|
+
|
|
13
|
+
Building your own MCP *server* and want to enforce policy inside it? That's
|
|
14
|
+
[`@agentvalet/mcp-broker`](https://www.npmjs.com/package/@agentvalet/mcp-broker).
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @agentvalet/client
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Node 18+. One dependency (`jose`, for RS256 signing).
|
|
23
|
+
|
|
24
|
+
## Get an agent identity
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx @agentvalet/register
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This generates an RSA keypair **locally** — the private key never leaves your
|
|
31
|
+
machine — registers the public half, and writes `~/.agentvalet/agent.key`.
|
|
32
|
+
|
|
33
|
+
## Use it
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { AgentValet } from "@agentvalet/client";
|
|
37
|
+
|
|
38
|
+
const av = AgentValet.fromEnv();
|
|
39
|
+
|
|
40
|
+
const result = await av.call({
|
|
41
|
+
platform: "slack",
|
|
42
|
+
endpoint: "/api/chat.postMessage",
|
|
43
|
+
method: "POST",
|
|
44
|
+
scope: "chat:write",
|
|
45
|
+
data: { channel: "#general", text: "Deploy finished." },
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`fromEnv()` reads `AGENTVALET_AGENT_ID` / `AGENTVALET_OWNER_ID` (or the bare
|
|
50
|
+
`AGENT_ID` / `OWNER_ID` the CLI writes) and finds the key via
|
|
51
|
+
`AGENT_PRIVATE_KEY_B64`, `AGENT_PRIVATE_KEY_PATH`, `AGENT_PRIVATE_KEY`, or
|
|
52
|
+
`~/.agentvalet/agent.key`. To wire it up explicitly:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
const av = new AgentValet({
|
|
56
|
+
agentId: process.env.AGENT_ID!,
|
|
57
|
+
ownerId: process.env.OWNER_ID!,
|
|
58
|
+
privateKey: process.env.AGENT_PRIVATE_KEY!,
|
|
59
|
+
proxyUrl: "https://api.agentvalet.ai", // default
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Approvals are just a slower call
|
|
64
|
+
|
|
65
|
+
When the owner has marked a scope as requiring approval, the proxy holds the
|
|
66
|
+
action and `call()` waits. If the owner approves, the proxy re-runs the call and
|
|
67
|
+
you get the result back — from your code's point of view it simply took longer.
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
const av = AgentValet.fromEnv({
|
|
71
|
+
onApprovalPending: ({ elapsedMs }) =>
|
|
72
|
+
console.log(`waiting for owner… ${Math.round(elapsedMs / 1000)}s`),
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
If nobody responds inside the budget (50s by default), you get an
|
|
77
|
+
`ApprovalTimeoutError` — **not** a failure. The action stays queued. Keep the
|
|
78
|
+
`approvalId` and resume whenever you like:
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { ApprovalTimeoutError } from "@agentvalet/client";
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
await av.call({ platform: "stripe", endpoint: "/v1/refunds", method: "POST", scope: "charge" });
|
|
85
|
+
} catch (err) {
|
|
86
|
+
if (err instanceof ApprovalTimeoutError) {
|
|
87
|
+
await saveForLater(err.approvalId); // e.g. into your job queue
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// …later, in another process:
|
|
92
|
+
const result = await av.waitForApproval(approvalId);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Set `approvalTimeoutMs: 0` if you never want to block — `call()` then throws
|
|
96
|
+
`ApprovalTimeoutError` the moment approval is required.
|
|
97
|
+
|
|
98
|
+
## Errors you can branch on
|
|
99
|
+
|
|
100
|
+
Every throw is typed, so you never string-match an error envelope:
|
|
101
|
+
|
|
102
|
+
| Error | Means | What to do |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| `ConfigError` | Bad/missing identity or key | Fix config; thrown before any network call |
|
|
105
|
+
| `NetworkError` | Transport failed | `.message` diagnoses DNS / TLS / firewall / timeout |
|
|
106
|
+
| `AccessDeniedError` | No grant, or policy blocked it | `requestAccess()` — see below |
|
|
107
|
+
| `ApprovalDeniedError` | Owner said no | Terminal. Don't retry |
|
|
108
|
+
| `ApprovalExpiredError` | Aged out server-side | Re-issue the call |
|
|
109
|
+
| `ApprovalTimeoutError` | You stopped waiting | Resume via `waitForApproval(approvalId)` |
|
|
110
|
+
| `UpstreamError` | The SaaS itself returned non-2xx | `.status` / `.data` hold the upstream reply |
|
|
111
|
+
| `ProxyError` | Anything else from the broker | `.status` / `.body` |
|
|
112
|
+
|
|
113
|
+
## Asking for access you don't have
|
|
114
|
+
|
|
115
|
+
Deny-by-default means a scope you were never granted returns
|
|
116
|
+
`AccessDeniedError`. Your agent can ask for it:
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
const { status } = await av.requestAccess({
|
|
120
|
+
platform: "slack",
|
|
121
|
+
scope: "chat:write",
|
|
122
|
+
reason: "Post deploy notifications to #general",
|
|
123
|
+
});
|
|
124
|
+
if (status === "approved") { /* retry the original call */ }
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Checking before you act
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
await av.listPlatforms(); // what this agent is actually granted
|
|
131
|
+
await av.pendingActions(); // queued behind an approval
|
|
132
|
+
await av.evaluate("stripe", "charge"); // dry-run the decision, no side effect
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`evaluate()` is worth a call before anything destructive — it tells you whether
|
|
136
|
+
the action would be allowed without performing it.
|
|
137
|
+
|
|
138
|
+
## Self-hosting
|
|
139
|
+
|
|
140
|
+
Point `proxyUrl` at your own deployment. Everything else is identical.
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { type FetchLike } from "./http.js";
|
|
2
|
+
export interface AgentValetOptions {
|
|
3
|
+
agentId: string;
|
|
4
|
+
ownerId: string;
|
|
5
|
+
/** RS256 private key, PEM (PKCS#8). */
|
|
6
|
+
privateKey: string;
|
|
7
|
+
/** Defaults to https://api.agentvalet.ai. */
|
|
8
|
+
proxyUrl?: string;
|
|
9
|
+
/** Per-request network timeout. Default 15s. */
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
/**
|
|
12
|
+
* How long `call()` waits on an owner approval before throwing
|
|
13
|
+
* ApprovalTimeoutError. Default 50s. Set 0 to never wait — `call()` then
|
|
14
|
+
* throws immediately with the approval_id for you to resume later.
|
|
15
|
+
*/
|
|
16
|
+
approvalTimeoutMs?: number;
|
|
17
|
+
/** Approval poll interval. Default 2s. */
|
|
18
|
+
approvalPollMs?: number;
|
|
19
|
+
/** Injectable for tests / custom agents. Defaults to global fetch. */
|
|
20
|
+
fetch?: FetchLike;
|
|
21
|
+
/** Called roughly every poll while an approval is outstanding. */
|
|
22
|
+
onApprovalPending?: (info: {
|
|
23
|
+
approvalId: string;
|
|
24
|
+
elapsedMs: number;
|
|
25
|
+
platform: string;
|
|
26
|
+
scope: string;
|
|
27
|
+
endpoint: string;
|
|
28
|
+
}) => void;
|
|
29
|
+
}
|
|
30
|
+
export interface CallRequest {
|
|
31
|
+
platform: string;
|
|
32
|
+
endpoint: string;
|
|
33
|
+
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
34
|
+
scope: string;
|
|
35
|
+
data?: unknown;
|
|
36
|
+
/** Pick a specific connection when the platform has several. */
|
|
37
|
+
connectionId?: string;
|
|
38
|
+
/** Justification shown to the approver. Normalized and capped server-side. */
|
|
39
|
+
reason?: string;
|
|
40
|
+
/** Overrides the client-level approval budget for this one call. */
|
|
41
|
+
approvalTimeoutMs?: number;
|
|
42
|
+
}
|
|
43
|
+
export declare class AgentValet {
|
|
44
|
+
readonly agentId: string;
|
|
45
|
+
readonly ownerId: string;
|
|
46
|
+
readonly proxyUrl: string;
|
|
47
|
+
private readonly privateKeyPem;
|
|
48
|
+
private readonly timeoutMs;
|
|
49
|
+
private readonly approvalTimeoutMs;
|
|
50
|
+
private readonly approvalPollMs;
|
|
51
|
+
private readonly doFetch;
|
|
52
|
+
private readonly onApprovalPending?;
|
|
53
|
+
private importedKey;
|
|
54
|
+
constructor(opts: AgentValetOptions);
|
|
55
|
+
/**
|
|
56
|
+
* Builds a client from the environment. Works out of the box on a machine
|
|
57
|
+
* that has run `npx @agentvalet/register`. See env.ts for the accepted names.
|
|
58
|
+
*/
|
|
59
|
+
static fromEnv(overrides?: Partial<AgentValetOptions>): AgentValet;
|
|
60
|
+
/**
|
|
61
|
+
* Calls an approved platform through the broker. Returns the upstream SaaS
|
|
62
|
+
* response body, parsed.
|
|
63
|
+
*
|
|
64
|
+
* If the owner must approve, this blocks for up to `approvalTimeoutMs` and
|
|
65
|
+
* then returns the result transparently — from the caller's point of view an
|
|
66
|
+
* approved call just took longer. If nobody approves in time it throws
|
|
67
|
+
* ApprovalTimeoutError, whose `approvalId` you can resume with
|
|
68
|
+
* `waitForApproval()`; the action stays queued server-side either way.
|
|
69
|
+
*/
|
|
70
|
+
call<T = unknown>(req: CallRequest): Promise<T>;
|
|
71
|
+
/**
|
|
72
|
+
* Resumes waiting on an outstanding approval. Use with the `approvalId` from
|
|
73
|
+
* a caught ApprovalTimeoutError — the action is queued server-side, so this
|
|
74
|
+
* picks up exactly where `call()` left off.
|
|
75
|
+
*/
|
|
76
|
+
waitForApproval<T = unknown>(approvalId: string, ctx?: {
|
|
77
|
+
platform?: string;
|
|
78
|
+
scope?: string;
|
|
79
|
+
endpoint?: string;
|
|
80
|
+
timeoutMs?: number;
|
|
81
|
+
}): Promise<T>;
|
|
82
|
+
/** Platforms and scopes this agent is actually granted. Deny-by-default: if
|
|
83
|
+
* it isn't here, `call()` will 403. */
|
|
84
|
+
listPlatforms<T = unknown>(): Promise<T>;
|
|
85
|
+
/** Actions queued behind an owner approval that haven't resolved yet. */
|
|
86
|
+
pendingActions<T = unknown>(): Promise<T>;
|
|
87
|
+
/**
|
|
88
|
+
* Dry-run an authorization decision without performing the action. Cheap way
|
|
89
|
+
* to check a destructive scope before committing to a side effect.
|
|
90
|
+
*/
|
|
91
|
+
evaluate<T = unknown>(platform: string, scope: string): Promise<T>;
|
|
92
|
+
/**
|
|
93
|
+
* Asks an org admin to grant platform+scope, then polls for the decision.
|
|
94
|
+
* Resolves "approved" | "denied" | "pending" — on "approved", retry the
|
|
95
|
+
* original `call()`.
|
|
96
|
+
*/
|
|
97
|
+
requestAccess(req: {
|
|
98
|
+
platform: string;
|
|
99
|
+
scope?: string;
|
|
100
|
+
reason?: string;
|
|
101
|
+
timeoutMs?: number;
|
|
102
|
+
}): Promise<{
|
|
103
|
+
status: "approved" | "denied" | "pending";
|
|
104
|
+
requestToken: string;
|
|
105
|
+
}>;
|
|
106
|
+
/** Signs a short-lived (60s) RS256 assertion of this agent's identity. */
|
|
107
|
+
signJWT(): Promise<string>;
|
|
108
|
+
private authedFetch;
|
|
109
|
+
private getJson;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
// packages/client/src/client.ts
|
|
2
|
+
//
|
|
3
|
+
// The AgentValet client. This is the non-MCP path: a developer writing their
|
|
4
|
+
// own agent (LangChain, a cron job, a plain Node service) gets the same
|
|
5
|
+
// governance guarantees the MCP server provides — signed agent identity,
|
|
6
|
+
// deny-by-default scope enforcement, the owner-approval long-poll, and the
|
|
7
|
+
// audit record — without hand-rolling RS256 JWTs against /v1/actions.
|
|
8
|
+
//
|
|
9
|
+
// Deliberate parity with apps/mcp-server: same endpoints, same 50s approval
|
|
10
|
+
// budget, same 2s poll interval, same one-shot 401 retry. If these drift, an
|
|
11
|
+
// operator debugging the SDK can no longer reason from the MCP server's
|
|
12
|
+
// behaviour (and vice versa).
|
|
13
|
+
import { SignJWT, importPKCS8 } from "jose";
|
|
14
|
+
import { AccessDeniedError, ApprovalDeniedError, ApprovalExpiredError, ApprovalTimeoutError, ConfigError, ProxyError, UpstreamError, } from "./errors.js";
|
|
15
|
+
import { diagnoseNetworkError, fetchWithTimeout, sleep, tryParseJson } from "./http.js";
|
|
16
|
+
import { DEFAULT_PROXY_URL, agentIdFromEnv, ownerIdFromEnv, privateKeyFromEnv, proxyUrlFromEnv, } from "./env.js";
|
|
17
|
+
/** Matches the mcp-server's budget: under Claude Desktop's 60s tool timeout. */
|
|
18
|
+
const DEFAULT_APPROVAL_TIMEOUT_MS = 50_000;
|
|
19
|
+
const DEFAULT_APPROVAL_POLL_MS = 2_000;
|
|
20
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 15_000;
|
|
21
|
+
export class AgentValet {
|
|
22
|
+
agentId;
|
|
23
|
+
ownerId;
|
|
24
|
+
proxyUrl;
|
|
25
|
+
privateKeyPem;
|
|
26
|
+
timeoutMs;
|
|
27
|
+
approvalTimeoutMs;
|
|
28
|
+
approvalPollMs;
|
|
29
|
+
doFetch;
|
|
30
|
+
onApprovalPending;
|
|
31
|
+
importedKey = null;
|
|
32
|
+
constructor(opts) {
|
|
33
|
+
if (!opts.agentId)
|
|
34
|
+
throw new ConfigError("agentId is required");
|
|
35
|
+
if (!opts.ownerId)
|
|
36
|
+
throw new ConfigError("ownerId is required");
|
|
37
|
+
if (!opts.privateKey)
|
|
38
|
+
throw new ConfigError("privateKey is required");
|
|
39
|
+
this.agentId = opts.agentId;
|
|
40
|
+
this.ownerId = opts.ownerId;
|
|
41
|
+
this.privateKeyPem = opts.privateKey;
|
|
42
|
+
this.proxyUrl = (opts.proxyUrl ?? DEFAULT_PROXY_URL).replace(/\/$/, "");
|
|
43
|
+
this.timeoutMs = opts.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
44
|
+
this.approvalTimeoutMs = opts.approvalTimeoutMs ?? DEFAULT_APPROVAL_TIMEOUT_MS;
|
|
45
|
+
this.approvalPollMs = opts.approvalPollMs ?? DEFAULT_APPROVAL_POLL_MS;
|
|
46
|
+
this.doFetch = opts.fetch ?? ((url, init) => fetch(url, init));
|
|
47
|
+
this.onApprovalPending = opts.onApprovalPending;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Builds a client from the environment. Works out of the box on a machine
|
|
51
|
+
* that has run `npx @agentvalet/register`. See env.ts for the accepted names.
|
|
52
|
+
*/
|
|
53
|
+
static fromEnv(overrides = {}) {
|
|
54
|
+
const agentId = overrides.agentId ?? agentIdFromEnv();
|
|
55
|
+
const ownerId = overrides.ownerId ?? ownerIdFromEnv();
|
|
56
|
+
if (!agentId || !ownerId) {
|
|
57
|
+
throw new ConfigError("AgentValet identity not found in the environment. Set AGENTVALET_AGENT_ID and " +
|
|
58
|
+
"AGENTVALET_OWNER_ID (or AGENT_ID / OWNER_ID), or run `npx @agentvalet/register`.");
|
|
59
|
+
}
|
|
60
|
+
return new AgentValet({
|
|
61
|
+
...overrides,
|
|
62
|
+
agentId,
|
|
63
|
+
ownerId,
|
|
64
|
+
privateKey: overrides.privateKey ?? privateKeyFromEnv(),
|
|
65
|
+
proxyUrl: overrides.proxyUrl ?? proxyUrlFromEnv(),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
// ---- core ---------------------------------------------------------------
|
|
69
|
+
/**
|
|
70
|
+
* Calls an approved platform through the broker. Returns the upstream SaaS
|
|
71
|
+
* response body, parsed.
|
|
72
|
+
*
|
|
73
|
+
* If the owner must approve, this blocks for up to `approvalTimeoutMs` and
|
|
74
|
+
* then returns the result transparently — from the caller's point of view an
|
|
75
|
+
* approved call just took longer. If nobody approves in time it throws
|
|
76
|
+
* ApprovalTimeoutError, whose `approvalId` you can resume with
|
|
77
|
+
* `waitForApproval()`; the action stays queued server-side either way.
|
|
78
|
+
*/
|
|
79
|
+
async call(req) {
|
|
80
|
+
const body = {
|
|
81
|
+
platform: req.platform,
|
|
82
|
+
endpoint: req.endpoint,
|
|
83
|
+
method: req.method ?? "GET",
|
|
84
|
+
scope: req.scope,
|
|
85
|
+
...(req.data !== undefined && { data: req.data }),
|
|
86
|
+
...(req.connectionId ? { connection_id: req.connectionId } : {}),
|
|
87
|
+
...(req.reason ? { reason: req.reason } : {}),
|
|
88
|
+
};
|
|
89
|
+
const res = await this.authedFetch("/v1/actions", { method: "POST", body: JSON.stringify(body) });
|
|
90
|
+
const text = await res.text();
|
|
91
|
+
// 202 + approval_id → the owner needs to approve. Enter the long-poll.
|
|
92
|
+
if (res.status === 202) {
|
|
93
|
+
const approvalId = tryParseJson(text)?.approval_id;
|
|
94
|
+
if (approvalId) {
|
|
95
|
+
return (await this.waitForApproval(approvalId, {
|
|
96
|
+
platform: req.platform,
|
|
97
|
+
scope: req.scope,
|
|
98
|
+
endpoint: req.endpoint,
|
|
99
|
+
timeoutMs: req.approvalTimeoutMs ?? this.approvalTimeoutMs,
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (!res.ok) {
|
|
104
|
+
// 403 is the proxy's authorize-pipeline denial (no grant, or policy
|
|
105
|
+
// blocked). Surface it as its own type so callers can branch into
|
|
106
|
+
// requestAccess() instead of dead-ending on a generic failure.
|
|
107
|
+
if (res.status === 403) {
|
|
108
|
+
throw new AccessDeniedError(res.status, text, req.platform, req.scope);
|
|
109
|
+
}
|
|
110
|
+
throw new ProxyError(res.status, text);
|
|
111
|
+
}
|
|
112
|
+
return (tryParseJson(text) ?? text);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Resumes waiting on an outstanding approval. Use with the `approvalId` from
|
|
116
|
+
* a caught ApprovalTimeoutError — the action is queued server-side, so this
|
|
117
|
+
* picks up exactly where `call()` left off.
|
|
118
|
+
*/
|
|
119
|
+
async waitForApproval(approvalId, ctx = {}) {
|
|
120
|
+
const budget = ctx.timeoutMs ?? this.approvalTimeoutMs;
|
|
121
|
+
const startedAt = Date.now();
|
|
122
|
+
while (Date.now() - startedAt < budget) {
|
|
123
|
+
await sleep(this.approvalPollMs);
|
|
124
|
+
const elapsed = Date.now() - startedAt;
|
|
125
|
+
let res;
|
|
126
|
+
try {
|
|
127
|
+
res = await this.authedFetch(`/v1/approvals/${encodeURIComponent(approvalId)}`, { method: "GET" });
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
continue; // transient — try again next tick
|
|
131
|
+
}
|
|
132
|
+
if (!res.ok)
|
|
133
|
+
throw new ProxyError(res.status, await res.text());
|
|
134
|
+
const status = (await res.json());
|
|
135
|
+
if (status.status === "denied") {
|
|
136
|
+
throw new ApprovalDeniedError(approvalId, status.execution_error);
|
|
137
|
+
}
|
|
138
|
+
if (status.status === "expired") {
|
|
139
|
+
throw new ApprovalExpiredError(approvalId);
|
|
140
|
+
}
|
|
141
|
+
if (status.execution_error) {
|
|
142
|
+
// Approved, but the re-execution failed (upstream down, agent revoked).
|
|
143
|
+
throw new ProxyError(502, `Approved but re-execution failed: ${status.execution_error}`);
|
|
144
|
+
}
|
|
145
|
+
if (status.status === "approved" && status.executed_at && status.result) {
|
|
146
|
+
const r = status.result;
|
|
147
|
+
if (r.status < 200 || r.status >= 300)
|
|
148
|
+
throw new UpstreamError(r.status, r.data);
|
|
149
|
+
return r.data;
|
|
150
|
+
}
|
|
151
|
+
this.onApprovalPending?.({
|
|
152
|
+
approvalId,
|
|
153
|
+
elapsedMs: elapsed,
|
|
154
|
+
platform: ctx.platform ?? "",
|
|
155
|
+
scope: ctx.scope ?? "",
|
|
156
|
+
endpoint: ctx.endpoint ?? "",
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
throw new ApprovalTimeoutError(approvalId, budget);
|
|
160
|
+
}
|
|
161
|
+
// ---- discovery / governance --------------------------------------------
|
|
162
|
+
/** Platforms and scopes this agent is actually granted. Deny-by-default: if
|
|
163
|
+
* it isn't here, `call()` will 403. */
|
|
164
|
+
async listPlatforms() {
|
|
165
|
+
return this.getJson("/v1/agent/permissions");
|
|
166
|
+
}
|
|
167
|
+
/** Actions queued behind an owner approval that haven't resolved yet. */
|
|
168
|
+
async pendingActions() {
|
|
169
|
+
return this.getJson("/v1/agents/me/pending-actions");
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Dry-run an authorization decision without performing the action. Cheap way
|
|
173
|
+
* to check a destructive scope before committing to a side effect.
|
|
174
|
+
*/
|
|
175
|
+
async evaluate(platform, scope) {
|
|
176
|
+
const res = await this.authedFetch("/v1/authzen/access", {
|
|
177
|
+
method: "POST",
|
|
178
|
+
body: JSON.stringify({
|
|
179
|
+
subject: { type: "agent", id: this.agentId },
|
|
180
|
+
action: { name: "tool_call" },
|
|
181
|
+
resource: { type: "platform_scope", id: `${platform}:${scope}` },
|
|
182
|
+
}),
|
|
183
|
+
});
|
|
184
|
+
const text = await res.text();
|
|
185
|
+
if (!res.ok)
|
|
186
|
+
throw new ProxyError(res.status, text);
|
|
187
|
+
return (tryParseJson(text) ?? text);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Asks an org admin to grant platform+scope, then polls for the decision.
|
|
191
|
+
* Resolves "approved" | "denied" | "pending" — on "approved", retry the
|
|
192
|
+
* original `call()`.
|
|
193
|
+
*/
|
|
194
|
+
async requestAccess(req) {
|
|
195
|
+
const submit = await this.authedFetch("/v1/access-request", {
|
|
196
|
+
method: "POST",
|
|
197
|
+
body: JSON.stringify({ platform: req.platform, scope: req.scope, reason: req.reason }),
|
|
198
|
+
});
|
|
199
|
+
if (!submit.ok && submit.status !== 202) {
|
|
200
|
+
throw new ProxyError(submit.status, await submit.text());
|
|
201
|
+
}
|
|
202
|
+
const { request_token: token } = (await submit.json());
|
|
203
|
+
if (!token)
|
|
204
|
+
throw new ProxyError(submit.status, "Access request did not return a request_token.");
|
|
205
|
+
const deadline = Date.now() + (req.timeoutMs ?? this.approvalTimeoutMs);
|
|
206
|
+
while (Date.now() < deadline) {
|
|
207
|
+
await sleep(this.approvalPollMs);
|
|
208
|
+
let res;
|
|
209
|
+
try {
|
|
210
|
+
res = await this.authedFetch(`/v1/access-request/status/${encodeURIComponent(token)}`, { method: "GET" });
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
if (!res.ok)
|
|
216
|
+
continue;
|
|
217
|
+
const s = (await res.json());
|
|
218
|
+
if (s.status === "approved")
|
|
219
|
+
return { status: "approved", requestToken: token };
|
|
220
|
+
if (s.status === "denied")
|
|
221
|
+
return { status: "denied", requestToken: token };
|
|
222
|
+
}
|
|
223
|
+
return { status: "pending", requestToken: token };
|
|
224
|
+
}
|
|
225
|
+
// ---- transport ----------------------------------------------------------
|
|
226
|
+
/** Signs a short-lived (60s) RS256 assertion of this agent's identity. */
|
|
227
|
+
async signJWT() {
|
|
228
|
+
if (!this.importedKey) {
|
|
229
|
+
try {
|
|
230
|
+
this.importedKey = await importPKCS8(this.privateKeyPem, "RS256");
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
throw new ConfigError(`Private key is not a valid PKCS#8 RS256 PEM: ${err instanceof Error ? err.message : err}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return new SignJWT({ agent_id: this.agentId, owner_id: this.ownerId })
|
|
237
|
+
.setProtectedHeader({ alg: "RS256" })
|
|
238
|
+
.setIssuedAt()
|
|
239
|
+
.setExpirationTime("60s")
|
|
240
|
+
.sign(this.importedKey);
|
|
241
|
+
}
|
|
242
|
+
async authedFetch(path, init) {
|
|
243
|
+
const url = `${this.proxyUrl}${path}`;
|
|
244
|
+
const once = async () => {
|
|
245
|
+
const token = await this.signJWT();
|
|
246
|
+
try {
|
|
247
|
+
return await fetchWithTimeout(this.doFetch, url, {
|
|
248
|
+
...init,
|
|
249
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", ...init.headers },
|
|
250
|
+
}, this.timeoutMs);
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
throw diagnoseNetworkError(err, this.proxyUrl);
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
const res = await once();
|
|
257
|
+
// Retry once on 401 — the JWT may have been minted either side of a clock
|
|
258
|
+
// skew boundary. Same one-shot retry the mcp-server does.
|
|
259
|
+
return res.status === 401 ? once() : res;
|
|
260
|
+
}
|
|
261
|
+
async getJson(path) {
|
|
262
|
+
const res = await this.authedFetch(path, { method: "GET" });
|
|
263
|
+
const text = await res.text();
|
|
264
|
+
if (!res.ok)
|
|
265
|
+
throw new ProxyError(res.status, text);
|
|
266
|
+
return (tryParseJson(text) ?? text);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/env.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const DEFAULT_PROXY_URL = "https://api.agentvalet.ai";
|
|
2
|
+
export declare function agentIdFromEnv(): string | null;
|
|
3
|
+
export declare function ownerIdFromEnv(): string | null;
|
|
4
|
+
export declare function proxyUrlFromEnv(): string;
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the RS256 private key PEM, in precedence order:
|
|
7
|
+
* 1. AGENT_PRIVATE_KEY_B64 — base64-encoded PEM (12-factor / container safe)
|
|
8
|
+
* 2. AGENT_PRIVATE_KEY_PATH — path to a PEM file
|
|
9
|
+
* 3. AGENT_PRIVATE_KEY — raw multi-line PEM, or \n-escaped single line
|
|
10
|
+
* 4. ~/.agentvalet/agent.key — written by `npx @agentvalet/register`
|
|
11
|
+
*
|
|
12
|
+
* Same order and same formats as the mcp-server's pem.ts, so a dev who already
|
|
13
|
+
* has the MCP server working can construct the SDK with no new setup.
|
|
14
|
+
*/
|
|
15
|
+
export declare function privateKeyFromEnv(): string;
|
|
16
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,iBAAiB,8BAA8B,CAAC;AAmB7D,wBAAgB,cAAc,IAAI,MAAM,GAAG,IAAI,CAE9C;AAED,wBAAgB,cAAc,IAAI,MAAM,GAAG,IAAI,CAE9C;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAiC1C"}
|
package/dist/env.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// packages/client/src/env.ts
|
|
2
|
+
//
|
|
3
|
+
// Environment resolution for AgentValet.fromEnv().
|
|
4
|
+
//
|
|
5
|
+
// Accepts BOTH naming conventions already in the wild: the bare names the
|
|
6
|
+
// mcp-server/MCPB write (AGENT_ID, OWNER_ID, PROXY_URL, AGENT_PRIVATE_KEY*)
|
|
7
|
+
// and AGENTVALET_-prefixed aliases, which is what the docs and the
|
|
8
|
+
// credentials-not-configured message tell people to set. A machine that has
|
|
9
|
+
// been through `npx @agentvalet/register` already satisfies the bare set, so
|
|
10
|
+
// fromEnv() works with zero extra config there.
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { ConfigError } from "./errors.js";
|
|
15
|
+
export const DEFAULT_PROXY_URL = "https://api.agentvalet.ai";
|
|
16
|
+
// Treat empty strings and unresolved MCPB placeholders ("${user_config.foo}")
|
|
17
|
+
// as not-set. The MCPB writes literal placeholders when a user_config field is
|
|
18
|
+
// left blank, and a literal "${...}" agent id fails far more confusingly later.
|
|
19
|
+
function readEnv(name) {
|
|
20
|
+
const v = process.env[name];
|
|
21
|
+
if (v === undefined)
|
|
22
|
+
return null;
|
|
23
|
+
const t = v.trim();
|
|
24
|
+
if (t === "")
|
|
25
|
+
return null;
|
|
26
|
+
if (t.startsWith("${") && t.endsWith("}"))
|
|
27
|
+
return null;
|
|
28
|
+
return t;
|
|
29
|
+
}
|
|
30
|
+
/** AGENTVALET_-prefixed name wins over the bare name when both are set. */
|
|
31
|
+
function readEither(suffix) {
|
|
32
|
+
return readEnv(`AGENTVALET_${suffix}`) ?? readEnv(suffix);
|
|
33
|
+
}
|
|
34
|
+
export function agentIdFromEnv() {
|
|
35
|
+
return readEither("AGENT_ID");
|
|
36
|
+
}
|
|
37
|
+
export function ownerIdFromEnv() {
|
|
38
|
+
return readEither("OWNER_ID");
|
|
39
|
+
}
|
|
40
|
+
export function proxyUrlFromEnv() {
|
|
41
|
+
return (readEither("PROXY_URL") ?? DEFAULT_PROXY_URL).replace(/\/$/, "");
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Resolves the RS256 private key PEM, in precedence order:
|
|
45
|
+
* 1. AGENT_PRIVATE_KEY_B64 — base64-encoded PEM (12-factor / container safe)
|
|
46
|
+
* 2. AGENT_PRIVATE_KEY_PATH — path to a PEM file
|
|
47
|
+
* 3. AGENT_PRIVATE_KEY — raw multi-line PEM, or \n-escaped single line
|
|
48
|
+
* 4. ~/.agentvalet/agent.key — written by `npx @agentvalet/register`
|
|
49
|
+
*
|
|
50
|
+
* Same order and same formats as the mcp-server's pem.ts, so a dev who already
|
|
51
|
+
* has the MCP server working can construct the SDK with no new setup.
|
|
52
|
+
*/
|
|
53
|
+
export function privateKeyFromEnv() {
|
|
54
|
+
const b64 = readEither("AGENT_PRIVATE_KEY_B64");
|
|
55
|
+
if (b64)
|
|
56
|
+
return Buffer.from(b64, "base64").toString("utf-8").trim();
|
|
57
|
+
const path = readEither("AGENT_PRIVATE_KEY_PATH");
|
|
58
|
+
if (path) {
|
|
59
|
+
try {
|
|
60
|
+
return readFileSync(path, "utf-8").trim();
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
throw new ConfigError(`Cannot read AGENT_PRIVATE_KEY_PATH (${path}): ${err instanceof Error ? err.message : err}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const raw = readEither("AGENT_PRIVATE_KEY");
|
|
67
|
+
if (raw) {
|
|
68
|
+
const unescaped = raw.replace(/\\n/g, "\n");
|
|
69
|
+
// Tolerate a bare base64 blob with the PEM armour stripped — a common
|
|
70
|
+
// casualty of pasting a key through a secrets UI that trims delimiters.
|
|
71
|
+
if (!unescaped.startsWith("-----")) {
|
|
72
|
+
return `-----BEGIN PRIVATE KEY-----\n${unescaped}\n-----END PRIVATE KEY-----`;
|
|
73
|
+
}
|
|
74
|
+
return unescaped;
|
|
75
|
+
}
|
|
76
|
+
const diskKey = readDiskKey();
|
|
77
|
+
if (diskKey)
|
|
78
|
+
return diskKey;
|
|
79
|
+
throw new ConfigError("No private key found. Set AGENT_PRIVATE_KEY, AGENT_PRIVATE_KEY_PATH, or AGENT_PRIVATE_KEY_B64, " +
|
|
80
|
+
"or run `npx @agentvalet/register` to create an agent and write ~/.agentvalet/agent.key.");
|
|
81
|
+
}
|
|
82
|
+
function readDiskKey() {
|
|
83
|
+
try {
|
|
84
|
+
return readFileSync(join(homedir(), ".agentvalet", "agent.key"), "utf-8").trim() || null;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=env.js.map
|
package/dist/env.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export declare class AgentValetError extends Error {
|
|
2
|
+
constructor(message: string);
|
|
3
|
+
}
|
|
4
|
+
/** Missing/!malformed identity or key — thrown before any network call. */
|
|
5
|
+
export declare class ConfigError extends AgentValetError {
|
|
6
|
+
}
|
|
7
|
+
/** fetch() itself failed. `.hint` carries an actionable diagnosis. */
|
|
8
|
+
export declare class NetworkError extends AgentValetError {
|
|
9
|
+
readonly cause: unknown;
|
|
10
|
+
constructor(message: string, cause: unknown);
|
|
11
|
+
}
|
|
12
|
+
/** Non-2xx from the AgentValet proxy that isn't a more specific case below. */
|
|
13
|
+
export declare class ProxyError extends AgentValetError {
|
|
14
|
+
readonly status: number;
|
|
15
|
+
readonly body: string;
|
|
16
|
+
constructor(status: number, body: string);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 403 — the agent has no grant for this platform+scope, or policy blocked it.
|
|
20
|
+
* Recoverable: call `requestAccess({ platform, scope, reason })`.
|
|
21
|
+
*/
|
|
22
|
+
export declare class AccessDeniedError extends ProxyError {
|
|
23
|
+
readonly platform: string;
|
|
24
|
+
readonly scope: string;
|
|
25
|
+
constructor(status: number, body: string, platform: string, scope: string);
|
|
26
|
+
}
|
|
27
|
+
/** The owner explicitly denied the action. Terminal — do not retry. */
|
|
28
|
+
export declare class ApprovalDeniedError extends AgentValetError {
|
|
29
|
+
readonly approvalId: string;
|
|
30
|
+
constructor(approvalId: string, detail?: string);
|
|
31
|
+
}
|
|
32
|
+
/** The approval request aged out server-side before anyone responded. */
|
|
33
|
+
export declare class ApprovalExpiredError extends AgentValetError {
|
|
34
|
+
readonly approvalId: string;
|
|
35
|
+
constructor(approvalId: string);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* We stopped waiting, but the action is still queued server-side and will run
|
|
39
|
+
* if the owner approves. NOT a failure — hold `approvalId` and resume later
|
|
40
|
+
* with `client.waitForApproval(approvalId)`.
|
|
41
|
+
*/
|
|
42
|
+
export declare class ApprovalTimeoutError extends AgentValetError {
|
|
43
|
+
readonly approvalId: string;
|
|
44
|
+
constructor(approvalId: string, waitedMs: number);
|
|
45
|
+
}
|
|
46
|
+
/** Approved and executed, but the upstream SaaS returned a non-2xx. */
|
|
47
|
+
export declare class UpstreamError extends AgentValetError {
|
|
48
|
+
readonly status: number;
|
|
49
|
+
readonly data: unknown;
|
|
50
|
+
constructor(status: number, data: unknown);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAMA,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED,2EAA2E;AAC3E,qBAAa,WAAY,SAAQ,eAAe;CAAG;AAEnD,sEAAsE;AACtE,qBAAa,YAAa,SAAQ,eAAe;IAClB,QAAQ,CAAC,KAAK,EAAE,OAAO;gBAAxC,OAAO,EAAE,MAAM,EAAW,KAAK,EAAE,OAAO;CAGrD;AAED,+EAA+E;AAC/E,qBAAa,UAAW,SAAQ,eAAe;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAArC,MAAM,EAAE,MAAM,EAAW,IAAI,EAAE,MAAM;CAG3D;AAED;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,UAAU;IACL,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM;gBAA/E,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAW,QAAQ,EAAE,MAAM,EAAW,KAAK,EAAE,MAAM;CAM5F;AAED,uEAAuE;AACvE,qBAAa,mBAAoB,SAAQ,eAAe;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM;gBAAlB,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAGzD;AAED,yEAAyE;AACzE,qBAAa,oBAAqB,SAAQ,eAAe;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM;gBAAlB,UAAU,EAAE,MAAM;CAGxC;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,eAAe;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM;gBAAlB,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAM1D;AAED,uEAAuE;AACvE,qBAAa,aAAc,SAAQ,eAAe;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO;gBAAtC,MAAM,EAAE,MAAM,EAAW,IAAI,EAAE,OAAO;CAG5D"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// packages/client/src/errors.ts
|
|
2
|
+
//
|
|
3
|
+
// Typed error hierarchy. The whole point of the SDK over raw /v1/actions is
|
|
4
|
+
// that a caller can branch on WHY a call failed without string-matching the
|
|
5
|
+
// proxy's error envelope. Every throw from the client is one of these.
|
|
6
|
+
export class AgentValetError extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = new.target.name;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Missing/!malformed identity or key — thrown before any network call. */
|
|
13
|
+
export class ConfigError extends AgentValetError {
|
|
14
|
+
}
|
|
15
|
+
/** fetch() itself failed. `.hint` carries an actionable diagnosis. */
|
|
16
|
+
export class NetworkError extends AgentValetError {
|
|
17
|
+
cause;
|
|
18
|
+
constructor(message, cause) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.cause = cause;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Non-2xx from the AgentValet proxy that isn't a more specific case below. */
|
|
24
|
+
export class ProxyError extends AgentValetError {
|
|
25
|
+
status;
|
|
26
|
+
body;
|
|
27
|
+
constructor(status, body) {
|
|
28
|
+
super(`Proxy error ${status}: ${body}`);
|
|
29
|
+
this.status = status;
|
|
30
|
+
this.body = body;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 403 — the agent has no grant for this platform+scope, or policy blocked it.
|
|
35
|
+
* Recoverable: call `requestAccess({ platform, scope, reason })`.
|
|
36
|
+
*/
|
|
37
|
+
export class AccessDeniedError extends ProxyError {
|
|
38
|
+
platform;
|
|
39
|
+
scope;
|
|
40
|
+
constructor(status, body, platform, scope) {
|
|
41
|
+
super(status, body);
|
|
42
|
+
this.platform = platform;
|
|
43
|
+
this.scope = scope;
|
|
44
|
+
this.message =
|
|
45
|
+
`Access denied for ${platform}:${scope} — ${body}. ` +
|
|
46
|
+
`Call requestAccess({ platform, scope, reason }) to ask an org admin to grant it.`;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** The owner explicitly denied the action. Terminal — do not retry. */
|
|
50
|
+
export class ApprovalDeniedError extends AgentValetError {
|
|
51
|
+
approvalId;
|
|
52
|
+
constructor(approvalId, detail) {
|
|
53
|
+
super(`Owner denied this action${detail ? `: ${detail}` : "."}`);
|
|
54
|
+
this.approvalId = approvalId;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** The approval request aged out server-side before anyone responded. */
|
|
58
|
+
export class ApprovalExpiredError extends AgentValetError {
|
|
59
|
+
approvalId;
|
|
60
|
+
constructor(approvalId) {
|
|
61
|
+
super("Approval request expired before the owner responded.");
|
|
62
|
+
this.approvalId = approvalId;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* We stopped waiting, but the action is still queued server-side and will run
|
|
67
|
+
* if the owner approves. NOT a failure — hold `approvalId` and resume later
|
|
68
|
+
* with `client.waitForApproval(approvalId)`.
|
|
69
|
+
*/
|
|
70
|
+
export class ApprovalTimeoutError extends AgentValetError {
|
|
71
|
+
approvalId;
|
|
72
|
+
constructor(approvalId, waitedMs) {
|
|
73
|
+
super(`Owner hasn't approved within ${Math.round(waitedMs / 1000)}s. The action is still queued — ` +
|
|
74
|
+
`keep approval_id ${approvalId} and call waitForApproval(approvalId) to resume.`);
|
|
75
|
+
this.approvalId = approvalId;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** Approved and executed, but the upstream SaaS returned a non-2xx. */
|
|
79
|
+
export class UpstreamError extends AgentValetError {
|
|
80
|
+
status;
|
|
81
|
+
data;
|
|
82
|
+
constructor(status, data) {
|
|
83
|
+
super(`Upstream returned ${status}: ${JSON.stringify(data)}`);
|
|
84
|
+
this.status = status;
|
|
85
|
+
this.data = data;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,EAAE;AACF,4EAA4E;AAC5E,4EAA4E;AAC5E,uEAAuE;AAEvE,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;IAC9B,CAAC;CACF;AAED,2EAA2E;AAC3E,MAAM,OAAO,WAAY,SAAQ,eAAe;CAAG;AAEnD,sEAAsE;AACtE,MAAM,OAAO,YAAa,SAAQ,eAAe;IACT;IAAtC,YAAY,OAAe,EAAW,KAAc;QAClD,KAAK,CAAC,OAAO,CAAC,CAAC;QADqB,UAAK,GAAL,KAAK,CAAS;IAEpD,CAAC;CACF;AAED,+EAA+E;AAC/E,MAAM,OAAO,UAAW,SAAQ,eAAe;IACxB;IAAyB;IAA9C,YAAqB,MAAc,EAAW,IAAY;QACxD,KAAK,CAAC,eAAe,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QADrB,WAAM,GAAN,MAAM,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAQ;IAE1D,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,UAAU;IACI;IAA2B;IAA9E,YAAY,MAAc,EAAE,IAAY,EAAW,QAAgB,EAAW,KAAa;QACzF,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAD6B,aAAQ,GAAR,QAAQ,CAAQ;QAAW,UAAK,GAAL,KAAK,CAAQ;QAEzF,IAAI,CAAC,OAAO;YACV,qBAAqB,QAAQ,IAAI,KAAK,MAAM,IAAI,IAAI;gBACpD,kFAAkF,CAAC;IACvF,CAAC;CACF;AAED,uEAAuE;AACvE,MAAM,OAAO,mBAAoB,SAAQ,eAAe;IACjC;IAArB,YAAqB,UAAkB,EAAE,MAAe;QACtD,KAAK,CAAC,2BAA2B,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QAD9C,eAAU,GAAV,UAAU,CAAQ;IAEvC,CAAC;CACF;AAED,yEAAyE;AACzE,MAAM,OAAO,oBAAqB,SAAQ,eAAe;IAClC;IAArB,YAAqB,UAAkB;QACrC,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAD3C,eAAU,GAAV,UAAU,CAAQ;IAEvC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,oBAAqB,SAAQ,eAAe;IAClC;IAArB,YAAqB,UAAkB,EAAE,QAAgB;QACvD,KAAK,CACH,gCAAgC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,kCAAkC;YAC3F,oBAAoB,UAAU,kDAAkD,CACnF,CAAC;QAJiB,eAAU,GAAV,UAAU,CAAQ;IAKvC,CAAC;CACF;AAED,uEAAuE;AACvE,MAAM,OAAO,aAAc,SAAQ,eAAe;IAC3B;IAAyB;IAA9C,YAAqB,MAAc,EAAW,IAAa;QACzD,KAAK,CAAC,qBAAqB,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAD3C,WAAM,GAAN,MAAM,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAS;IAE3D,CAAC;CACF"}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { NetworkError } from "./errors.js";
|
|
2
|
+
export type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
3
|
+
export declare function fetchWithTimeout(doFetch: FetchLike, url: string, init: RequestInit, timeoutMs: number): Promise<Response>;
|
|
4
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
5
|
+
export declare function tryParseJson(text: string): unknown;
|
|
6
|
+
export declare function diagnoseNetworkError(err: unknown, proxyUrl: string): NetworkError;
|
|
7
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjF,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,EAClB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,WAAW,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,QAAQ,CAAC,CAInB;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQlD;AAKD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAiBjF"}
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// packages/client/src/http.ts
|
|
2
|
+
//
|
|
3
|
+
// Stateless transport helpers. Kept behaviourally identical to the mcp-server's
|
|
4
|
+
// net.ts so the SDK and the MCP server fail the same way on the same network
|
|
5
|
+
// conditions — an operator debugging one is debugging both.
|
|
6
|
+
import { NetworkError } from "./errors.js";
|
|
7
|
+
export function fetchWithTimeout(doFetch, url, init, timeoutMs) {
|
|
8
|
+
const ac = new AbortController();
|
|
9
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
10
|
+
return doFetch(url, { ...init, signal: ac.signal }).finally(() => clearTimeout(timer));
|
|
11
|
+
}
|
|
12
|
+
export function sleep(ms) {
|
|
13
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
14
|
+
}
|
|
15
|
+
export function tryParseJson(text) {
|
|
16
|
+
const trimmed = text.trim();
|
|
17
|
+
if (!trimmed.startsWith("{") && !trimmed.startsWith("["))
|
|
18
|
+
return undefined;
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(trimmed);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Translates a fetch() failure into something a developer can act on. The
|
|
27
|
+
// default "fetch failed" tells you nothing about whether it's DNS, a corporate
|
|
28
|
+
// MITM proxy, or the proxy being down.
|
|
29
|
+
export function diagnoseNetworkError(err, proxyUrl) {
|
|
30
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
31
|
+
const lower = raw.toLowerCase();
|
|
32
|
+
let message;
|
|
33
|
+
if (lower.includes("enotfound") || lower.includes("getaddrinfo")) {
|
|
34
|
+
message = `Cannot resolve ${proxyUrl}. Check DNS / corporate proxy / VPN, or confirm proxyUrl is correct. Raw: ${raw}`;
|
|
35
|
+
}
|
|
36
|
+
else if (lower.includes("econnrefused") || lower.includes("econnreset")) {
|
|
37
|
+
message = `Connection to ${proxyUrl} was refused or reset. The proxy may be down — check https://status.agentvalet.ai — or a firewall is blocking it. Raw: ${raw}`;
|
|
38
|
+
}
|
|
39
|
+
else if (lower.includes("etimedout") || lower.includes("timeout") || lower.includes("aborterror")) {
|
|
40
|
+
message = `Request to ${proxyUrl} timed out. Likely VPN routing, corporate proxy buffering, or a slow network. Raw: ${raw}`;
|
|
41
|
+
}
|
|
42
|
+
else if (lower.includes("self signed") || lower.includes("cert") || lower.includes("ssl") || lower.includes("tls")) {
|
|
43
|
+
message = `TLS / certificate problem talking to ${proxyUrl}. A corporate MITM proxy may be intercepting traffic. Raw: ${raw}`;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
message = `Network error reaching ${proxyUrl}: ${raw}. Check VPN, corporate proxy, and firewall rules for api.agentvalet.ai.`;
|
|
47
|
+
}
|
|
48
|
+
return new NetworkError(message, err);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,gFAAgF;AAChF,6EAA6E;AAC7E,4DAA4D;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,MAAM,UAAU,gBAAgB,CAC9B,OAAkB,EAClB,GAAW,EACX,IAAiB,EACjB,SAAiB;IAEjB,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;IACjC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;IACtD,OAAO,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AACzF,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3E,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,+EAA+E;AAC/E,uCAAuC;AACvC,MAAM,UAAU,oBAAoB,CAAC,GAAY,EAAE,QAAgB;IACjE,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAEhC,IAAI,OAAe,CAAC;IACpB,IAAI,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACjE,OAAO,GAAG,kBAAkB,QAAQ,6EAA6E,GAAG,EAAE,CAAC;IACzH,CAAC;SAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC1E,OAAO,GAAG,iBAAiB,QAAQ,0HAA0H,GAAG,EAAE,CAAC;IACrK,CAAC;SAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACpG,OAAO,GAAG,cAAc,QAAQ,sFAAsF,GAAG,EAAE,CAAC;IAC9H,CAAC;SAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrH,OAAO,GAAG,wCAAwC,QAAQ,8DAA8D,GAAG,EAAE,CAAC;IAChI,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,0BAA0B,QAAQ,KAAK,GAAG,yEAAyE,CAAC;IAChI,CAAC;IACD,OAAO,IAAI,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AACxC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { AgentValet } from "./client.js";
|
|
2
|
+
export type { AgentValetOptions, CallRequest } from "./client.js";
|
|
3
|
+
export { AgentValetError, AccessDeniedError, ApprovalDeniedError, ApprovalExpiredError, ApprovalTimeoutError, ConfigError, NetworkError, ProxyError, UpstreamError, } from "./errors.js";
|
|
4
|
+
export { DEFAULT_PROXY_URL } from "./env.js";
|
|
5
|
+
export type { FetchLike } from "./http.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAElE,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,WAAW,EACX,YAAY,EACZ,UAAU,EACV,aAAa,GACd,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// packages/client/src/index.ts
|
|
2
|
+
//
|
|
3
|
+
// @agentvalet/client — the non-MCP path onto the AgentValet broker.
|
|
4
|
+
//
|
|
5
|
+
// If you're inside an MCP host (Claude Code, Claude Desktop, Cursor), install
|
|
6
|
+
// @agentvalet/mcp-server instead and call use_platform. This package is for
|
|
7
|
+
// agents that aren't MCP: LangChain tools, cron jobs, plain Node services.
|
|
8
|
+
export { AgentValet } from "./client.js";
|
|
9
|
+
export { AgentValetError, AccessDeniedError, ApprovalDeniedError, ApprovalExpiredError, ApprovalTimeoutError, ConfigError, NetworkError, ProxyError, UpstreamError, } from "./errors.js";
|
|
10
|
+
export { DEFAULT_PROXY_URL } from "./env.js";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,EAAE;AACF,oEAAoE;AACpE,EAAE;AACF,8EAA8E;AAC9E,4EAA4E;AAC5E,2EAA2E;AAE3E,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,WAAW,EACX,YAAY,EACZ,UAAU,EACV,aAAa,GACd,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentvalet/client",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AgentValet client SDK — call approved SaaS platforms from any Node agent. Signs the agent JWT, brokers through the AgentValet proxy, and waits out owner approvals.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"jose": "^5.10.0"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^20.0.0",
|
|
20
|
+
"typescript": "^5.4.0",
|
|
21
|
+
"vitest": "^1.5.0"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/MCSEdwin/agentvalet.git",
|
|
29
|
+
"directory": "packages/client"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"ai",
|
|
33
|
+
"agents",
|
|
34
|
+
"agentvalet",
|
|
35
|
+
"credentials",
|
|
36
|
+
"authorization",
|
|
37
|
+
"sdk"
|
|
38
|
+
],
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc",
|
|
42
|
+
"dev": "tsc --watch",
|
|
43
|
+
"typecheck": "tsc --noEmit",
|
|
44
|
+
"test": "vitest run"
|
|
45
|
+
}
|
|
46
|
+
}
|