@economic/agents 1.6.3 → 1.6.5

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.d.mts CHANGED
@@ -57,9 +57,9 @@ declare function buildLLMParams(config: BuildLLMParamsConfig): LLMParams;
57
57
  * type MyContext = AgentToolContext<MyBody>;
58
58
  * ```
59
59
  */
60
- type AgentToolContext<TBody = Record<string, unknown>, TSession = Record<string, unknown> | undefined> = TBody & {
61
- logEvent: (message: string, payload?: Record<string, unknown>) => void | Promise<void>;
62
- session?: TSession;
60
+ type AgentToolContext<TBody = Record<string, unknown>, TJwtIdentity = Record<string, unknown> | undefined> = TBody & {
61
+ _logEvent: (message: string, payload?: Record<string, unknown>) => void | Promise<void>;
62
+ _jwtIdentity?: TJwtIdentity;
63
63
  };
64
64
  interface AgentEnv {
65
65
  AGENT_DB: D1Database;
@@ -95,12 +95,7 @@ interface JwtAuthConfig<TClaims extends Record<string, unknown> = Record<string,
95
95
  * For chat agents with message history, compaction, and conversation recording,
96
96
  * extend {@link ChatAgent} instead.
97
97
  */
98
- declare abstract class Agent<Env extends Cloudflare.Env = Cloudflare.Env> extends Agent$1<Env & AgentEnv> {
99
- /**
100
- * Verified session claims from JWT authentication.
101
- * Set in `onConnect` when `getJwtAuthConfig` is implemented.
102
- */
103
- private session?;
98
+ declare abstract class Agent<Env extends Cloudflare.Env = Cloudflare.Env, TJwtIdentity extends Record<string, unknown> = Record<string, unknown>> extends Agent$1<Env & AgentEnv> {
104
99
  /**
105
100
  * Override to enable JWT authentication on WebSocket connections.
106
101
  * Return the auth config based on the incoming request, or undefined to skip auth.
@@ -109,6 +104,17 @@ declare abstract class Agent<Env extends Cloudflare.Env = Cloudflare.Env> extend
109
104
  * @returns JWT auth config or undefined to skip authentication
110
105
  */
111
106
  protected getJwtAuthConfig?(request: Request): JwtAuthConfig<Record<string, unknown>> | undefined;
107
+ /**
108
+ * The identity associated with the session.
109
+ * Define getIdentity to return the identity from the request.
110
+ */
111
+ protected jwtIdentity: TJwtIdentity;
112
+ /**
113
+ * Returns the identity following verification of the JWT token - getJwtAuthConfig is required.
114
+ * @returns The identity from the request.
115
+ * @param token - The token from the request.
116
+ */
117
+ protected getJwtIdentity?(token: string): Promise<TJwtIdentity>;
112
118
  /**
113
119
  * Returns the user ID from the durable object name.
114
120
  */
@@ -152,7 +158,7 @@ interface MessageRating {
152
158
  * Skill loading, compaction, and LLM calls use `buildLLMParams` from
153
159
  * `@economic/agents` inside `onChatMessage`.
154
160
  */
155
- declare abstract class ChatAgent<Env extends Cloudflare.Env = Cloudflare.Env, TSessionIdentity extends Record<string, unknown> = Record<string, unknown>> extends AIChatAgent<Env & ChatAgentEnv> {
161
+ declare abstract class ChatAgent<Env extends Cloudflare.Env = Cloudflare.Env, TJwtIdentity extends Record<string, unknown> = Record<string, unknown>> extends AIChatAgent<Env & ChatAgentEnv> {
156
162
  /**
157
163
  * The binding of the Durable Object instance for this agent.
158
164
  */
@@ -188,11 +194,6 @@ declare abstract class ChatAgent<Env extends Cloudflare.Env = Cloudflare.Env, TS
188
194
  * Default is 15.
189
195
  */
190
196
  protected maxMessagesBeforeCompaction?: number | undefined;
191
- /**
192
- * Verified session claims from JWT authentication.
193
- * Set in `onConnect` when `getJwtAuthConfig` is implemented.
194
- */
195
- private session?;
196
197
  /**
197
198
  * Override to enable JWT authentication on WebSocket connections.
198
199
  * Return the auth config based on the incoming request, or undefined to skip auth.
@@ -205,13 +206,13 @@ declare abstract class ChatAgent<Env extends Cloudflare.Env = Cloudflare.Env, TS
205
206
  * The identity associated with the session.
206
207
  * Define getIdentity to return the identity from the request.
207
208
  */
208
- protected identity: TSessionIdentity;
209
+ protected jwtIdentity: TJwtIdentity;
209
210
  /**
210
- * Returns the identity from the request.
211
+ * Returns the identity following verification of the JWT token - getJwtAuthConfig is required.
211
212
  * @returns The identity from the request.
212
213
  * @param token - The token from the request.
213
214
  */
214
- protected getIdentity(_token: string): Promise<TSessionIdentity>;
215
+ protected getJwtIdentity?(token: string): Promise<TJwtIdentity>;
215
216
  /**
216
217
  * Returns the user ID from the durable object name.
217
218
  */
package/dist/index.mjs CHANGED
@@ -474,10 +474,10 @@ async function verifyJwt(request, config) {
474
474
  */
475
475
  var Agent = class extends Agent$1 {
476
476
  /**
477
- * Verified session claims from JWT authentication.
478
- * Set in `onConnect` when `getJwtAuthConfig` is implemented.
477
+ * The identity associated with the session.
478
+ * Define getIdentity to return the identity from the request.
479
479
  */
480
- session;
480
+ jwtIdentity = {};
481
481
  /**
482
482
  * Returns the user ID from the durable object name.
483
483
  */
@@ -510,7 +510,8 @@ var Agent = class extends Agent$1 {
510
510
  connection.close(result.status === 401 ? 4001 : 4003, result.message);
511
511
  return;
512
512
  }
513
- this.session = result.claims;
513
+ const token = extractTokenFromConnectRequest(ctx.request);
514
+ if (token) this.jwtIdentity = await this.getJwtIdentity?.(token) ?? {};
514
515
  }
515
516
  }
516
517
  return super.onConnect(connection, ctx);
@@ -541,8 +542,8 @@ var Agent = class extends Agent$1 {
541
542
  const experimental_context = {
542
543
  ...config.experimental_context,
543
544
  ...config.options?.body,
544
- session: this.session,
545
- logEvent: this.logEvent.bind(this)
545
+ _jwtIdentity: this.jwtIdentity,
546
+ _logEvent: this.logEvent.bind(this)
546
547
  };
547
548
  const onFinish = async (event) => {
548
549
  this.logEvent("Turn completed", buildTurnLogPayload(event));
@@ -603,7 +604,7 @@ function formatMessagesForSummary(messages) {
603
604
  }
604
605
  if (parts.length > 0) lines.push(`${roleLabel}: ${parts.join(" ")}`);
605
606
  }
606
- return lines.join("\n\n");
607
+ return lines.join("\n");
607
608
  }
608
609
  /**
609
610
  * Calls the model to produce a concise summary of old + recent message windows.
@@ -661,14 +662,37 @@ async function compactIfNeeded(messages, model, tailSize) {
661
662
  }
662
663
  //#endregion
663
664
  //#region src/server/agent-chat/features/conversations/conversations.ts
665
+ /**
666
+ * Renders only the user- and assistant-visible text parts of a message
667
+ * array for conversation title/summary generation.
668
+ *
669
+ * Tool calls, tool results, system messages, and reasoning parts are
670
+ * intentionally excluded so the model receives a clean transcript.
671
+ */
672
+ function formatMessagesForConversationSummary(messages) {
673
+ const lines = [];
674
+ for (const message of messages) {
675
+ if (message.role !== "user" && message.role !== "assistant") continue;
676
+ let text = "";
677
+ if (typeof message.content === "string") text = message.content.trim();
678
+ else text = message.content.filter((part) => part.type === "text").map((part) => part.text.trim()).filter(Boolean).join(" ");
679
+ if (!text) continue;
680
+ const roleLabel = message.role === "user" ? "User" : "Assistant";
681
+ lines.push(`${roleLabel}: ${text}`);
682
+ }
683
+ return lines.join("\n");
684
+ }
685
+ /**
686
+ * Number of recent messages passed to `generateSummary` for rolling
687
+ * summarization. Keeping this bounded prevents the prompt growing
688
+ * unboundedly regardless of conversation length.
689
+ */
690
+ const SUMMARY_CONTEXT_MESSAGES = 15;
664
691
  async function recordConversationSummary(db, durableObjectName, messages, model) {
665
692
  if (!await getConversationSummary(db, durableObjectName)) {
666
693
  const { title, summary } = await generateTitleAndSummary(messages, model);
667
694
  await upsertConversationSummary(db, durableObjectName, title, summary);
668
- } else {
669
- await upsertConversationSummary(db, durableObjectName);
670
- if (messages.length % SUMMARY_CONTEXT_MESSAGES === 0) await generateConversationSummary(db, durableObjectName, messages, model);
671
- }
695
+ } else if (messages.length <= 7 || messages.length % SUMMARY_CONTEXT_MESSAGES === 0) await generateConversationSummary(db, durableObjectName, messages, model);
672
696
  }
673
697
  /**
674
698
  * Records a conversation row in the `conversations` D1 table.
@@ -688,12 +712,6 @@ async function upsertConversationSummary(db, durableObjectName, title, summary)
688
712
  updated_at = excluded.updated_at`).bind(durableObjectName, title ?? null, summary ?? null, now, now).run();
689
713
  }
690
714
  /**
691
- * Number of recent messages passed to `generateSummary` for rolling
692
- * summarization. Keeping this bounded prevents the prompt growing
693
- * unboundedly regardless of conversation length.
694
- */
695
- const SUMMARY_CONTEXT_MESSAGES = 30;
696
- /**
697
715
  * Returns the current `title` and `summary` for a conversation row,
698
716
  * or `null` if the row does not exist yet.
699
717
  */
@@ -732,7 +750,7 @@ async function updateConversationSummary(db, durableObjectName, title, summary)
732
750
  */
733
751
  async function generateTitleAndSummary(messages, model, existingSummary) {
734
752
  const recentMessages = await convertToModelMessages(messages.slice(-SUMMARY_CONTEXT_MESSAGES));
735
- const previousContext = existingSummary ? `Previous summary: ${existingSummary}\n\nMost recent messages:` : "Conversation:";
753
+ const previousContext = existingSummary ? `Previous summary:\n${existingSummary}\n\nMost recent messages:` : "Conversation:";
736
754
  const { output } = await generateText({
737
755
  model,
738
756
  output: Output.object({ schema: jsonSchema({
@@ -744,12 +762,12 @@ async function generateTitleAndSummary(messages, model, existingSummary) {
744
762
  },
745
763
  summary: {
746
764
  type: "string",
747
- description: "2-3 sentence summary. If the conversation direction has changed from the previous summary, reflect the new direction."
765
+ description: "1-2 short sentence summary of the conversation. If the conversation direction has changed from the previous summary, reflect the new direction."
748
766
  }
749
767
  },
750
768
  required: ["title", "summary"]
751
769
  }) }),
752
- prompt: `${previousContext}\n\n${formatMessagesForSummary(recentMessages)}`
770
+ prompt: `${previousContext}\n\n${formatMessagesForConversationSummary(recentMessages)}`
753
771
  });
754
772
  return output;
755
773
  }
@@ -844,23 +862,10 @@ var ChatAgent = class extends AIChatAgent {
844
862
  */
845
863
  maxMessagesBeforeCompaction = 15;
846
864
  /**
847
- * Verified session claims from JWT authentication.
848
- * Set in `onConnect` when `getJwtAuthConfig` is implemented.
849
- */
850
- session;
851
- /**
852
865
  * The identity associated with the session.
853
866
  * Define getIdentity to return the identity from the request.
854
867
  */
855
- identity = {};
856
- /**
857
- * Returns the identity from the request.
858
- * @returns The identity from the request.
859
- * @param token - The token from the request.
860
- */
861
- async getIdentity(_token) {
862
- return Promise.resolve({});
863
- }
868
+ jwtIdentity = {};
864
869
  /**
865
870
  * Returns the user ID from the durable object name.
866
871
  */
@@ -893,11 +898,10 @@ var ChatAgent = class extends AIChatAgent {
893
898
  connection.close(result.status === 401 ? 4001 : 4003, result.message);
894
899
  return;
895
900
  }
896
- this.session = result.claims;
897
901
  }
902
+ const token = extractTokenFromConnectRequest(ctx.request);
903
+ if (token) this.jwtIdentity = await this.getJwtIdentity?.(token) ?? {};
898
904
  }
899
- const token = extractTokenFromConnectRequest(ctx.request);
900
- if (token) this.identity = await this.getIdentity(token);
901
905
  return super.onConnect(connection, ctx);
902
906
  }
903
907
  /**
@@ -931,8 +935,8 @@ var ChatAgent = class extends AIChatAgent {
931
935
  const experimental_context = {
932
936
  ...config.experimental_context,
933
937
  ...config.options?.body,
934
- session: this.session,
935
- logEvent: this.logEvent.bind(this)
938
+ _jwtIdentity: this.jwtIdentity,
939
+ _logEvent: this.logEvent.bind(this)
936
940
  };
937
941
  const messages = await convertToModelMessages(this.messages);
938
942
  const fastModel = this.getFastModel();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@economic/agents",
3
- "version": "1.6.3",
3
+ "version": "1.6.5",
4
4
  "description": "A starter for creating a TypeScript package.",
5
5
  "license": "MIT",
6
6
  "bin": {