@codespring-app/use-agent 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 +164 -0
- package/dist/chunk-FAD2XMPA.js +220 -0
- package/dist/client-Bz3eVQXx.d.ts +156 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +48 -0
- package/dist/react.d.ts +212 -0
- package/dist/react.js +1148 -0
- package/docs/screenshots/default-agent.png +0 -0
- package/package.json +65 -0
package/README.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# `@codespring-app/use-agent`
|
|
2
|
+
|
|
3
|
+
The supported server and React SDK for CodeSpring Agents. It speaks a versioned
|
|
4
|
+
HTTP protocol and contains no Cloudflare runtime implementation, so the same
|
|
5
|
+
application can target CodeSpring-hosted or self-hosted endpoints.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Server
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { createAgent, createClient } from "@codespring-app/use-agent";
|
|
13
|
+
|
|
14
|
+
const support = createAgent({
|
|
15
|
+
id: "support",
|
|
16
|
+
revision: "7",
|
|
17
|
+
instructions: "Help the customer clearly and safely.",
|
|
18
|
+
model: "production-default",
|
|
19
|
+
skills: [{ id: "returns", version: "1" }],
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const agents = createClient({
|
|
23
|
+
endpoint: process.env.CODESPRING_AGENTS_ENDPOINT!,
|
|
24
|
+
apiKey: process.env.CODESPRING_AGENTS_API_KEY!,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const session = await agents.sessions.create(support);
|
|
28
|
+
await session.submit("Where is my order?", { idempotencyKey: crypto.randomUUID() });
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`production-default` is a reusable, tenant-scoped virtual model profile—not a
|
|
32
|
+
provider model name and not an agent/use-case configuration. Multiple agents can
|
|
33
|
+
reference it. The control plane maps it to encrypted BYOK connections, provider
|
|
34
|
+
candidates, fallback, budgets, and policy. Publishing resolves the profile to an
|
|
35
|
+
immutable policy revision while credential rotation remains independent.
|
|
36
|
+
|
|
37
|
+
API keys are server-only. Do not pass the server client into a browser bundle.
|
|
38
|
+
|
|
39
|
+
## Plug-and-play React UI
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import {
|
|
43
|
+
AgentChat,
|
|
44
|
+
AgentProvider,
|
|
45
|
+
createAgentAppearance,
|
|
46
|
+
createAgentClient,
|
|
47
|
+
} from "@codespring-app/use-agent/react";
|
|
48
|
+
|
|
49
|
+
const agentClient = createAgentClient({
|
|
50
|
+
endpoint: "https://api.agents.codespring.app/browser",
|
|
51
|
+
clientTokenEndpoint: "/api/agents/token",
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const acmeAppearance = createAgentAppearance({
|
|
55
|
+
theme: { accent: "#2856D8" },
|
|
56
|
+
copy: { placeholder: "Ask us anything" },
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export function App({ sessionId }: { sessionId: string }) {
|
|
60
|
+
return (
|
|
61
|
+
<AgentProvider client={agentClient} appearance={acmeAppearance}>
|
|
62
|
+
<AgentChat sessionId={sessionId} />
|
|
63
|
+
</AgentProvider>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`/api/agents/token` returns `{ token, expiresAt }`. The SDK caches it in memory,
|
|
69
|
+
deduplicates concurrent refreshes, refreshes before expiry, and retries once
|
|
70
|
+
after a 401. It never persists the token. `createAgentAppearance` produces a
|
|
71
|
+
frozen, reusable preset so unrelated renders do not invalidate theme/copy
|
|
72
|
+
consumers; use `useMemo` when appearance must be dynamic.
|
|
73
|
+
|
|
74
|
+
The `/browser` endpoint is intentional: it accepts only short-lived client
|
|
75
|
+
tokens and is the only runtime surface with browser CORS. Server API keys stay
|
|
76
|
+
on the endpoint root and must never be shipped to a browser.
|
|
77
|
+
|
|
78
|
+
The default Paper experience renders assistant replies as document content on
|
|
79
|
+
an edge-to-edge canvas, user messages as quiet trailing wells, tool calls as
|
|
80
|
+
compact inspectable activity rows, and the live-edge composer without a shadow.
|
|
81
|
+
`paperLightTheme`, `paperDarkTheme`, theme/copy overrides, slots, and render
|
|
82
|
+
functions are available for customization.
|
|
83
|
+
|
|
84
|
+
## CSS variables, Tailwind CSS, and StyleX
|
|
85
|
+
|
|
86
|
+
Every default component resolves theme tokens through inherited
|
|
87
|
+
`--codespring-agent-*` custom properties. Variables override the appearance
|
|
88
|
+
preset; unset variables use the selected Paper or custom appearance value as a
|
|
89
|
+
fallback.
|
|
90
|
+
|
|
91
|
+
```css
|
|
92
|
+
.acme-agent-theme {
|
|
93
|
+
--codespring-agent-accent: #2856d8;
|
|
94
|
+
--codespring-agent-container-radius: 18px;
|
|
95
|
+
--codespring-agent-content-max-width: 52rem;
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The public names are also exported as `agentThemeVariables`. Supported tokens
|
|
100
|
+
are `canvas`, `ink`, `inkSecondary`, `inkTertiary`, `well`, `hairline`,
|
|
101
|
+
`statusGood`, `statusBad`, `statusWarn`, `accent`, `fontFamily`, `monoFamily`,
|
|
102
|
+
`contentMaxWidth`, `containerRadius`, and `wellRadius`.
|
|
103
|
+
|
|
104
|
+
Tailwind CSS can set the variables on any ancestor:
|
|
105
|
+
|
|
106
|
+
```css
|
|
107
|
+
@theme {
|
|
108
|
+
--color-acme-primary: #2856d8;
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
<div className="[--codespring-agent-accent:var(--color-acme-primary)] [--codespring-agent-container-radius:18px]">
|
|
114
|
+
<AgentProvider client={agentClient} appearance={acmeAppearance}>
|
|
115
|
+
<AgentChat sessionId={sessionId} />
|
|
116
|
+
</AgentProvider>
|
|
117
|
+
</div>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
StyleX variables can be used as appearance values and themed from an ancestor:
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
// agent-theme.stylex.ts
|
|
124
|
+
import * as stylex from "@stylexjs/stylex";
|
|
125
|
+
|
|
126
|
+
export const agentTokens = stylex.defineVars({ accent: "#3B6AC5" });
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
import * as stylex from "@stylexjs/stylex";
|
|
131
|
+
import { agentTokens } from "./agent-theme.stylex";
|
|
132
|
+
|
|
133
|
+
const brandedTheme = stylex.createTheme(agentTokens, { accent: "#2856D8" });
|
|
134
|
+
const stylexAppearance = createAgentAppearance({
|
|
135
|
+
theme: { accent: agentTokens.accent },
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
<div {...stylex.props(brandedTheme)}>
|
|
139
|
+
<AgentProvider client={agentClient} appearance={stylexAppearance}>
|
|
140
|
+
<AgentChat sessionId={sessionId} />
|
|
141
|
+
</AgentProvider>
|
|
142
|
+
</div>;
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Headless React
|
|
146
|
+
|
|
147
|
+
Advanced clients can use `useAgentSession`, `useAgentMessages`,
|
|
148
|
+
`useAgentToolCalls`, `useAgentClient`, `useAgentTheme`, and `useAgentCopy` to
|
|
149
|
+
build a completely custom interface. The composable `AgentMessageList`,
|
|
150
|
+
`AgentMessage`, `AgentToolCall`, and `AgentComposer` primitives can also be
|
|
151
|
+
mixed with client-owned components.
|
|
152
|
+
|
|
153
|
+
The browser entrypoint never accepts an API key. A trusted application backend
|
|
154
|
+
must issue short-lived, origin-bound client tokens.
|
|
155
|
+
|
|
156
|
+
## Local showcase
|
|
157
|
+
|
|
158
|
+
```sh
|
|
159
|
+
bun run showcase
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Open `http://127.0.0.1:5173` for the Paper UI or append `?theme=dark` for
|
|
163
|
+
the dark palette. The showcase uses mocked durable events and makes no
|
|
164
|
+
external API calls.
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
var AgentError = class extends Error {
|
|
3
|
+
constructor(message, status, code, requestId, details) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.status = status;
|
|
6
|
+
this.code = code;
|
|
7
|
+
this.requestId = requestId;
|
|
8
|
+
this.details = details;
|
|
9
|
+
this.name = "AgentError";
|
|
10
|
+
}
|
|
11
|
+
status;
|
|
12
|
+
code;
|
|
13
|
+
requestId;
|
|
14
|
+
details;
|
|
15
|
+
};
|
|
16
|
+
var Transport = class {
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.options = options;
|
|
19
|
+
this.endpoint = normalizeEndpoint(options.endpoint);
|
|
20
|
+
this.fetchImplementation = options.fetch ?? globalThis.fetch;
|
|
21
|
+
if (!this.fetchImplementation) throw new TypeError("A fetch implementation is required");
|
|
22
|
+
}
|
|
23
|
+
options;
|
|
24
|
+
endpoint;
|
|
25
|
+
fetchImplementation;
|
|
26
|
+
async request(path, init = {}) {
|
|
27
|
+
let response = await this.fetchWithToken(path, init);
|
|
28
|
+
if (response.status === 401 && this.options.token.invalidate()) {
|
|
29
|
+
response = await this.fetchWithToken(path, init);
|
|
30
|
+
}
|
|
31
|
+
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
32
|
+
const payload = await readJson(response);
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
const error = isObject(payload) && isObject(payload.error) ? payload.error : void 0;
|
|
35
|
+
throw new AgentError(
|
|
36
|
+
typeof error?.message === "string" ? error.message : `Use Agent request failed with ${response.status}`,
|
|
37
|
+
response.status,
|
|
38
|
+
typeof error?.code === "string" ? error.code : "request_failed",
|
|
39
|
+
requestId,
|
|
40
|
+
error?.details
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return payload;
|
|
44
|
+
}
|
|
45
|
+
async fetchWithToken(path, init) {
|
|
46
|
+
const headers = new Headers(init.headers);
|
|
47
|
+
headers.set("Accept", "application/json");
|
|
48
|
+
headers.set("Authorization", `Bearer ${await this.options.token.get()}`);
|
|
49
|
+
if (init.body !== void 0) headers.set("Content-Type", "application/json");
|
|
50
|
+
return this.fetchImplementation(`${this.endpoint}${path}`, { ...init, headers });
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
function jwtExpiry(token) {
|
|
54
|
+
const encoded = token.split(".")[1];
|
|
55
|
+
if (!encoded || typeof globalThis.atob !== "function") return void 0;
|
|
56
|
+
try {
|
|
57
|
+
const normalized = encoded.replace(/-/gu, "+").replace(/_/gu, "/");
|
|
58
|
+
const payload = JSON.parse(globalThis.atob(normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=")));
|
|
59
|
+
return typeof payload.exp === "number" ? payload.exp * 1e3 : void 0;
|
|
60
|
+
} catch {
|
|
61
|
+
return void 0;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function explicitExpiry(value) {
|
|
65
|
+
if (typeof value === "number") return value < 1e12 ? value * 1e3 : value;
|
|
66
|
+
if (typeof value !== "string") return void 0;
|
|
67
|
+
const parsed = Date.parse(value);
|
|
68
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
69
|
+
}
|
|
70
|
+
var CachedTokenProvider = class {
|
|
71
|
+
constructor(load, fallbackTtlMs, refreshSkewMs) {
|
|
72
|
+
this.load = load;
|
|
73
|
+
this.fallbackTtlMs = fallbackTtlMs;
|
|
74
|
+
this.refreshSkewMs = refreshSkewMs;
|
|
75
|
+
}
|
|
76
|
+
load;
|
|
77
|
+
fallbackTtlMs;
|
|
78
|
+
refreshSkewMs;
|
|
79
|
+
cached;
|
|
80
|
+
inFlight;
|
|
81
|
+
get = async () => {
|
|
82
|
+
if (this.cached && Date.now() < this.cached.refreshAt) return this.cached.token;
|
|
83
|
+
if (this.inFlight) return this.inFlight;
|
|
84
|
+
this.inFlight = this.refresh();
|
|
85
|
+
try {
|
|
86
|
+
return await this.inFlight;
|
|
87
|
+
} finally {
|
|
88
|
+
this.inFlight = void 0;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
invalidate = () => {
|
|
92
|
+
this.cached = void 0;
|
|
93
|
+
return true;
|
|
94
|
+
};
|
|
95
|
+
async refresh() {
|
|
96
|
+
const loaded = await this.load();
|
|
97
|
+
const token = typeof loaded === "string" ? loaded : loaded.token;
|
|
98
|
+
if (!token.trim()) throw new TypeError("getClientToken returned an empty token");
|
|
99
|
+
const now = Date.now();
|
|
100
|
+
const expiry = (typeof loaded === "string" ? void 0 : explicitExpiry(loaded.expiresAt)) ?? jwtExpiry(token) ?? now + this.fallbackTtlMs;
|
|
101
|
+
const lifetime = Math.max(1e3, expiry - now);
|
|
102
|
+
this.cached = {
|
|
103
|
+
token,
|
|
104
|
+
refreshAt: expiry - Math.min(this.refreshSkewMs, Math.max(500, lifetime / 2))
|
|
105
|
+
};
|
|
106
|
+
return token;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
var staticTokenProvider = (token) => ({
|
|
110
|
+
get: async () => token,
|
|
111
|
+
invalidate: () => false
|
|
112
|
+
});
|
|
113
|
+
var isObject = (value) => value !== null && typeof value === "object";
|
|
114
|
+
async function readJson(response) {
|
|
115
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
116
|
+
if (!contentType.includes("application/json")) {
|
|
117
|
+
if (!response.ok) return void 0;
|
|
118
|
+
throw new AgentError("Runtime returned a non-JSON response", response.status, "invalid_response");
|
|
119
|
+
}
|
|
120
|
+
return response.json();
|
|
121
|
+
}
|
|
122
|
+
function normalizeEndpoint(endpoint) {
|
|
123
|
+
const parsed = new URL(endpoint);
|
|
124
|
+
if (parsed.protocol !== "https:" && parsed.hostname !== "localhost" && parsed.hostname !== "127.0.0.1") {
|
|
125
|
+
throw new TypeError("endpoint must use HTTPS outside local development");
|
|
126
|
+
}
|
|
127
|
+
parsed.pathname = parsed.pathname.replace(/\/$/u, "");
|
|
128
|
+
parsed.search = "";
|
|
129
|
+
parsed.hash = "";
|
|
130
|
+
return parsed.toString().replace(/\/$/u, "");
|
|
131
|
+
}
|
|
132
|
+
var randomIdempotencyKey = () => {
|
|
133
|
+
if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID();
|
|
134
|
+
throw new Error("crypto.randomUUID is required when no idempotency key is supplied");
|
|
135
|
+
};
|
|
136
|
+
var AgentSession = class {
|
|
137
|
+
constructor(transport, id) {
|
|
138
|
+
this.transport = transport;
|
|
139
|
+
this.id = id;
|
|
140
|
+
}
|
|
141
|
+
transport;
|
|
142
|
+
id;
|
|
143
|
+
get(options = {}) {
|
|
144
|
+
return this.transport.request(`/v1/sessions/${encodeURIComponent(this.id)}`, {
|
|
145
|
+
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
submit(content, options = {}) {
|
|
149
|
+
const idempotencyKey = options.idempotencyKey ?? randomIdempotencyKey();
|
|
150
|
+
return this.transport.request(`/v1/sessions/${encodeURIComponent(this.id)}/turns`, {
|
|
151
|
+
method: "POST",
|
|
152
|
+
headers: { "Idempotency-Key": idempotencyKey },
|
|
153
|
+
body: JSON.stringify({ content }),
|
|
154
|
+
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
events(after = 0, limit = 100, options = {}) {
|
|
158
|
+
const query = new URLSearchParams({ after: String(after), limit: String(limit) });
|
|
159
|
+
return this.transport.request(`/v1/sessions/${encodeURIComponent(this.id)}/events?${query}`, {
|
|
160
|
+
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
async cancel(turnId, options = {}) {
|
|
164
|
+
return this.transport.request(
|
|
165
|
+
`/v1/sessions/${encodeURIComponent(this.id)}/turns/${encodeURIComponent(turnId)}/cancel`,
|
|
166
|
+
{
|
|
167
|
+
method: "POST",
|
|
168
|
+
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
169
|
+
}
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
var AgentClient = class {
|
|
174
|
+
constructor(transport) {
|
|
175
|
+
this.transport = transport;
|
|
176
|
+
}
|
|
177
|
+
transport;
|
|
178
|
+
sessions = {
|
|
179
|
+
create: async (agent, options = {}) => {
|
|
180
|
+
const created = await this.transport.request("/v1/sessions", {
|
|
181
|
+
method: "POST",
|
|
182
|
+
body: JSON.stringify({ agentRevisionId: agent.revisionId }),
|
|
183
|
+
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
184
|
+
});
|
|
185
|
+
return new AgentSession(this.transport, created.sessionId);
|
|
186
|
+
},
|
|
187
|
+
get: (sessionId) => new AgentSession(this.transport, sessionId)
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
function createClient(options) {
|
|
191
|
+
if (!options.apiKey.trim()) throw new TypeError("apiKey is required");
|
|
192
|
+
return new AgentClient(
|
|
193
|
+
new Transport({
|
|
194
|
+
endpoint: options.endpoint,
|
|
195
|
+
token: staticTokenProvider(options.apiKey),
|
|
196
|
+
...options.fetch === void 0 ? {} : { fetch: options.fetch }
|
|
197
|
+
})
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
function createBrowserClient(options) {
|
|
201
|
+
return new AgentClient(
|
|
202
|
+
new Transport({
|
|
203
|
+
endpoint: options.endpoint,
|
|
204
|
+
token: new CachedTokenProvider(
|
|
205
|
+
options.getClientToken,
|
|
206
|
+
options.clientTokenTtlMs ?? 6e4,
|
|
207
|
+
options.refreshSkewMs ?? 3e4
|
|
208
|
+
),
|
|
209
|
+
...options.fetch === void 0 ? {} : { fetch: options.fetch }
|
|
210
|
+
})
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export {
|
|
215
|
+
AgentError,
|
|
216
|
+
AgentSession,
|
|
217
|
+
AgentClient,
|
|
218
|
+
createClient,
|
|
219
|
+
createBrowserClient
|
|
220
|
+
};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
type TurnStatus = "queued" | "running" | "completed" | "failed" | "cancelled";
|
|
2
|
+
interface AgentEvent {
|
|
3
|
+
schemaVersion: 1;
|
|
4
|
+
id: number;
|
|
5
|
+
sessionId: string;
|
|
6
|
+
turnId?: string;
|
|
7
|
+
attempt: number;
|
|
8
|
+
type: string;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
data: unknown;
|
|
11
|
+
}
|
|
12
|
+
interface SessionSnapshot {
|
|
13
|
+
sessionId: string;
|
|
14
|
+
agentRevisionId: string;
|
|
15
|
+
createdAt: string;
|
|
16
|
+
updatedAt: string;
|
|
17
|
+
cursor: number;
|
|
18
|
+
turns: Array<{
|
|
19
|
+
id: string;
|
|
20
|
+
status: TurnStatus;
|
|
21
|
+
attempt: number;
|
|
22
|
+
createdAt: string;
|
|
23
|
+
updatedAt: string;
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
interface CreateSessionResponse {
|
|
27
|
+
sessionId: string;
|
|
28
|
+
agentRevisionId: string;
|
|
29
|
+
createdAt: string;
|
|
30
|
+
}
|
|
31
|
+
interface SubmitTurnResponse {
|
|
32
|
+
sessionId: string;
|
|
33
|
+
turnId: string;
|
|
34
|
+
status: TurnStatus;
|
|
35
|
+
cursor: number;
|
|
36
|
+
duplicate: boolean;
|
|
37
|
+
}
|
|
38
|
+
interface ListEventsResponse {
|
|
39
|
+
events: AgentEvent[];
|
|
40
|
+
cursor: number;
|
|
41
|
+
hasMore: boolean;
|
|
42
|
+
}
|
|
43
|
+
/** Tenant-scoped model profile configured in the CodeSpring control plane. */
|
|
44
|
+
type ModelProfileId = string;
|
|
45
|
+
interface AgentToolReference {
|
|
46
|
+
name: string;
|
|
47
|
+
description?: string;
|
|
48
|
+
}
|
|
49
|
+
interface AgentMcpServerReference {
|
|
50
|
+
id: string;
|
|
51
|
+
allowedTools?: string[];
|
|
52
|
+
}
|
|
53
|
+
interface AgentSkillReference {
|
|
54
|
+
id: string;
|
|
55
|
+
version?: string;
|
|
56
|
+
}
|
|
57
|
+
interface AgentDefinition {
|
|
58
|
+
readonly id: string;
|
|
59
|
+
readonly revision: string;
|
|
60
|
+
readonly revisionId: string;
|
|
61
|
+
readonly instructions?: string;
|
|
62
|
+
readonly model?: ModelProfileId;
|
|
63
|
+
readonly tools: readonly AgentToolReference[];
|
|
64
|
+
readonly mcpServers: readonly AgentMcpServerReference[];
|
|
65
|
+
readonly skills: readonly AgentSkillReference[];
|
|
66
|
+
readonly metadata: Readonly<Record<string, string>>;
|
|
67
|
+
}
|
|
68
|
+
interface CreateAgentOptions {
|
|
69
|
+
id: string;
|
|
70
|
+
revision: string;
|
|
71
|
+
instructions?: string;
|
|
72
|
+
model?: ModelProfileId;
|
|
73
|
+
tools?: AgentToolReference[];
|
|
74
|
+
mcpServers?: AgentMcpServerReference[];
|
|
75
|
+
skills?: AgentSkillReference[];
|
|
76
|
+
metadata?: Record<string, string>;
|
|
77
|
+
}
|
|
78
|
+
interface RequestOptions {
|
|
79
|
+
signal?: AbortSignal;
|
|
80
|
+
}
|
|
81
|
+
interface SubmitOptions extends RequestOptions {
|
|
82
|
+
idempotencyKey?: string;
|
|
83
|
+
}
|
|
84
|
+
type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
85
|
+
interface AgentClientOptions {
|
|
86
|
+
endpoint: string;
|
|
87
|
+
apiKey: string;
|
|
88
|
+
fetch?: FetchLike;
|
|
89
|
+
}
|
|
90
|
+
interface BrowserAgentClientOptions {
|
|
91
|
+
endpoint: string;
|
|
92
|
+
getClientToken: () => Promise<ClientTokenResult>;
|
|
93
|
+
/** Fallback lifetime for opaque legacy tokens without an expiry. Defaults to 60 seconds. */
|
|
94
|
+
clientTokenTtlMs?: number;
|
|
95
|
+
/** Refresh before expiry. Defaults to 30 seconds and is bounded for short tokens. */
|
|
96
|
+
refreshSkewMs?: number;
|
|
97
|
+
fetch?: FetchLike;
|
|
98
|
+
}
|
|
99
|
+
type ClientTokenResult = string | {
|
|
100
|
+
token: string;
|
|
101
|
+
/** ISO timestamp or Unix time in seconds/milliseconds. */
|
|
102
|
+
expiresAt?: string | number;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
declare class AgentError extends Error {
|
|
106
|
+
readonly status: number;
|
|
107
|
+
readonly code: string;
|
|
108
|
+
readonly requestId?: string | undefined;
|
|
109
|
+
readonly details?: unknown | undefined;
|
|
110
|
+
constructor(message: string, status: number, code: string, requestId?: string | undefined, details?: unknown | undefined);
|
|
111
|
+
}
|
|
112
|
+
interface TokenProvider {
|
|
113
|
+
get: () => Promise<string>;
|
|
114
|
+
invalidate: () => boolean;
|
|
115
|
+
}
|
|
116
|
+
interface TransportOptions {
|
|
117
|
+
endpoint: string;
|
|
118
|
+
token: TokenProvider;
|
|
119
|
+
fetch?: FetchLike;
|
|
120
|
+
}
|
|
121
|
+
declare class Transport {
|
|
122
|
+
private readonly options;
|
|
123
|
+
readonly endpoint: string;
|
|
124
|
+
readonly fetchImplementation: FetchLike;
|
|
125
|
+
constructor(options: TransportOptions);
|
|
126
|
+
request<T>(path: string, init?: RequestInit): Promise<T>;
|
|
127
|
+
private fetchWithToken;
|
|
128
|
+
}
|
|
129
|
+
declare class AgentSession {
|
|
130
|
+
private readonly transport;
|
|
131
|
+
readonly id: string;
|
|
132
|
+
constructor(transport: Transport, id: string);
|
|
133
|
+
get(options?: RequestOptions): Promise<SessionSnapshot>;
|
|
134
|
+
submit(content: string, options?: SubmitOptions): Promise<SubmitTurnResponse>;
|
|
135
|
+
events(after?: number, limit?: number, options?: RequestOptions): Promise<ListEventsResponse>;
|
|
136
|
+
cancel(turnId: string, options?: RequestOptions): Promise<TurnStatusResponse>;
|
|
137
|
+
}
|
|
138
|
+
interface TurnStatusResponse {
|
|
139
|
+
sessionId: string;
|
|
140
|
+
turnId: string;
|
|
141
|
+
status: string;
|
|
142
|
+
}
|
|
143
|
+
declare class AgentClient {
|
|
144
|
+
private readonly transport;
|
|
145
|
+
constructor(transport: Transport);
|
|
146
|
+
readonly sessions: {
|
|
147
|
+
create: (agent: AgentDefinition, options?: RequestOptions) => Promise<AgentSession>;
|
|
148
|
+
get: (sessionId: string) => AgentSession;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/** Server entrypoint. Never pass this client or its API key into a browser bundle. */
|
|
152
|
+
declare function createClient(options: AgentClientOptions): AgentClient;
|
|
153
|
+
/** Browser-safe client used by the React subpath with short-lived client tokens. */
|
|
154
|
+
declare function createBrowserClient(options: BrowserAgentClientOptions): AgentClient;
|
|
155
|
+
|
|
156
|
+
export { type AgentDefinition as A, type BrowserAgentClientOptions as B, type CreateAgentOptions as C, type FetchLike as F, type ListEventsResponse as L, type ModelProfileId as M, type RequestOptions as R, type SessionSnapshot as S, type TurnStatus as T, AgentClient as a, type AgentClientOptions as b, AgentError as c, type AgentEvent as d, type AgentMcpServerReference as e, AgentSession as f, type AgentSkillReference as g, type AgentToolReference as h, type ClientTokenResult as i, type CreateSessionResponse as j, type SubmitOptions as k, type SubmitTurnResponse as l, createBrowserClient as m, createClient as n };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { C as CreateAgentOptions, A as AgentDefinition } from './client-Bz3eVQXx.js';
|
|
2
|
+
export { a as AgentClient, b as AgentClientOptions, c as AgentError, d as AgentEvent, e as AgentMcpServerReference, f as AgentSession, g as AgentSkillReference, h as AgentToolReference, B as BrowserAgentClientOptions, i as ClientTokenResult, j as CreateSessionResponse, F as FetchLike, L as ListEventsResponse, M as ModelProfileId, R as RequestOptions, S as SessionSnapshot, k as SubmitOptions, l as SubmitTurnResponse, T as TurnStatus, m as createBrowserClient, n as createClient } from './client-Bz3eVQXx.js';
|
|
3
|
+
|
|
4
|
+
/** Defines a portable agent revision without importing runtime implementation code. */
|
|
5
|
+
declare function createAgent(options: CreateAgentOptions): AgentDefinition;
|
|
6
|
+
|
|
7
|
+
export { AgentDefinition, CreateAgentOptions, createAgent };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentClient,
|
|
3
|
+
AgentError,
|
|
4
|
+
AgentSession,
|
|
5
|
+
createBrowserClient,
|
|
6
|
+
createClient
|
|
7
|
+
} from "./chunk-FAD2XMPA.js";
|
|
8
|
+
|
|
9
|
+
// src/agent.ts
|
|
10
|
+
var identifierPattern = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/u;
|
|
11
|
+
function requireIdentifier(value, name) {
|
|
12
|
+
const normalized = value.trim();
|
|
13
|
+
if (!identifierPattern.test(normalized)) {
|
|
14
|
+
throw new TypeError(`${name} must match ${identifierPattern.source}`);
|
|
15
|
+
}
|
|
16
|
+
return normalized;
|
|
17
|
+
}
|
|
18
|
+
function uniqueNames(values, name) {
|
|
19
|
+
const normalized = values.map((value) => value.name.trim());
|
|
20
|
+
if (new Set(normalized).size !== normalized.length) {
|
|
21
|
+
throw new TypeError(`${name} names must be unique`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function createAgent(options) {
|
|
25
|
+
const id = requireIdentifier(options.id, "id");
|
|
26
|
+
const revision = requireIdentifier(options.revision, "revision");
|
|
27
|
+
const tools = (options.tools ?? []).map((tool) => ({ ...tool, name: tool.name.trim() }));
|
|
28
|
+
uniqueNames(tools, "tool");
|
|
29
|
+
return Object.freeze({
|
|
30
|
+
id,
|
|
31
|
+
revision,
|
|
32
|
+
revisionId: `${id}@${revision}`,
|
|
33
|
+
...options.instructions === void 0 ? {} : { instructions: options.instructions },
|
|
34
|
+
...options.model === void 0 ? {} : { model: requireIdentifier(options.model, "model") },
|
|
35
|
+
tools: Object.freeze(tools.map((tool) => Object.freeze(tool))),
|
|
36
|
+
mcpServers: Object.freeze((options.mcpServers ?? []).map((server) => Object.freeze({ ...server }))),
|
|
37
|
+
skills: Object.freeze((options.skills ?? []).map((skill) => Object.freeze({ ...skill }))),
|
|
38
|
+
metadata: Object.freeze({ ...options.metadata ?? {} })
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
AgentClient,
|
|
43
|
+
AgentError,
|
|
44
|
+
AgentSession,
|
|
45
|
+
createAgent,
|
|
46
|
+
createBrowserClient,
|
|
47
|
+
createClient
|
|
48
|
+
};
|