@friendlyrobot/discord-pi-agent 0.21.0 → 0.21.1

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.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { DiscordGateway, DiscordGatewayConfig } from "./types";
2
- export { buildDiscordMessageContextPrompt, formatDiscordPromptTime, type DiscordMessageContextPromptOptions, type DiscordPromptScope, type DiscordPromptTimeFormatOptions, } from "./prompt-context";
2
+ export { formatDiscordPromptTime } from "./prompt-context";
3
3
  export { loadDiscordGatewayConfigFromEnv, resolveConfig } from "./config";
4
4
  export type { AgentStatus, DiscordGateway, DiscordGatewayConfig, PromptTransform, PromptTransformContext, ResolvedDiscordGatewayConfig, GatewayAccessConfig, } from "./types";
5
5
  /**
package/dist/index.js CHANGED
@@ -508,8 +508,9 @@ class AgentService {
508
508
  const session = this.requireSession();
509
509
  const transformedPrompt = await this.config.promptTransform({
510
510
  rawContent: text,
511
- now: () => new Date().toISOString(),
512
- wrapWithDiscordContext: () => text
511
+ discordMetadata: "",
512
+ now: () => "",
513
+ userMessage: () => text
513
514
  });
514
515
  return runAgentTurn(session, transformedPrompt);
515
516
  }
@@ -674,7 +675,8 @@ function parseThinkingLevel(value) {
674
675
  return;
675
676
  }
676
677
  function defaultPromptTransform(ctx) {
677
- return ctx.wrapWithDiscordContext();
678
+ return [ctx.now(), ctx.discordMetadata, "", ctx.userMessage()].filter(Boolean).join(`
679
+ `);
678
680
  }
679
681
  function parseStringArrayFromEnv(key) {
680
682
  const value = process.env[key];
@@ -1611,28 +1613,6 @@ function stopTypingForChannel(channelKey) {
1611
1613
  }
1612
1614
 
1613
1615
  // src/prompt-context.ts
1614
- function buildDiscordMessageContextPrompt(userMessage, options) {
1615
- const contextEntries = [
1616
- ["scope", options.scope],
1617
- ["sent_at", options.sentAt],
1618
- ["sent_at_local", options.sentAtLocal],
1619
- ["message_id", options.messageId],
1620
- ["author_name", normalizeContextValue(options.authorName)],
1621
- ["author_id", options.authorId],
1622
- ["thread_title", normalizeContextValue(options.threadTitle)],
1623
- ["thread_id", options.threadId],
1624
- ["forum_channel_id", options.forumChannelId ?? undefined]
1625
- ].filter((entry) => {
1626
- return typeof entry[1] === "string" && entry[1].trim().length > 0;
1627
- });
1628
- const contextJson = JSON.stringify(Object.fromEntries(contextEntries), null, 2);
1629
- return [
1630
- wrapXmlTag("discord_message_context", contextJson),
1631
- "",
1632
- wrapXmlTag("user_message", userMessage.trim())
1633
- ].join(`
1634
- `);
1635
- }
1636
1616
  function formatDiscordPromptTime(date, options = {}) {
1637
1617
  const timeZone = options.timeZone || "UTC";
1638
1618
  const locale = options.locale || "en-AU";
@@ -1651,41 +1631,35 @@ function formatDiscordPromptTime(date, options = {}) {
1651
1631
  function wrapXmlTag(tag, content) {
1652
1632
  return `<${tag}>${content}</${tag}>`;
1653
1633
  }
1654
- function normalizeContextValue(value) {
1655
- if (value === undefined) {
1656
- return;
1657
- }
1658
- return value.replace(/\s+/g, " ").trim();
1659
- }
1660
1634
 
1661
1635
  // src/discord-message-handler.ts
1662
1636
  var logger12 = createModuleLogger("discord-message-handler");
1663
- function buildPromptTransformContext(message, scope, content, config) {
1637
+ function formatDiscordMessageMetadata(message, scope) {
1664
1638
  const isThread = scope.startsWith("thread:") && message.channel.isThread();
1665
- const sentAtLocal = formatDiscordPromptTime(message.createdAt, {
1666
- timeZone: config.promptTimeZone,
1667
- locale: config.promptLocale
1639
+ const contextEntries = [
1640
+ ["scope", scope === "dm" ? "dm" : "thread"],
1641
+ ["sent_at", message.createdAt.toISOString()],
1642
+ ["sent_at_local", formatDiscordPromptTime(message.createdAt)],
1643
+ ["message_id", message.id],
1644
+ [
1645
+ "author_name",
1646
+ getAuthorDisplayName(message).replace(/\s+/g, " ").trim() || undefined
1647
+ ],
1648
+ ["author_id", message.author.id],
1649
+ [
1650
+ "thread_title",
1651
+ isThread ? (message.channel.name ?? "").replace(/\s+/g, " ").trim() : undefined
1652
+ ],
1653
+ ["thread_id", isThread ? message.channel.id : undefined],
1654
+ [
1655
+ "forum_channel_id",
1656
+ isThread ? message.channel.parentId ?? undefined : undefined
1657
+ ]
1658
+ ].filter((entry) => {
1659
+ return typeof entry[1] === "string" && entry[1].length > 0;
1668
1660
  });
1669
- return {
1670
- rawContent: content,
1671
- now: () => `<datetime>${sentAtLocal}</datetime>`,
1672
- wrapWithDiscordContext: () => {
1673
- return buildDiscordMessageContextPrompt(content, {
1674
- scope: scope === "dm" ? "dm" : "thread",
1675
- sentAt: message.createdAt.toISOString(),
1676
- sentAtLocal: formatDiscordPromptTime(message.createdAt, {
1677
- timeZone: config.promptTimeZone,
1678
- locale: config.promptLocale
1679
- }),
1680
- messageId: message.id,
1681
- authorId: message.author.id,
1682
- authorName: getAuthorDisplayName(message),
1683
- threadId: isThread ? message.channel.id : undefined,
1684
- threadTitle: isThread ? message.channel.name : undefined,
1685
- forumChannelId: isThread ? message.channel.parentId : undefined
1686
- });
1687
- }
1688
- };
1661
+ const contextJson = JSON.stringify(Object.fromEntries(contextEntries), null, 2);
1662
+ return `<discord_message_context>${contextJson}</discord_message_context>`;
1689
1663
  }
1690
1664
  async function handleDiscordMessage(message, config, agentService, sessionRegistry, accessConfig) {
1691
1665
  if (message.author.bot) {
@@ -1809,8 +1783,16 @@ ${commandResult.response ?? "Archiving..."}
1809
1783
  promptImages = resolvedPromptMedia.images;
1810
1784
  }
1811
1785
  }
1812
- const transformCtx = buildPromptTransformContext(message, scope, promptContent, config);
1813
- const transformedPrompt = await config.promptTransform(transformCtx);
1786
+ const discordMetadata = formatDiscordMessageMetadata(message, scope);
1787
+ const transformedPrompt = await config.promptTransform({
1788
+ rawContent: promptContent,
1789
+ discordMetadata,
1790
+ now: () => wrapXmlTag("datetime", formatDiscordPromptTime(new Date, {
1791
+ timeZone: config.promptTimeZone,
1792
+ locale: config.promptLocale
1793
+ })),
1794
+ userMessage: () => wrapXmlTag("user_message", promptContent)
1795
+ });
1814
1796
  return runAgentTurn(session, transformedPrompt, {
1815
1797
  images: promptImages
1816
1798
  });
@@ -1930,6 +1912,5 @@ export {
1930
1912
  startDiscordGateway,
1931
1913
  resolveConfig,
1932
1914
  loadDiscordGatewayConfigFromEnv,
1933
- formatDiscordPromptTime,
1934
- buildDiscordMessageContextPrompt
1915
+ formatDiscordPromptTime
1935
1916
  };
@@ -2,17 +2,6 @@ export type DiscordPromptTimeFormatOptions = {
2
2
  timeZone?: string;
3
3
  locale?: string;
4
4
  };
5
- export type DiscordPromptScope = "dm" | "thread";
6
- export type DiscordMessageContextPromptOptions = {
7
- scope: DiscordPromptScope;
8
- messageId: string;
9
- authorId: string;
10
- sentAt?: string;
11
- sentAtLocal?: string;
12
- authorName?: string;
13
- threadId?: string;
14
- threadTitle?: string;
15
- forumChannelId?: string | null;
16
- };
17
- export declare function buildDiscordMessageContextPrompt(userMessage: string, options: DiscordMessageContextPromptOptions): string;
18
5
  export declare function formatDiscordPromptTime(date: Date, options?: DiscordPromptTimeFormatOptions): string;
6
+ /** Wrap content in an XML-style tag: `<tag>content</tag>`. */
7
+ export declare function wrapXmlTag(tag: string, content: string): string;
package/dist/types.d.ts CHANGED
@@ -2,14 +2,15 @@ import type { Client } from "discord.js";
2
2
  /** Context object passed to promptTransform so consumers can optionally
3
3
  * wrap the raw content with Discord metadata. */
4
4
  export type PromptTransformContext = {
5
- /** The raw user content without any Discord context wrapping. */
5
+ /** The raw user content without any XML wrapping. */
6
6
  rawContent: string;
7
- /** Returns the message timestamp formatted using the gateway config's
8
- * promptTimeZone and promptLocale. */
7
+ /** XML string with Discord message metadata (context JSON block). */
8
+ discordMetadata: string;
9
+ /** Returns current datetime formatted using the gateway config's
10
+ * promptTimeZone and promptLocale, wrapped in a <datetime> tag. */
9
11
  now: () => string;
10
- /** Wraps the raw content with Discord message metadata (scope, author,
11
- * timestamps, thread info). Returns the traditional wrapped prompt. */
12
- wrapWithDiscordContext: () => string;
12
+ /** Returns rawContent wrapped in a <user_message> tag. */
13
+ userMessage: () => string;
13
14
  };
14
15
  export type PromptTransform = (ctx: PromptTransformContext) => string | Promise<string>;
15
16
  export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@friendlyrobot/discord-pi-agent",
3
- "version": "0.21.0",
3
+ "version": "0.21.1",
4
4
  "description": "Reusable Discord gateway for persistent pi agent sessions",
5
5
  "license": "MIT",
6
6
  "type": "module",