@personaai/runtime 0.7.0 → 0.8.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/dist/index.cjs +79 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -2
- package/dist/index.d.ts +34 -2
- package/dist/index.js +79 -52
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChatMessageInput, LogLevel, Logger } from '@personaai/sdk';
|
|
1
|
+
import { ChatMessageInput, CreateRestToolInput, LogLevel, Logger } from '@personaai/sdk';
|
|
2
2
|
|
|
3
3
|
type RuntimeMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
4
4
|
/** A single uploaded file — present on `RuntimeRequest.file` for a multipart `POST /files`. */
|
|
@@ -116,6 +116,8 @@ interface MemoryWriteContext {
|
|
|
116
116
|
interface VoiceSessionCreateContext {
|
|
117
117
|
userId: string;
|
|
118
118
|
agentId: string;
|
|
119
|
+
/** Set when the session resumed an existing conversation (optional `threadId` on the request). */
|
|
120
|
+
threadId?: string;
|
|
119
121
|
}
|
|
120
122
|
/**
|
|
121
123
|
* Lifecycle hooks — the host application's voice inside the runtime's
|
|
@@ -146,6 +148,13 @@ interface RuntimeHooks {
|
|
|
146
148
|
onVoiceSessionCreate?(ctx: VoiceSessionCreateContext): void | Promise<void>;
|
|
147
149
|
}
|
|
148
150
|
|
|
151
|
+
/**
|
|
152
|
+
* One REST tool definition served by the manifest route — identical to
|
|
153
|
+
* `CreateRestToolInput` from `@personaai/sdk@^0.7.0` (also `defineRestTool`'s
|
|
154
|
+
* return type from `@personaai/sdk/rest-tools`), aliased under this name for
|
|
155
|
+
* clarity at the call site (`createRuntime({ restToolsManifest: { tools } })`).
|
|
156
|
+
*/
|
|
157
|
+
type RestToolManifestEntry = CreateRestToolInput;
|
|
149
158
|
/**
|
|
150
159
|
* The single point of contact between the host's auth world and the
|
|
151
160
|
* runtime's world. Receives the inbound request (with `userId: null`) and
|
|
@@ -184,6 +193,27 @@ interface RuntimeCapabilities {
|
|
|
184
193
|
/** The Architect co-pilot — builds/edits Agents on the caller's behalf via tool calls. @default false */
|
|
185
194
|
architect?: boolean;
|
|
186
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Serves a list of code-defined REST tools (built with `defineRestTool`
|
|
198
|
+
* from `@personaai/sdk/rest-tools`) as a JSON manifest at
|
|
199
|
+
* `GET {mountPath}/rest-tools/manifest` — register that URL in the Persona
|
|
200
|
+
* dashboard as a REST Tool Source and it discovers/calls these tools live,
|
|
201
|
+
* the same way it discovers an MCP server's tools. This is host-side
|
|
202
|
+
* static data the runtime *serves*, not a Persona-proxy capability — it
|
|
203
|
+
* never calls `PersonaClient` and works even with no `resolveUser`
|
|
204
|
+
* traffic at all.
|
|
205
|
+
*/
|
|
206
|
+
interface RestToolsManifestOptions {
|
|
207
|
+
/** REST tool definitions to serve — build each with `defineRestTool` from `@personaai/sdk/rest-tools`, or pass a plain object of the same shape. */
|
|
208
|
+
tools: RestToolManifestEntry[];
|
|
209
|
+
/**
|
|
210
|
+
* Required `Authorization: Bearer <token>` value the manifest route
|
|
211
|
+
* checks incoming requests against — must match the API Key configured
|
|
212
|
+
* on the Persona-side REST Tool Source. Omitting this leaves the route
|
|
213
|
+
* open (no auth) — only acceptable for local/dev testing.
|
|
214
|
+
*/
|
|
215
|
+
authToken?: string;
|
|
216
|
+
}
|
|
187
217
|
interface CreateRuntimeOptions {
|
|
188
218
|
/** Base URL of the Persona Developer Platform API, e.g. "https://api.persona.hasanraiyan.me". */
|
|
189
219
|
baseUrl: string;
|
|
@@ -226,6 +256,8 @@ interface CreateRuntimeOptions {
|
|
|
226
256
|
maxTrackedRuns?: number;
|
|
227
257
|
/** Opt-in switches for Project-level admin surface. See {@link RuntimeCapabilities} — everything defaults to off. */
|
|
228
258
|
capabilities?: RuntimeCapabilities;
|
|
259
|
+
/** Serves a code-defined REST tool list for a Persona REST Tool Source to discover. See {@link RestToolsManifestOptions}. Unset by default — the route only exists when this is provided. */
|
|
260
|
+
restToolsManifest?: RestToolsManifestOptions;
|
|
229
261
|
/** Log level for the runtime — off by default. Overrides the global level set via `setLogLevel()` from `@personaai/sdk`. */
|
|
230
262
|
logLevel?: LogLevel;
|
|
231
263
|
/** Custom logger instance — when provided, `logLevel` is ignored. */
|
|
@@ -254,4 +286,4 @@ declare class RuntimeHttpError extends Error {
|
|
|
254
286
|
|
|
255
287
|
declare const RUNTIME_VERSION = "0.5.4";
|
|
256
288
|
|
|
257
|
-
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, type VoiceSessionCreateContext, createRuntime };
|
|
289
|
+
export { type CreateRuntimeOptions, type ErrorContext, type FileUploadContext, type MemoryWriteContext, RUNTIME_VERSION, type ResolveUser, type RestToolManifestEntry, type RestToolsManifestOptions, 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, type VoiceSessionCreateContext, createRuntime };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChatMessageInput, LogLevel, Logger } from '@personaai/sdk';
|
|
1
|
+
import { ChatMessageInput, CreateRestToolInput, LogLevel, Logger } from '@personaai/sdk';
|
|
2
2
|
|
|
3
3
|
type RuntimeMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
4
4
|
/** A single uploaded file — present on `RuntimeRequest.file` for a multipart `POST /files`. */
|
|
@@ -116,6 +116,8 @@ interface MemoryWriteContext {
|
|
|
116
116
|
interface VoiceSessionCreateContext {
|
|
117
117
|
userId: string;
|
|
118
118
|
agentId: string;
|
|
119
|
+
/** Set when the session resumed an existing conversation (optional `threadId` on the request). */
|
|
120
|
+
threadId?: string;
|
|
119
121
|
}
|
|
120
122
|
/**
|
|
121
123
|
* Lifecycle hooks — the host application's voice inside the runtime's
|
|
@@ -146,6 +148,13 @@ interface RuntimeHooks {
|
|
|
146
148
|
onVoiceSessionCreate?(ctx: VoiceSessionCreateContext): void | Promise<void>;
|
|
147
149
|
}
|
|
148
150
|
|
|
151
|
+
/**
|
|
152
|
+
* One REST tool definition served by the manifest route — identical to
|
|
153
|
+
* `CreateRestToolInput` from `@personaai/sdk@^0.7.0` (also `defineRestTool`'s
|
|
154
|
+
* return type from `@personaai/sdk/rest-tools`), aliased under this name for
|
|
155
|
+
* clarity at the call site (`createRuntime({ restToolsManifest: { tools } })`).
|
|
156
|
+
*/
|
|
157
|
+
type RestToolManifestEntry = CreateRestToolInput;
|
|
149
158
|
/**
|
|
150
159
|
* The single point of contact between the host's auth world and the
|
|
151
160
|
* runtime's world. Receives the inbound request (with `userId: null`) and
|
|
@@ -184,6 +193,27 @@ interface RuntimeCapabilities {
|
|
|
184
193
|
/** The Architect co-pilot — builds/edits Agents on the caller's behalf via tool calls. @default false */
|
|
185
194
|
architect?: boolean;
|
|
186
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Serves a list of code-defined REST tools (built with `defineRestTool`
|
|
198
|
+
* from `@personaai/sdk/rest-tools`) as a JSON manifest at
|
|
199
|
+
* `GET {mountPath}/rest-tools/manifest` — register that URL in the Persona
|
|
200
|
+
* dashboard as a REST Tool Source and it discovers/calls these tools live,
|
|
201
|
+
* the same way it discovers an MCP server's tools. This is host-side
|
|
202
|
+
* static data the runtime *serves*, not a Persona-proxy capability — it
|
|
203
|
+
* never calls `PersonaClient` and works even with no `resolveUser`
|
|
204
|
+
* traffic at all.
|
|
205
|
+
*/
|
|
206
|
+
interface RestToolsManifestOptions {
|
|
207
|
+
/** REST tool definitions to serve — build each with `defineRestTool` from `@personaai/sdk/rest-tools`, or pass a plain object of the same shape. */
|
|
208
|
+
tools: RestToolManifestEntry[];
|
|
209
|
+
/**
|
|
210
|
+
* Required `Authorization: Bearer <token>` value the manifest route
|
|
211
|
+
* checks incoming requests against — must match the API Key configured
|
|
212
|
+
* on the Persona-side REST Tool Source. Omitting this leaves the route
|
|
213
|
+
* open (no auth) — only acceptable for local/dev testing.
|
|
214
|
+
*/
|
|
215
|
+
authToken?: string;
|
|
216
|
+
}
|
|
187
217
|
interface CreateRuntimeOptions {
|
|
188
218
|
/** Base URL of the Persona Developer Platform API, e.g. "https://api.persona.hasanraiyan.me". */
|
|
189
219
|
baseUrl: string;
|
|
@@ -226,6 +256,8 @@ interface CreateRuntimeOptions {
|
|
|
226
256
|
maxTrackedRuns?: number;
|
|
227
257
|
/** Opt-in switches for Project-level admin surface. See {@link RuntimeCapabilities} — everything defaults to off. */
|
|
228
258
|
capabilities?: RuntimeCapabilities;
|
|
259
|
+
/** Serves a code-defined REST tool list for a Persona REST Tool Source to discover. See {@link RestToolsManifestOptions}. Unset by default — the route only exists when this is provided. */
|
|
260
|
+
restToolsManifest?: RestToolsManifestOptions;
|
|
229
261
|
/** Log level for the runtime — off by default. Overrides the global level set via `setLogLevel()` from `@personaai/sdk`. */
|
|
230
262
|
logLevel?: LogLevel;
|
|
231
263
|
/** Custom logger instance — when provided, `logLevel` is ignored. */
|
|
@@ -254,4 +286,4 @@ declare class RuntimeHttpError extends Error {
|
|
|
254
286
|
|
|
255
287
|
declare const RUNTIME_VERSION = "0.5.4";
|
|
256
288
|
|
|
257
|
-
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, type VoiceSessionCreateContext, createRuntime };
|
|
289
|
+
export { type CreateRuntimeOptions, type ErrorContext, type FileUploadContext, type MemoryWriteContext, RUNTIME_VERSION, type ResolveUser, type RestToolManifestEntry, type RestToolsManifestOptions, 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, type VoiceSessionCreateContext, createRuntime };
|
package/dist/index.js
CHANGED
|
@@ -161,6 +161,71 @@ var healthRoute = async (_request, ctx) => {
|
|
|
161
161
|
};
|
|
162
162
|
};
|
|
163
163
|
|
|
164
|
+
// src/routeHelpers.ts
|
|
165
|
+
function json(status, value) {
|
|
166
|
+
return {
|
|
167
|
+
kind: "buffered",
|
|
168
|
+
status,
|
|
169
|
+
headers: { "content-type": "application/json" },
|
|
170
|
+
body: JSON.stringify(value)
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function noContent() {
|
|
174
|
+
return { kind: "buffered", status: 204, headers: {}, body: "" };
|
|
175
|
+
}
|
|
176
|
+
function requireParam(params, name) {
|
|
177
|
+
const value = params[name];
|
|
178
|
+
if (!value) {
|
|
179
|
+
throw new RuntimeHttpError(400, "INVALID_REQUEST", `"${name}" path parameter is required.`);
|
|
180
|
+
}
|
|
181
|
+
return value;
|
|
182
|
+
}
|
|
183
|
+
function requireQueryParam(query, name) {
|
|
184
|
+
const value = query[name];
|
|
185
|
+
if (!value) {
|
|
186
|
+
throw new RuntimeHttpError(400, "INVALID_REQUEST", `"${name}" query parameter is required.`);
|
|
187
|
+
}
|
|
188
|
+
return value;
|
|
189
|
+
}
|
|
190
|
+
function toInt(value) {
|
|
191
|
+
if (value === void 0) return void 0;
|
|
192
|
+
const parsed = Number.parseInt(value, 10);
|
|
193
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
194
|
+
}
|
|
195
|
+
function requireBodyObject(body) {
|
|
196
|
+
if (typeof body !== "object" || body === null) {
|
|
197
|
+
throw new RuntimeHttpError(400, "INVALID_REQUEST", "Request body must be a JSON object.");
|
|
198
|
+
}
|
|
199
|
+
return body;
|
|
200
|
+
}
|
|
201
|
+
function requireStringField(body, field) {
|
|
202
|
+
const value = body[field];
|
|
203
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
204
|
+
throw new RuntimeHttpError(
|
|
205
|
+
400,
|
|
206
|
+
"INVALID_REQUEST",
|
|
207
|
+
`"${field}" is required and must be a string.`
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
return value;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/routes/restToolsManifest.ts
|
|
214
|
+
var restToolsManifestRoute = async (request, ctx) => {
|
|
215
|
+
const manifest = ctx.restToolsManifest;
|
|
216
|
+
if (!manifest) {
|
|
217
|
+
throw new RuntimeHttpError(404, "NOT_FOUND", "No REST tools manifest is configured.");
|
|
218
|
+
}
|
|
219
|
+
if (manifest.authToken) {
|
|
220
|
+
const header = request.headers.authorization;
|
|
221
|
+
const expected = `Bearer ${manifest.authToken}`;
|
|
222
|
+
if (header !== expected) {
|
|
223
|
+
throw new RuntimeHttpError(401, "UNAUTHORIZED", "Invalid or missing manifest bearer token.");
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return json(200, { tools: manifest.tools });
|
|
227
|
+
};
|
|
228
|
+
|
|
164
229
|
// src/runDriver.ts
|
|
165
230
|
import { EventType } from "@personaai/sdk";
|
|
166
231
|
function formatSseFrame(event) {
|
|
@@ -619,55 +684,6 @@ function createResumeRoute(expectedKind) {
|
|
|
619
684
|
};
|
|
620
685
|
}
|
|
621
686
|
|
|
622
|
-
// src/routeHelpers.ts
|
|
623
|
-
function json(status, value) {
|
|
624
|
-
return {
|
|
625
|
-
kind: "buffered",
|
|
626
|
-
status,
|
|
627
|
-
headers: { "content-type": "application/json" },
|
|
628
|
-
body: JSON.stringify(value)
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
function noContent() {
|
|
632
|
-
return { kind: "buffered", status: 204, headers: {}, body: "" };
|
|
633
|
-
}
|
|
634
|
-
function requireParam(params, name) {
|
|
635
|
-
const value = params[name];
|
|
636
|
-
if (!value) {
|
|
637
|
-
throw new RuntimeHttpError(400, "INVALID_REQUEST", `"${name}" path parameter is required.`);
|
|
638
|
-
}
|
|
639
|
-
return value;
|
|
640
|
-
}
|
|
641
|
-
function requireQueryParam(query, name) {
|
|
642
|
-
const value = query[name];
|
|
643
|
-
if (!value) {
|
|
644
|
-
throw new RuntimeHttpError(400, "INVALID_REQUEST", `"${name}" query parameter is required.`);
|
|
645
|
-
}
|
|
646
|
-
return value;
|
|
647
|
-
}
|
|
648
|
-
function toInt(value) {
|
|
649
|
-
if (value === void 0) return void 0;
|
|
650
|
-
const parsed = Number.parseInt(value, 10);
|
|
651
|
-
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
652
|
-
}
|
|
653
|
-
function requireBodyObject(body) {
|
|
654
|
-
if (typeof body !== "object" || body === null) {
|
|
655
|
-
throw new RuntimeHttpError(400, "INVALID_REQUEST", "Request body must be a JSON object.");
|
|
656
|
-
}
|
|
657
|
-
return body;
|
|
658
|
-
}
|
|
659
|
-
function requireStringField(body, field) {
|
|
660
|
-
const value = body[field];
|
|
661
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
662
|
-
throw new RuntimeHttpError(
|
|
663
|
-
400,
|
|
664
|
-
"INVALID_REQUEST",
|
|
665
|
-
`"${field}" is required and must be a string.`
|
|
666
|
-
);
|
|
667
|
-
}
|
|
668
|
-
return value;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
687
|
// src/routes/threads.ts
|
|
672
688
|
var listThreads = async (request, ctx) => {
|
|
673
689
|
const items = await ctx.client.threads.list({
|
|
@@ -719,10 +735,12 @@ var resetThread = async (_request, ctx) => {
|
|
|
719
735
|
var createVoiceSession = async (request, ctx) => {
|
|
720
736
|
const body = requireBodyObject(request.body);
|
|
721
737
|
const agentId = requireStringField(body, "agentId");
|
|
722
|
-
const
|
|
738
|
+
const threadId = typeof body.threadId === "string" && body.threadId ? body.threadId : void 0;
|
|
739
|
+
const ticket = await ctx.client.voice.createSession(agentId, threadId ? { threadId } : {});
|
|
723
740
|
await ctx.hooks?.onVoiceSessionCreate?.({
|
|
724
741
|
userId: request.userId,
|
|
725
|
-
agentId
|
|
742
|
+
agentId,
|
|
743
|
+
threadId
|
|
726
744
|
});
|
|
727
745
|
return json(201, ticket);
|
|
728
746
|
};
|
|
@@ -1433,6 +1451,14 @@ function createRuntime(options) {
|
|
|
1433
1451
|
);
|
|
1434
1452
|
const capabilities = resolveCapabilities(options.capabilities);
|
|
1435
1453
|
const routes = buildRoutes(capabilities);
|
|
1454
|
+
if (options.restToolsManifest) {
|
|
1455
|
+
routes.push({
|
|
1456
|
+
method: "GET",
|
|
1457
|
+
pattern: ["rest-tools", "manifest"],
|
|
1458
|
+
handler: restToolsManifestRoute,
|
|
1459
|
+
requiresAuth: false
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1436
1462
|
const mode = resolveMode(options);
|
|
1437
1463
|
const heartbeatIntervalMs = options.heartbeatIntervalMs ?? 15e3;
|
|
1438
1464
|
const runGraceMs = options.runGraceMs ?? DEFAULT_RUN_GRACE_MS;
|
|
@@ -1598,7 +1624,8 @@ function createRuntime(options) {
|
|
|
1598
1624
|
heartbeatIntervalMs,
|
|
1599
1625
|
runs,
|
|
1600
1626
|
capabilities,
|
|
1601
|
-
logger: routeLogger
|
|
1627
|
+
logger: routeLogger,
|
|
1628
|
+
restToolsManifest: options.restToolsManifest
|
|
1602
1629
|
});
|
|
1603
1630
|
const durationMs = Date.now() - startMs;
|
|
1604
1631
|
logger.info("handle succeeded", {
|