@friendlyrobot/discord-pi-agent 0.3.18 → 0.4.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.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { DiscordPiBridge, DiscordPiBridgeConfig } from "./types";
2
2
  export { buildTimeContextPrompt, type TimeContextPromptOptions, } from "./prompt-context";
3
+ export { transformMarkdownTablesToCodeBlocks, transformMarkdownTablesSync, } from "./markdown-table-transformer";
3
4
  export { loadDiscordPiBridgeConfigFromEnv, resolveConfig } from "./config";
4
5
  export type { AgentStatus, DiscordPiBridge, DiscordPiBridgeConfig, PromptTransform, ResolvedDiscordPiBridgeConfig, } from "./types";
5
6
  export declare function startDiscordPiBridge(config: DiscordPiBridgeConfig): Promise<DiscordPiBridge>;
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ import { createRequire } from "node:module";
2
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
+
1
4
  // src/agent-service.ts
2
5
  import fs from "node:fs/promises";
3
6
  import path from "node:path";
@@ -10,6 +13,85 @@ import {
10
13
  SettingsManager
11
14
  } from "@mariozechner/pi-coding-agent";
12
15
 
16
+ // src/markdown-table-transformer.ts
17
+ var TABLE_BLOCK_REGEX = /(\|.+?(?:\|.*)+)(\n\|[-:]+(?:\|[-:]+)+\|?)(\n\|.+?(?:\|.*)+\|?)+/g;
18
+ var CODE_BLOCK_WRAPPER = "```\n{TABLE}\n```";
19
+ async function transformMarkdownTablesToCodeBlocks(text) {
20
+ const matches = [...text.matchAll(TABLE_BLOCK_REGEX)];
21
+ if (matches.length === 0) {
22
+ return text;
23
+ }
24
+ const formattedTables = await Promise.all(matches.map((match) => formatTableWithPrettier(match[0])));
25
+ let result = text;
26
+ for (let i = 0;i < matches.length; i++) {
27
+ const match = matches[i];
28
+ const originalTable = match[0];
29
+ const formattedTable = formattedTables[i];
30
+ const wrappedTable = CODE_BLOCK_WRAPPER.replace("{TABLE}", formattedTable);
31
+ result = result.replace(originalTable, wrappedTable);
32
+ }
33
+ return result;
34
+ }
35
+ function parseMarkdownTable(table) {
36
+ const lines = table.trim().split(`
37
+ `);
38
+ return lines.map((line) => {
39
+ return line.split("|").filter((cell) => cell.trim() !== "").map((cell) => cell.trim());
40
+ });
41
+ }
42
+ async function formatTableWithPrettier(table) {
43
+ const prettier = await import("prettier");
44
+ try {
45
+ const formatted = await prettier.format(table, {
46
+ parser: "markdown",
47
+ printWidth: 80
48
+ });
49
+ return formatted.trim();
50
+ } catch {
51
+ return formatTableManually(table);
52
+ }
53
+ }
54
+ function formatTableManually(table) {
55
+ const rows = parseMarkdownTable(table);
56
+ if (rows.length === 0) {
57
+ return table;
58
+ }
59
+ const columnCount = Math.max(...rows.map((row) => row.length));
60
+ const columnWidths = Array(columnCount).fill(0);
61
+ for (const row of rows) {
62
+ for (let i = 0;i < row.length; i++) {
63
+ columnWidths[i] = Math.max(columnWidths[i], row[i].length);
64
+ }
65
+ }
66
+ const formattedRows = rows.map((row, rowIndex) => {
67
+ const paddedCells = row.map((cell, colIndex) => {
68
+ const width = columnWidths[colIndex];
69
+ return padCell(cell, width);
70
+ });
71
+ return "| " + paddedCells.join(" | ") + " |";
72
+ });
73
+ if (formattedRows.length > 1) {
74
+ const separatorCells = columnWidths.map((width) => {
75
+ return "-".repeat(width);
76
+ });
77
+ const separator = "| " + separatorCells.join(" | ") + " |";
78
+ formattedRows.splice(1, 0, separator);
79
+ }
80
+ return formattedRows.join(`
81
+ `);
82
+ }
83
+ function padCell(value, width) {
84
+ if (value.length >= width) {
85
+ return value;
86
+ }
87
+ return value + " ".repeat(width - value.length);
88
+ }
89
+ function transformMarkdownTablesSync(text) {
90
+ return text.replace(TABLE_BLOCK_REGEX, (tableMatch) => {
91
+ return CODE_BLOCK_WRAPPER.replace("{TABLE}", tableMatch.trim());
92
+ });
93
+ }
94
+
13
95
  // src/reply-buffer.ts
14
96
  async function collectReply(session, prompt, options = {}) {
15
97
  const logPrefix = options.logPrefix ?? "[agent]";
@@ -67,7 +149,8 @@ async function collectReply(session, prompt, options = {}) {
67
149
  return errorMessage;
68
150
  }
69
151
  if (finalText) {
70
- return finalText;
152
+ const transformed = await transformMarkdownTablesToCodeBlocks(finalText);
153
+ return transformed;
71
154
  }
72
155
  return "No response generated.";
73
156
  }
@@ -756,6 +839,8 @@ function registerSignalHandlers(stop) {
756
839
  });
757
840
  }
758
841
  export {
842
+ transformMarkdownTablesToCodeBlocks,
843
+ transformMarkdownTablesSync,
759
844
  startDiscordPiBridge,
760
845
  resolveConfig,
761
846
  loadDiscordPiBridgeConfigFromEnv,
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Transforms markdown tables into Discord-friendly code blocks.
3
+ * Discord doesn't support markdown tables natively, so we:
4
+ * 1. Detect markdown tables in the text
5
+ * 2. Wrap them in triple backticks
6
+ * 3. Use Prettier to format the table with proper column alignment
7
+ */
8
+ /**
9
+ * Transforms markdown tables in the text to Discord-friendly code blocks.
10
+ * Tables are detected by their markdown syntax and wrapped in triple backticks.
11
+ * Table contents are formatted with Prettier for proper column alignment.
12
+ */
13
+ export declare function transformMarkdownTablesToCodeBlocks(text: string): Promise<string>;
14
+ /**
15
+ * Synchronous version that wraps tables in code blocks but skips Prettier formatting.
16
+ * Useful when you want quick transformation without async overhead.
17
+ */
18
+ export declare function transformMarkdownTablesSync(text: string): string;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@friendlyrobot/discord-pi-agent",
3
- "version": "0.3.18",
3
+ "version": "0.4.0",
4
4
  "description": "Reusable Discord gateway bridge for persistent pi agent sessions",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -27,7 +27,7 @@
27
27
  "scripts": {
28
28
  "test:watch": "vitest",
29
29
  "test": "vitest run",
30
- "update-deps": "bun add @mariozechner/pi-ai@latest @mariozechner/pi-coding-agent@latest discord.js@latest dotenv@latest; bun add -d @types/node@latest prettier@latest typescript@latest vitest@latest @vitest/ui@latest",
30
+ "update-deps": "bun add @mariozechner/pi-ai@latest @mariozechner/pi-coding-agent@latest discord.js@latest dotenv@latest prettier@latest; bun add -d @types/node@latest typescript@latest vitest@latest @vitest/ui@latest",
31
31
  "format": "prettier --write .",
32
32
  "build": "rm -rf dist && bun build ./src/index.ts --outdir ./dist --target node --format esm --packages external && tsc -p tsconfig.json --emitDeclarationOnly --declaration --declarationMap false",
33
33
  "typecheck": "tsc --noEmit -p tsconfig.json"
@@ -36,12 +36,12 @@
36
36
  "@mariozechner/pi-ai": "^0.70.0",
37
37
  "@mariozechner/pi-coding-agent": "^0.70.0",
38
38
  "discord.js": "^14.26.3",
39
- "dotenv": "^17.4.2"
39
+ "dotenv": "^17.4.2",
40
+ "prettier": "^3.8.3"
40
41
  },
41
42
  "devDependencies": {
42
43
  "@types/node": "^25.6.0",
43
44
  "@vitest/ui": "^4.1.5",
44
- "prettier": "^3.8.3",
45
45
  "typescript": "^6.0.3",
46
46
  "vitest": "^4.1.5"
47
47
  }