@personaai/runtime 0.5.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 +411 -0
- package/dist/index.cjs +1439 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +247 -0
- package/dist/index.d.ts +247 -0
- package/dist/index.js +1410 -0
- package/dist/index.js.map +1 -0
- package/package.json +71 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { ChatMessageInput } from '@personaai/sdk';
|
|
2
|
+
|
|
3
|
+
type RuntimeMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
4
|
+
/** A single uploaded file — present on `RuntimeRequest.file` for a multipart `POST /files`. */
|
|
5
|
+
interface RuntimeUploadedFile {
|
|
6
|
+
filename: string;
|
|
7
|
+
content: Uint8Array;
|
|
8
|
+
contentType?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Framework-neutral inbound request. A framework adapter (Express, Node
|
|
12
|
+
* `http`, ...) translates its own request object into this shape and calls
|
|
13
|
+
* `Runtime.handle()` — the runtime never imports a framework.
|
|
14
|
+
*/
|
|
15
|
+
interface RuntimeRequest {
|
|
16
|
+
method: RuntimeMethod;
|
|
17
|
+
/** Pathname only (no query string). May still include the `mountPath` prefix — the runtime strips it. */
|
|
18
|
+
path: string;
|
|
19
|
+
/** Header names as the adapter received them (Node's `http` already lowercases these). */
|
|
20
|
+
headers: Record<string, string | undefined>;
|
|
21
|
+
query: Record<string, string | undefined>;
|
|
22
|
+
/**
|
|
23
|
+
* Already-parsed JSON body, or `undefined` for bodyless requests. For a
|
|
24
|
+
* multipart request (`POST /files`, `POST /knowledge/:id/documents`), this
|
|
25
|
+
* holds the non-file form fields (e.g. `{ agentId, threadId }`) — the
|
|
26
|
+
* file(s) themselves are on `file`/`files`, not here. Parsing raw bytes is
|
|
27
|
+
* the adapter's job either way.
|
|
28
|
+
*/
|
|
29
|
+
body: unknown;
|
|
30
|
+
/** The uploaded file, for a multipart `POST /files` request (single-file upload) only. */
|
|
31
|
+
file?: RuntimeUploadedFile;
|
|
32
|
+
/** The uploaded files, for a multipart `POST /knowledge/:id/documents` request (multi-file upload) only. */
|
|
33
|
+
files?: RuntimeUploadedFile[];
|
|
34
|
+
/**
|
|
35
|
+
* The resolved external user id. Always `null` on the request the host
|
|
36
|
+
* constructs — the runtime fills this in via `resolveUser` before an
|
|
37
|
+
* auth-required route handler sees it.
|
|
38
|
+
*/
|
|
39
|
+
userId: string | null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** A complete response with a known-length body — every route except streaming chat. */
|
|
43
|
+
interface RuntimeBufferedResponse {
|
|
44
|
+
kind: 'buffered';
|
|
45
|
+
status: number;
|
|
46
|
+
headers: Record<string, string>;
|
|
47
|
+
/** Pre-serialized (e.g. already `JSON.stringify`-ed) — adapters never need to know content-type semantics. */
|
|
48
|
+
body: string;
|
|
49
|
+
}
|
|
50
|
+
/** An open-ended SSE response — the chat route only. */
|
|
51
|
+
interface RuntimeStreamResponse {
|
|
52
|
+
kind: 'stream';
|
|
53
|
+
status: number;
|
|
54
|
+
headers: Record<string, string>;
|
|
55
|
+
/** Already-formatted SSE frame text chunks (`"data: ...\n\n"`); adapters just write them through as they arrive. */
|
|
56
|
+
body: AsyncIterable<string>;
|
|
57
|
+
}
|
|
58
|
+
/** Raw bytes with a known (or unknown, chunked) length — file downloads only. */
|
|
59
|
+
interface RuntimeBinaryResponse {
|
|
60
|
+
kind: 'binary';
|
|
61
|
+
status: number;
|
|
62
|
+
headers: Record<string, string>;
|
|
63
|
+
body: AsyncIterable<Uint8Array>;
|
|
64
|
+
}
|
|
65
|
+
type RuntimeResponse = RuntimeBufferedResponse | RuntimeStreamResponse | RuntimeBinaryResponse;
|
|
66
|
+
|
|
67
|
+
interface RunContext {
|
|
68
|
+
userId: string;
|
|
69
|
+
/** Which endpoint started this run. */
|
|
70
|
+
kind: 'chat' | 'architect';
|
|
71
|
+
/** Absent for `kind: 'architect'` — the Architect co-pilot has no target agentId, it builds/edits Agents itself. */
|
|
72
|
+
agentId?: string;
|
|
73
|
+
threadId?: string;
|
|
74
|
+
messages: ChatMessageInput[];
|
|
75
|
+
}
|
|
76
|
+
interface RunResult {
|
|
77
|
+
/** Assembled assistant text (concatenated TEXT_MESSAGE_CHUNK deltas), same as `ChatResult.text`. */
|
|
78
|
+
text: string;
|
|
79
|
+
eventCount: number;
|
|
80
|
+
/** True when the run paused on a HITL/clarification interrupt instead of finishing normally. */
|
|
81
|
+
interrupted: boolean;
|
|
82
|
+
/** True when a RUN_ERROR event was seen — the run still completed (as far as the stream is concerned); see README on the `onError` vs `erroredInBand` distinction. */
|
|
83
|
+
erroredInBand: boolean;
|
|
84
|
+
}
|
|
85
|
+
interface ErrorContext {
|
|
86
|
+
userId: string | null;
|
|
87
|
+
/** Which stage of request handling the error came from. */
|
|
88
|
+
phase: 'auth' | 'chat' | 'architect';
|
|
89
|
+
agentId?: string;
|
|
90
|
+
threadId?: string;
|
|
91
|
+
}
|
|
92
|
+
interface ToolCallContext {
|
|
93
|
+
userId: string;
|
|
94
|
+
/** Absent for a tool call inside an Architect run. */
|
|
95
|
+
agentId?: string;
|
|
96
|
+
threadId?: string;
|
|
97
|
+
toolName: string;
|
|
98
|
+
toolCallId: string;
|
|
99
|
+
}
|
|
100
|
+
interface FileUploadContext {
|
|
101
|
+
userId: string;
|
|
102
|
+
fileName: string;
|
|
103
|
+
mimeType?: string;
|
|
104
|
+
}
|
|
105
|
+
interface ThreadCreateContext {
|
|
106
|
+
userId: string;
|
|
107
|
+
agentId: string;
|
|
108
|
+
threadId: string;
|
|
109
|
+
}
|
|
110
|
+
interface MemoryWriteContext {
|
|
111
|
+
userId: string;
|
|
112
|
+
/** Set when the write was agent-scoped (`scope: 'agent'`); absent for a user-scoped write. */
|
|
113
|
+
agentId?: string;
|
|
114
|
+
path: string;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Lifecycle hooks — the host application's voice inside the runtime's
|
|
118
|
+
* request handling. Plain async event listeners, not middleware: the
|
|
119
|
+
* runtime proceeds with sensible defaults when a hook is omitted, and a
|
|
120
|
+
* hook that wants to reject a run simply throws (the throw is caught and
|
|
121
|
+
* routed through the same sanitized error path as any other failure).
|
|
122
|
+
*/
|
|
123
|
+
interface RuntimeHooks {
|
|
124
|
+
beforeRun?(ctx: RunContext): void | Promise<void>;
|
|
125
|
+
afterRun?(ctx: RunContext, result: RunResult): void | Promise<void>;
|
|
126
|
+
onError?(ctx: ErrorContext, error: unknown): void | Promise<void>;
|
|
127
|
+
/** Fires when a TOOL_CALL_START event arrives in the chat stream, before its result is known. */
|
|
128
|
+
beforeToolCall?(ctx: ToolCallContext): void | Promise<void>;
|
|
129
|
+
/** Fires when the matching TOOL_CALL_RESULT event arrives. `result` is the raw (string or JSON-parsed) tool output. */
|
|
130
|
+
afterToolCall?(ctx: ToolCallContext, result: unknown): void | Promise<void>;
|
|
131
|
+
/** Fires after a file finishes uploading via `POST /files`. */
|
|
132
|
+
onFileUpload?(ctx: FileUploadContext): void | Promise<void>;
|
|
133
|
+
/**
|
|
134
|
+
* Fires after a Thread is created — either explicitly via `POST /threads`,
|
|
135
|
+
* or implicitly by `POST /chat` when no `threadId` was supplied and the
|
|
136
|
+
* run's `RUN_STARTED` event reports one that didn't exist yet.
|
|
137
|
+
*/
|
|
138
|
+
onThreadCreate?(ctx: ThreadCreateContext): void | Promise<void>;
|
|
139
|
+
/** Fires after a memory file is written via `PUT /memory/file`. */
|
|
140
|
+
onMemoryWrite?(ctx: MemoryWriteContext): void | Promise<void>;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The single point of contact between the host's auth world and the
|
|
145
|
+
* runtime's world. Receives the inbound request (with `userId: null`) and
|
|
146
|
+
* returns the resolved external user id, or `null`/a thrown error if the
|
|
147
|
+
* request isn't authenticated — either way the runtime responds 401.
|
|
148
|
+
* Persona never authenticates users; this function is entirely the host's.
|
|
149
|
+
*/
|
|
150
|
+
type ResolveUser = (request: RuntimeRequest) => string | null | Promise<string | null>;
|
|
151
|
+
/**
|
|
152
|
+
* Every one of these is `false` unless explicitly enabled — always-off by
|
|
153
|
+
* default so upgrading this package never silently exposes new surface to
|
|
154
|
+
* whoever `resolveUser` accepts. These resources are Project-level
|
|
155
|
+
* configuration (LLM provider credentials, skill/knowledge-base/vector-store
|
|
156
|
+
* management, security audit logs, an agent-building co-pilot) rather than
|
|
157
|
+
* things an end user does in a chat session — most hosts should manage them
|
|
158
|
+
* via `@personaai/sdk` directly from their own admin surface and never turn
|
|
159
|
+
* these on. Turn one on only if you specifically want it reachable through
|
|
160
|
+
* whatever `resolveUser` gates (which may not be "any logged-in end user" —
|
|
161
|
+
* that's your call).
|
|
162
|
+
*/
|
|
163
|
+
interface RuntimeCapabilities {
|
|
164
|
+
/** Full Agent CRUD (create/get/update/delete/bulk-delete) beyond the always-on read-only `GET /agents` list. @default false */
|
|
165
|
+
agentsWrite?: boolean;
|
|
166
|
+
/** Full MCP server CRUD + testConnection/readResource/callTool, beyond the always-on `/mcps/:id/oauth/*` routes. @default false */
|
|
167
|
+
mcps?: boolean;
|
|
168
|
+
/** LLM provider configuration — **holds API keys**. @default false */
|
|
169
|
+
providers?: boolean;
|
|
170
|
+
/** Skill authoring. @default false */
|
|
171
|
+
skills?: boolean;
|
|
172
|
+
/** Knowledge base CRUD, document upload/search. @default false */
|
|
173
|
+
knowledge?: boolean;
|
|
174
|
+
/** Vector store CRUD and file read/write. @default false */
|
|
175
|
+
stores?: boolean;
|
|
176
|
+
/** Security/compliance audit log read access. @default false */
|
|
177
|
+
auditLogs?: boolean;
|
|
178
|
+
/** The Architect co-pilot — builds/edits Agents on the caller's behalf via tool calls. @default false */
|
|
179
|
+
architect?: boolean;
|
|
180
|
+
}
|
|
181
|
+
interface CreateRuntimeOptions {
|
|
182
|
+
/** Base URL of the Persona Developer Platform API, e.g. "https://api.persona.hasanraiyan.me". */
|
|
183
|
+
baseUrl: string;
|
|
184
|
+
/** Project credential, shaped "<keyId>.<secret>" — never expose this to a browser. */
|
|
185
|
+
credential: string;
|
|
186
|
+
resolveUser: ResolveUser;
|
|
187
|
+
hooks?: RuntimeHooks;
|
|
188
|
+
/** Prefix to strip from `request.path` before routing, e.g. '/api/persona'. @default '' (no stripping) */
|
|
189
|
+
mountPath?: string;
|
|
190
|
+
/**
|
|
191
|
+
* 'development' includes error detail (message/stack/upstream response)
|
|
192
|
+
* in error responses; 'production' hides it behind a generic message.
|
|
193
|
+
* @default 'production', unless `process.env.NODE_ENV === 'development'`.
|
|
194
|
+
*/
|
|
195
|
+
mode?: 'development' | 'production';
|
|
196
|
+
/** Override fetch (proxying, tracing, or test injection). Forwarded to every per-request PersonaClient. */
|
|
197
|
+
fetch?: typeof fetch;
|
|
198
|
+
/**
|
|
199
|
+
* How often to send an SSE comment-line heartbeat (`: heartbeat\n\n`)
|
|
200
|
+
* during a gap in the `/chat` stream — e.g. a long-running tool call with
|
|
201
|
+
* no token output — so intermediary proxies/load balancers with an idle
|
|
202
|
+
* timeout don't kill the connection. Comment lines are invisible to any
|
|
203
|
+
* `data:`-only SSE parser (including `@personaai/sdk`'s own), so this
|
|
204
|
+
* never changes the AG-UI event sequence a consumer sees.
|
|
205
|
+
* @default 15000
|
|
206
|
+
*/
|
|
207
|
+
heartbeatIntervalMs?: number;
|
|
208
|
+
/**
|
|
209
|
+
* How long a finished `/chat` run stays resumable via `GET /chat/:runId/resume`
|
|
210
|
+
* before an internal eviction sweep removes it.
|
|
211
|
+
* @default 300000 (5 minutes)
|
|
212
|
+
*/
|
|
213
|
+
runGraceMs?: number;
|
|
214
|
+
/**
|
|
215
|
+
* Safety valve on the in-memory resumable-run registry — once over this
|
|
216
|
+
* many tracked runs, the oldest-finished ones are evicted first (still
|
|
217
|
+
* in-flight runs are never evicted by this cap).
|
|
218
|
+
* @default 1000
|
|
219
|
+
*/
|
|
220
|
+
maxTrackedRuns?: number;
|
|
221
|
+
/** Opt-in switches for Project-level admin surface. See {@link RuntimeCapabilities} — everything defaults to off. */
|
|
222
|
+
capabilities?: RuntimeCapabilities;
|
|
223
|
+
}
|
|
224
|
+
interface Runtime {
|
|
225
|
+
handle(request: RuntimeRequest): Promise<RuntimeResponse>;
|
|
226
|
+
/**
|
|
227
|
+
* Stops the background eviction timer used for resumable-run bookkeeping.
|
|
228
|
+
* The timer is `unref`'d and won't itself keep a Node process alive, so
|
|
229
|
+
* calling this is optional — but do call it if you `createRuntime()`
|
|
230
|
+
* repeatedly in a long-lived process (e.g. per-test-suite setup) to avoid
|
|
231
|
+
* accumulating timers.
|
|
232
|
+
*/
|
|
233
|
+
close(): void;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
declare function createRuntime(options: CreateRuntimeOptions): Runtime;
|
|
237
|
+
|
|
238
|
+
/** A runtime-originated HTTP error (routing, validation, auth) — as opposed to one surfaced from the Persona API itself. */
|
|
239
|
+
declare class RuntimeHttpError extends Error {
|
|
240
|
+
readonly status: number;
|
|
241
|
+
readonly code: string;
|
|
242
|
+
constructor(status: number, code: string, message: string);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
declare const RUNTIME_VERSION = "0.5.0";
|
|
246
|
+
|
|
247
|
+
export { type CreateRuntimeOptions, type ErrorContext, type FileUploadContext, type MemoryWriteContext, RUNTIME_VERSION, type ResolveUser, type RunContext, type RunResult, type Runtime, type RuntimeBinaryResponse, type RuntimeBufferedResponse, type RuntimeCapabilities, type RuntimeHooks, RuntimeHttpError, type RuntimeMethod, type RuntimeRequest, type RuntimeResponse, type RuntimeStreamResponse, type RuntimeUploadedFile, type ThreadCreateContext, type ToolCallContext, createRuntime };
|