@dexto/server 1.6.17 → 1.6.19

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.
@@ -24,9 +24,33 @@ module.exports = __toCommonJS(sessions_exports);
24
24
  var import_zod_openapi = require("@hono/zod-openapi");
25
25
  var import_core = require("@dexto/core");
26
26
  var import_responses = require("../schemas/responses.js");
27
+ var import_error = require("../middleware/error.js");
27
28
  const CreateSessionSchema = import_zod_openapi.z.object({
28
29
  sessionId: import_zod_openapi.z.string().optional().describe("A custom ID for the new session")
29
30
  }).describe("Request body for creating a new session");
31
+ const MAX_SYSTEM_PROMPT_CONTRIBUTOR_CONTENT_CHARS = 12e4;
32
+ const DEFAULT_SYSTEM_PROMPT_CONTRIBUTOR_PRIORITY = 45;
33
+ const SessionPromptContributorInfoSchema = import_zod_openapi.z.object({
34
+ id: import_zod_openapi.z.string().describe("Contributor identifier"),
35
+ priority: import_zod_openapi.z.number().describe("Contributor priority")
36
+ }).strict().describe("Session-scoped system prompt contributor metadata.");
37
+ const UpsertSessionPromptContributorSchema = import_zod_openapi.z.object({
38
+ id: import_zod_openapi.z.string().min(1).describe("Contributor identifier"),
39
+ priority: import_zod_openapi.z.number().int().nonnegative().optional().default(DEFAULT_SYSTEM_PROMPT_CONTRIBUTOR_PRIORITY).describe("Optional priority override"),
40
+ enabled: import_zod_openapi.z.boolean().default(true).describe("Set false to remove the contributor instead of adding or updating it"),
41
+ content: import_zod_openapi.z.string().optional().describe("Static contributor content for this session (required when enabled)")
42
+ }).strict().superRefine((value, ctx) => {
43
+ if (value.enabled !== false && (!value.content || value.content.trim().length === 0)) {
44
+ ctx.addIssue({
45
+ code: import_zod_openapi.z.ZodIssueCode.custom,
46
+ path: ["content"],
47
+ message: "Contributor content is required when enabled"
48
+ });
49
+ }
50
+ }).describe("Session-scoped system prompt contributor update payload.");
51
+ function sanitizeContributorId(value) {
52
+ return value.trim().replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
53
+ }
30
54
  function mapSessionMetadata(sessionId, metadata, defaults) {
31
55
  return {
32
56
  id: sessionId,
@@ -45,7 +69,24 @@ function mapSessionMetadata(sessionId, metadata, defaults) {
45
69
  };
46
70
  }
47
71
  function createSessionsRouter(getAgent) {
48
- const app = new import_zod_openapi.OpenAPIHono();
72
+ const app = new import_zod_openapi.OpenAPIHono({
73
+ defaultHook: (result, ctx) => {
74
+ if (!result.success) {
75
+ const issues = (0, import_core.zodToIssues)(result.error);
76
+ return (0, import_error.handleHonoError)(
77
+ ctx,
78
+ new import_core.DextoRuntimeError(
79
+ "validation_failed",
80
+ "validation",
81
+ import_core.ErrorType.USER,
82
+ issues[0]?.message ?? "Validation failed",
83
+ { issues }
84
+ )
85
+ );
86
+ }
87
+ }
88
+ });
89
+ app.onError((err, ctx) => (0, import_error.handleHonoError)(ctx, err));
49
90
  const listRoute = (0, import_zod_openapi.createRoute)({
50
91
  method: "get",
51
92
  path: "/sessions",
@@ -174,6 +215,86 @@ function createSessionsRouter(getAgent) {
174
215
  }
175
216
  }
176
217
  });
218
+ const listSessionPromptContributorsRoute = (0, import_zod_openapi.createRoute)({
219
+ method: "get",
220
+ path: "/sessions/{sessionId}/system-prompt/contributors",
221
+ summary: "List Session System Prompt Contributors",
222
+ description: "Lists static system prompt contributors that apply only to the specified session.",
223
+ tags: ["sessions", "config"],
224
+ request: { params: import_zod_openapi.z.object({ sessionId: import_zod_openapi.z.string().describe("Session identifier") }) },
225
+ responses: {
226
+ 200: {
227
+ description: "Current session contributor list",
228
+ content: {
229
+ "application/json": {
230
+ schema: import_zod_openapi.z.object({
231
+ contributors: import_zod_openapi.z.array(SessionPromptContributorInfoSchema).describe("Registered session prompt contributors.")
232
+ }).strict()
233
+ }
234
+ }
235
+ },
236
+ 404: {
237
+ description: "Session not found",
238
+ content: {
239
+ "application/json": {
240
+ schema: import_responses.StandardErrorEnvelopeSchema
241
+ }
242
+ }
243
+ }
244
+ }
245
+ });
246
+ const upsertSessionPromptContributorRoute = (0, import_zod_openapi.createRoute)({
247
+ method: "post",
248
+ path: "/sessions/{sessionId}/system-prompt/contributors",
249
+ summary: "Upsert Session System Prompt Contributor",
250
+ description: "Adds or updates a static system prompt contributor that applies only to the specified session. Set enabled=false to remove it.",
251
+ tags: ["sessions", "config"],
252
+ request: {
253
+ params: import_zod_openapi.z.object({ sessionId: import_zod_openapi.z.string().describe("Session identifier") }),
254
+ body: {
255
+ required: true,
256
+ content: {
257
+ "application/json": {
258
+ schema: UpsertSessionPromptContributorSchema
259
+ }
260
+ }
261
+ }
262
+ },
263
+ responses: {
264
+ 200: {
265
+ description: "Session contributor upsert result",
266
+ content: {
267
+ "application/json": {
268
+ schema: import_zod_openapi.z.object({
269
+ id: import_zod_openapi.z.string().describe("Contributor identifier"),
270
+ enabled: import_zod_openapi.z.boolean().describe("Whether the contributor remains enabled"),
271
+ priority: import_zod_openapi.z.number().optional().describe("Contributor priority"),
272
+ replaced: import_zod_openapi.z.boolean().optional().describe("Whether an existing contributor was replaced"),
273
+ removed: import_zod_openapi.z.boolean().optional().describe("Whether the contributor was removed"),
274
+ contentLength: import_zod_openapi.z.number().optional().describe("Stored content length in characters"),
275
+ truncated: import_zod_openapi.z.boolean().optional().describe("Whether the submitted content was truncated")
276
+ }).strict()
277
+ }
278
+ }
279
+ },
280
+ 400: {
281
+ description: "Invalid session contributor request",
282
+ content: {
283
+ "application/json": {
284
+ schema: import_responses.StandardErrorEnvelopeSchema
285
+ }
286
+ }
287
+ },
288
+ 404: {
289
+ description: "Session not found",
290
+ content: {
291
+ "application/json": {
292
+ schema: import_responses.StandardErrorEnvelopeSchema
293
+ }
294
+ }
295
+ }
296
+ }
297
+ });
177
298
  const deleteRoute = (0, import_zod_openapi.createRoute)({
178
299
  method: "delete",
179
300
  path: "/sessions/{sessionId}",
@@ -420,6 +541,81 @@ function createSessionsRouter(getAgent) {
420
541
  history,
421
542
  isBusy
422
543
  });
544
+ }).openapi(listSessionPromptContributorsRoute, async (ctx) => {
545
+ const agent = await getAgent(ctx);
546
+ const { sessionId } = ctx.req.valid("param");
547
+ const contributors = await agent.getSessionSystemPromptContributors(sessionId);
548
+ return ctx.json(
549
+ {
550
+ contributors: contributors.map((contributor) => ({
551
+ id: contributor.id,
552
+ priority: contributor.priority
553
+ }))
554
+ },
555
+ 200
556
+ );
557
+ }).openapi(upsertSessionPromptContributorRoute, async (ctx) => {
558
+ const agent = await getAgent(ctx);
559
+ const { sessionId } = ctx.req.valid("param");
560
+ const payload = ctx.req.valid("json");
561
+ const contributorId = sanitizeContributorId(payload.id);
562
+ if (contributorId.length === 0) {
563
+ throw new import_core.DextoRuntimeError(
564
+ "session_systemprompt_contributor_config_invalid",
565
+ import_core.ErrorScope.SYSTEM_PROMPT,
566
+ import_core.ErrorType.USER,
567
+ "A valid contributor id is required",
568
+ {
569
+ id: payload.id,
570
+ sessionId
571
+ }
572
+ );
573
+ }
574
+ const rawContent = payload.content ?? "";
575
+ const content = rawContent.slice(0, MAX_SYSTEM_PROMPT_CONTRIBUTOR_CONTENT_CHARS);
576
+ if (!payload.enabled) {
577
+ const removed = await agent.removeSessionSystemPromptContributor(
578
+ sessionId,
579
+ contributorId
580
+ );
581
+ return ctx.json(
582
+ {
583
+ id: contributorId,
584
+ enabled: false,
585
+ removed
586
+ },
587
+ 200
588
+ );
589
+ }
590
+ if (content.trim().length === 0) {
591
+ throw new import_core.DextoRuntimeError(
592
+ "session_systemprompt_contributor_config_invalid",
593
+ import_core.ErrorScope.SYSTEM_PROMPT,
594
+ import_core.ErrorType.USER,
595
+ "Contributor content is required when enabled",
596
+ {
597
+ id: payload.id,
598
+ sessionId
599
+ }
600
+ );
601
+ }
602
+ const priority = payload.priority;
603
+ const result = await agent.upsertSessionSystemPromptContributor(sessionId, {
604
+ id: contributorId,
605
+ priority,
606
+ content
607
+ });
608
+ return ctx.json(
609
+ {
610
+ id: contributorId,
611
+ enabled: true,
612
+ priority,
613
+ replaced: result.replaced,
614
+ contentLength: content.length,
615
+ truncated: rawContent.length > content.length
616
+ },
617
+ 200
618
+ );
423
619
  }).openapi(deleteRoute, async (ctx) => {
424
620
  const agent = await getAgent(ctx);
425
621
  const { sessionId } = ctx.req.param();
@@ -464,7 +660,7 @@ function createSessionsRouter(getAgent) {
464
660
  const metadata = await agent.getSessionMetadata(sessionId);
465
661
  const isBusy = await agent.isSessionBusy(sessionId);
466
662
  const usageSummary = await agent.getSessionUsageSummary(sessionId);
467
- const activeUsageScopeId = (0, import_core.getConfiguredUsageScopeId)() ?? null;
663
+ const activeUsageScopeId = agent.getEffectiveConfig().usageScopeId ?? null;
468
664
  const activeUsageScope = activeUsageScopeId ? {
469
665
  scopeId: activeUsageScopeId,
470
666
  ...await agent.getSessionUsageSummary(sessionId, activeUsageScopeId)
@@ -256,6 +256,7 @@ export declare function createSessionsRouter(getAgent: GetAgentFn): OpenAPIHono<
256
256
  } | undefined;
257
257
  })[] | null;
258
258
  role: "system" | "user" | "assistant" | "tool";
259
+ usageScopeId?: string | undefined;
259
260
  id?: string | undefined;
260
261
  name?: string | undefined;
261
262
  timestamp?: number | undefined;
@@ -270,7 +271,6 @@ export declare function createSessionsRouter(getAgent: GetAgentFn): OpenAPIHono<
270
271
  } | undefined;
271
272
  estimatedCost?: number | undefined;
272
273
  pricingStatus?: "estimated" | "unpriced" | undefined;
273
- usageScopeId?: string | undefined;
274
274
  model?: string | undefined;
275
275
  provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto-nova" | undefined;
276
276
  toolCalls?: {
@@ -290,6 +290,93 @@ export declare function createSessionsRouter(getAgent: GetAgentFn): OpenAPIHono<
290
290
  status: 200;
291
291
  };
292
292
  };
293
+ } & {
294
+ "/sessions/:sessionId/system-prompt/contributors": {
295
+ $get: {
296
+ input: {
297
+ param: {
298
+ sessionId: string;
299
+ };
300
+ };
301
+ output: never;
302
+ outputFormat: "json";
303
+ status: 404;
304
+ } | {
305
+ input: {
306
+ param: {
307
+ sessionId: string;
308
+ };
309
+ };
310
+ output: {
311
+ contributors: {
312
+ id: string;
313
+ priority: number;
314
+ }[];
315
+ };
316
+ outputFormat: "json";
317
+ status: 200;
318
+ };
319
+ };
320
+ } & {
321
+ "/sessions/:sessionId/system-prompt/contributors": {
322
+ $post: {
323
+ input: {
324
+ param: {
325
+ sessionId: string;
326
+ };
327
+ } & {
328
+ json: {
329
+ id: string;
330
+ content?: string | undefined;
331
+ enabled?: boolean | undefined;
332
+ priority?: number | undefined;
333
+ };
334
+ };
335
+ output: never;
336
+ outputFormat: "json";
337
+ status: 400;
338
+ } | {
339
+ input: {
340
+ param: {
341
+ sessionId: string;
342
+ };
343
+ } & {
344
+ json: {
345
+ id: string;
346
+ content?: string | undefined;
347
+ enabled?: boolean | undefined;
348
+ priority?: number | undefined;
349
+ };
350
+ };
351
+ output: never;
352
+ outputFormat: "json";
353
+ status: 404;
354
+ } | {
355
+ input: {
356
+ param: {
357
+ sessionId: string;
358
+ };
359
+ } & {
360
+ json: {
361
+ id: string;
362
+ content?: string | undefined;
363
+ enabled?: boolean | undefined;
364
+ priority?: number | undefined;
365
+ };
366
+ };
367
+ output: {
368
+ id: string;
369
+ enabled: boolean;
370
+ priority?: number | undefined;
371
+ replaced?: boolean | undefined;
372
+ removed?: boolean | undefined;
373
+ contentLength?: number | undefined;
374
+ truncated?: boolean | undefined;
375
+ };
376
+ outputFormat: "json";
377
+ status: 200;
378
+ };
379
+ };
293
380
  } & {
294
381
  "/sessions/:sessionId": {
295
382
  $delete: {
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAYhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAqC9C,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAwjBxD"}
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAehE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAwF9C,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAowBxD"}
@@ -1,6 +1,9 @@
1
1
  import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
2
2
  import {
3
- getConfiguredUsageScopeId
3
+ DextoRuntimeError,
4
+ ErrorScope,
5
+ ErrorType,
6
+ zodToIssues
4
7
  } from "@dexto/core";
5
8
  import {
6
9
  SessionMetadataSchema,
@@ -9,9 +12,33 @@ import {
9
12
  StandardErrorEnvelopeSchema,
10
13
  UsageSummarySchema
11
14
  } from "../schemas/responses.js";
15
+ import { handleHonoError } from "../middleware/error.js";
12
16
  const CreateSessionSchema = z.object({
13
17
  sessionId: z.string().optional().describe("A custom ID for the new session")
14
18
  }).describe("Request body for creating a new session");
19
+ const MAX_SYSTEM_PROMPT_CONTRIBUTOR_CONTENT_CHARS = 12e4;
20
+ const DEFAULT_SYSTEM_PROMPT_CONTRIBUTOR_PRIORITY = 45;
21
+ const SessionPromptContributorInfoSchema = z.object({
22
+ id: z.string().describe("Contributor identifier"),
23
+ priority: z.number().describe("Contributor priority")
24
+ }).strict().describe("Session-scoped system prompt contributor metadata.");
25
+ const UpsertSessionPromptContributorSchema = z.object({
26
+ id: z.string().min(1).describe("Contributor identifier"),
27
+ priority: z.number().int().nonnegative().optional().default(DEFAULT_SYSTEM_PROMPT_CONTRIBUTOR_PRIORITY).describe("Optional priority override"),
28
+ enabled: z.boolean().default(true).describe("Set false to remove the contributor instead of adding or updating it"),
29
+ content: z.string().optional().describe("Static contributor content for this session (required when enabled)")
30
+ }).strict().superRefine((value, ctx) => {
31
+ if (value.enabled !== false && (!value.content || value.content.trim().length === 0)) {
32
+ ctx.addIssue({
33
+ code: z.ZodIssueCode.custom,
34
+ path: ["content"],
35
+ message: "Contributor content is required when enabled"
36
+ });
37
+ }
38
+ }).describe("Session-scoped system prompt contributor update payload.");
39
+ function sanitizeContributorId(value) {
40
+ return value.trim().replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
41
+ }
15
42
  function mapSessionMetadata(sessionId, metadata, defaults) {
16
43
  return {
17
44
  id: sessionId,
@@ -30,7 +57,24 @@ function mapSessionMetadata(sessionId, metadata, defaults) {
30
57
  };
31
58
  }
32
59
  function createSessionsRouter(getAgent) {
33
- const app = new OpenAPIHono();
60
+ const app = new OpenAPIHono({
61
+ defaultHook: (result, ctx) => {
62
+ if (!result.success) {
63
+ const issues = zodToIssues(result.error);
64
+ return handleHonoError(
65
+ ctx,
66
+ new DextoRuntimeError(
67
+ "validation_failed",
68
+ "validation",
69
+ ErrorType.USER,
70
+ issues[0]?.message ?? "Validation failed",
71
+ { issues }
72
+ )
73
+ );
74
+ }
75
+ }
76
+ });
77
+ app.onError((err, ctx) => handleHonoError(ctx, err));
34
78
  const listRoute = createRoute({
35
79
  method: "get",
36
80
  path: "/sessions",
@@ -159,6 +203,86 @@ function createSessionsRouter(getAgent) {
159
203
  }
160
204
  }
161
205
  });
206
+ const listSessionPromptContributorsRoute = createRoute({
207
+ method: "get",
208
+ path: "/sessions/{sessionId}/system-prompt/contributors",
209
+ summary: "List Session System Prompt Contributors",
210
+ description: "Lists static system prompt contributors that apply only to the specified session.",
211
+ tags: ["sessions", "config"],
212
+ request: { params: z.object({ sessionId: z.string().describe("Session identifier") }) },
213
+ responses: {
214
+ 200: {
215
+ description: "Current session contributor list",
216
+ content: {
217
+ "application/json": {
218
+ schema: z.object({
219
+ contributors: z.array(SessionPromptContributorInfoSchema).describe("Registered session prompt contributors.")
220
+ }).strict()
221
+ }
222
+ }
223
+ },
224
+ 404: {
225
+ description: "Session not found",
226
+ content: {
227
+ "application/json": {
228
+ schema: StandardErrorEnvelopeSchema
229
+ }
230
+ }
231
+ }
232
+ }
233
+ });
234
+ const upsertSessionPromptContributorRoute = createRoute({
235
+ method: "post",
236
+ path: "/sessions/{sessionId}/system-prompt/contributors",
237
+ summary: "Upsert Session System Prompt Contributor",
238
+ description: "Adds or updates a static system prompt contributor that applies only to the specified session. Set enabled=false to remove it.",
239
+ tags: ["sessions", "config"],
240
+ request: {
241
+ params: z.object({ sessionId: z.string().describe("Session identifier") }),
242
+ body: {
243
+ required: true,
244
+ content: {
245
+ "application/json": {
246
+ schema: UpsertSessionPromptContributorSchema
247
+ }
248
+ }
249
+ }
250
+ },
251
+ responses: {
252
+ 200: {
253
+ description: "Session contributor upsert result",
254
+ content: {
255
+ "application/json": {
256
+ schema: z.object({
257
+ id: z.string().describe("Contributor identifier"),
258
+ enabled: z.boolean().describe("Whether the contributor remains enabled"),
259
+ priority: z.number().optional().describe("Contributor priority"),
260
+ replaced: z.boolean().optional().describe("Whether an existing contributor was replaced"),
261
+ removed: z.boolean().optional().describe("Whether the contributor was removed"),
262
+ contentLength: z.number().optional().describe("Stored content length in characters"),
263
+ truncated: z.boolean().optional().describe("Whether the submitted content was truncated")
264
+ }).strict()
265
+ }
266
+ }
267
+ },
268
+ 400: {
269
+ description: "Invalid session contributor request",
270
+ content: {
271
+ "application/json": {
272
+ schema: StandardErrorEnvelopeSchema
273
+ }
274
+ }
275
+ },
276
+ 404: {
277
+ description: "Session not found",
278
+ content: {
279
+ "application/json": {
280
+ schema: StandardErrorEnvelopeSchema
281
+ }
282
+ }
283
+ }
284
+ }
285
+ });
162
286
  const deleteRoute = createRoute({
163
287
  method: "delete",
164
288
  path: "/sessions/{sessionId}",
@@ -405,6 +529,81 @@ function createSessionsRouter(getAgent) {
405
529
  history,
406
530
  isBusy
407
531
  });
532
+ }).openapi(listSessionPromptContributorsRoute, async (ctx) => {
533
+ const agent = await getAgent(ctx);
534
+ const { sessionId } = ctx.req.valid("param");
535
+ const contributors = await agent.getSessionSystemPromptContributors(sessionId);
536
+ return ctx.json(
537
+ {
538
+ contributors: contributors.map((contributor) => ({
539
+ id: contributor.id,
540
+ priority: contributor.priority
541
+ }))
542
+ },
543
+ 200
544
+ );
545
+ }).openapi(upsertSessionPromptContributorRoute, async (ctx) => {
546
+ const agent = await getAgent(ctx);
547
+ const { sessionId } = ctx.req.valid("param");
548
+ const payload = ctx.req.valid("json");
549
+ const contributorId = sanitizeContributorId(payload.id);
550
+ if (contributorId.length === 0) {
551
+ throw new DextoRuntimeError(
552
+ "session_systemprompt_contributor_config_invalid",
553
+ ErrorScope.SYSTEM_PROMPT,
554
+ ErrorType.USER,
555
+ "A valid contributor id is required",
556
+ {
557
+ id: payload.id,
558
+ sessionId
559
+ }
560
+ );
561
+ }
562
+ const rawContent = payload.content ?? "";
563
+ const content = rawContent.slice(0, MAX_SYSTEM_PROMPT_CONTRIBUTOR_CONTENT_CHARS);
564
+ if (!payload.enabled) {
565
+ const removed = await agent.removeSessionSystemPromptContributor(
566
+ sessionId,
567
+ contributorId
568
+ );
569
+ return ctx.json(
570
+ {
571
+ id: contributorId,
572
+ enabled: false,
573
+ removed
574
+ },
575
+ 200
576
+ );
577
+ }
578
+ if (content.trim().length === 0) {
579
+ throw new DextoRuntimeError(
580
+ "session_systemprompt_contributor_config_invalid",
581
+ ErrorScope.SYSTEM_PROMPT,
582
+ ErrorType.USER,
583
+ "Contributor content is required when enabled",
584
+ {
585
+ id: payload.id,
586
+ sessionId
587
+ }
588
+ );
589
+ }
590
+ const priority = payload.priority;
591
+ const result = await agent.upsertSessionSystemPromptContributor(sessionId, {
592
+ id: contributorId,
593
+ priority,
594
+ content
595
+ });
596
+ return ctx.json(
597
+ {
598
+ id: contributorId,
599
+ enabled: true,
600
+ priority,
601
+ replaced: result.replaced,
602
+ contentLength: content.length,
603
+ truncated: rawContent.length > content.length
604
+ },
605
+ 200
606
+ );
408
607
  }).openapi(deleteRoute, async (ctx) => {
409
608
  const agent = await getAgent(ctx);
410
609
  const { sessionId } = ctx.req.param();
@@ -449,7 +648,7 @@ function createSessionsRouter(getAgent) {
449
648
  const metadata = await agent.getSessionMetadata(sessionId);
450
649
  const isBusy = await agent.isSessionBusy(sessionId);
451
650
  const usageSummary = await agent.getSessionUsageSummary(sessionId);
452
- const activeUsageScopeId = getConfiguredUsageScopeId() ?? null;
651
+ const activeUsageScopeId = agent.getEffectiveConfig().usageScopeId ?? null;
453
652
  const activeUsageScope = activeUsageScopeId ? {
454
653
  scopeId: activeUsageScopeId,
455
654
  ...await agent.getSessionUsageSummary(sessionId, activeUsageScopeId)
@@ -42,9 +42,9 @@ export declare function createSystemPromptRouter(getAgent: GetAgentFn): OpenAPIH
42
42
  output: {
43
43
  id: string;
44
44
  enabled: boolean;
45
- removed?: boolean | undefined;
46
45
  priority?: number | undefined;
47
46
  replaced?: boolean | undefined;
47
+ removed?: boolean | undefined;
48
48
  contentLength?: number | undefined;
49
49
  truncated?: boolean | undefined;
50
50
  };