@personaai/runtime 0.9.1 → 0.9.4

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 CHANGED
@@ -159,7 +159,7 @@ function evictStaleRuns(runs, now, graceMs = DEFAULT_RUN_GRACE_MS, maxTracked =
159
159
  }
160
160
 
161
161
  // src/version.ts
162
- var RUNTIME_VERSION = "0.5.4";
162
+ var RUNTIME_VERSION = "0.9.4";
163
163
 
164
164
  // src/routes/health.ts
165
165
  var alwaysOnCapabilities = {
@@ -237,6 +237,33 @@ function requireStringField(body, field) {
237
237
  }
238
238
  return value;
239
239
  }
240
+ var MAX_TURN_CONTEXT_BYTES = 2e3;
241
+ function validateTurnContext(value) {
242
+ if (value === void 0) return void 0;
243
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
244
+ throw new RuntimeHttpError(400, "INVALID_CONTEXT", "context must be a flat object.");
245
+ }
246
+ const context = value;
247
+ for (const [key, entry] of Object.entries(context)) {
248
+ const entryType = typeof entry;
249
+ if (entryType !== "string" && entryType !== "number" && entryType !== "boolean") {
250
+ throw new RuntimeHttpError(
251
+ 400,
252
+ "INVALID_CONTEXT",
253
+ `context.${key} must be a string, number, or boolean.`
254
+ );
255
+ }
256
+ }
257
+ const byteLength = new TextEncoder().encode(JSON.stringify(context)).length;
258
+ if (byteLength > MAX_TURN_CONTEXT_BYTES) {
259
+ throw new RuntimeHttpError(
260
+ 400,
261
+ "CONTEXT_TOO_LARGE",
262
+ `context must be ${MAX_TURN_CONTEXT_BYTES} bytes or fewer when serialized.`
263
+ );
264
+ }
265
+ return context;
266
+ }
240
267
 
241
268
  // src/routes/restToolsManifest.ts
242
269
  var restToolsManifestRoute = async (request, ctx) => {
@@ -562,7 +589,12 @@ function parseChatBody(body) {
562
589
  messages: b.messages,
563
590
  threadId: typeof b.threadId === "string" ? b.threadId : void 0,
564
591
  resume: b.resume ?? void 0,
565
- contextOverride: typeof b.contextOverride === "string" ? b.contextOverride : void 0
592
+ contextOverride: typeof b.contextOverride === "string" ? b.contextOverride : void 0,
593
+ // Distinct from contextOverride above — never shown to the model, only
594
+ // ever read live by an RCP tool's resolver. validateTurnContext throws
595
+ // a 400 on any shape violation (not a flat string/number/boolean
596
+ // object, or over the byte cap) rather than coercing/dropping it.
597
+ context: validateTurnContext(b.context)
566
598
  };
567
599
  }
568
600
  var chatRoute = async (request, ctx) => {
@@ -574,7 +606,8 @@ var chatRoute = async (request, ctx) => {
574
606
  threadId: body.threadId,
575
607
  messageCount: body.messages?.length ?? 0,
576
608
  hasResume: !!body.resume,
577
- hasContextOverride: !!body.contextOverride
609
+ hasContextOverride: !!body.contextOverride,
610
+ hasContext: !!body.context
578
611
  });
579
612
  const userId = request.userId;
580
613
  const runCtx = {
@@ -592,7 +625,8 @@ var chatRoute = async (request, ctx) => {
592
625
  messages: body.messages,
593
626
  threadId: body.threadId,
594
627
  resume: body.resume,
595
- contextOverride: body.contextOverride
628
+ contextOverride: body.contextOverride,
629
+ context: body.context
596
630
  });
597
631
  const runId = crypto.randomUUID();
598
632
  logger.info("chat run created", {
@@ -785,9 +819,11 @@ var createVoiceSession = async (request, ctx) => {
785
819
  const agentId = requireStringField(body, "agentId");
786
820
  const threadId = typeof body.threadId === "string" && body.threadId ? body.threadId : void 0;
787
821
  const contextOverride = typeof body.contextOverride === "string" && body.contextOverride ? body.contextOverride : void 0;
822
+ const context = validateTurnContext(body.context);
788
823
  const ticket = await ctx.client.voice.createSession(agentId, {
789
824
  ...threadId ? { threadId } : {},
790
- ...contextOverride ? { contextOverride } : {}
825
+ ...contextOverride ? { contextOverride } : {},
826
+ ...context ? { context } : {}
791
827
  });
792
828
  await ctx.hooks?.onVoiceSessionCreate?.({
793
829
  userId: request.userId,
@@ -1385,6 +1421,17 @@ function buildRoutes(capabilities) {
1385
1421
  method: "GET",
1386
1422
  pattern: ["agents", ":id", "mcp-connections"],
1387
1423
  handler: getAgentMcpConnections
1424
+ },
1425
+ // MCP App resources and widget tool calls — always on for conversational widgets.
1426
+ {
1427
+ method: "GET",
1428
+ pattern: ["mcps", ":id", "resource"],
1429
+ handler: readMcpResource
1430
+ },
1431
+ {
1432
+ method: "POST",
1433
+ pattern: ["mcps", ":id", "call-tool"],
1434
+ handler: callMcpTool
1388
1435
  }
1389
1436
  ];
1390
1437
  if (capabilities.agentsWrite) {
@@ -1405,9 +1452,7 @@ function buildRoutes(capabilities) {
1405
1452
  { method: "PATCH", pattern: ["mcps", ":id"], handler: updateMcp },
1406
1453
  { method: "DELETE", pattern: ["mcps", ":id"], handler: deleteMcp },
1407
1454
  { method: "GET", pattern: ["mcps", ":id", "usage"], handler: getMcpUsage },
1408
- { method: "POST", pattern: ["mcps", ":id", "test"], handler: testMcpConnection },
1409
- { method: "GET", pattern: ["mcps", ":id", "resource"], handler: readMcpResource },
1410
- { method: "POST", pattern: ["mcps", ":id", "call-tool"], handler: callMcpTool }
1455
+ { method: "POST", pattern: ["mcps", ":id", "test"], handler: testMcpConnection }
1411
1456
  );
1412
1457
  }
1413
1458
  if (capabilities.providers) {