@hmawla/co-assistant 1.0.6 → 1.0.8

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/cli/index.js CHANGED
@@ -976,6 +976,7 @@ var init_plugin_health = __esm({
976
976
  var message_exports = {};
977
977
  __export(message_exports, {
978
978
  createMessageHandler: () => createMessageHandler,
979
+ safeSendMarkdown: () => safeSendMarkdown,
979
980
  splitMessage: () => splitMessage
980
981
  });
981
982
  function splitMessage(text, maxLength = 4096) {
@@ -1001,6 +1002,19 @@ function splitMessage(text, maxLength = 4096) {
1001
1002
  }
1002
1003
  return chunks.filter((c) => c.length > 0);
1003
1004
  }
1005
+ async function safeSendMarkdown(sendFn, text, extra = {}) {
1006
+ try {
1007
+ await sendFn(text, { parse_mode: "Markdown", ...extra });
1008
+ } catch (err) {
1009
+ const msg = err instanceof Error ? err.message : String(err);
1010
+ if (msg.includes("can't parse entities")) {
1011
+ const plain = text.replace(/[*_`]/g, "");
1012
+ await sendFn(plain, extra);
1013
+ } else {
1014
+ throw err;
1015
+ }
1016
+ }
1017
+ }
1004
1018
  function createMessageHandler(deps) {
1005
1019
  const { sessionManager: sessionManager2, conversationRepo } = deps;
1006
1020
  return async (ctx, text) => {
@@ -1692,8 +1706,20 @@ function createPluginRegistry(pluginsDir) {
1692
1706
  init_logger();
1693
1707
  import path3 from "path";
1694
1708
  import { existsSync as existsSync4, statSync as statSync2 } from "fs";
1695
- import { pathToFileURL } from "url";
1709
+ import { fileURLToPath, pathToFileURL } from "url";
1696
1710
  var pluginLogger = createChildLogger("plugins:manager");
1711
+ function findNodeModules() {
1712
+ const thisFile = fileURLToPath(import.meta.url);
1713
+ let dir = path3.dirname(thisFile);
1714
+ for (let i = 0; i < 10; i++) {
1715
+ const candidate = path3.join(dir, "node_modules");
1716
+ if (existsSync4(candidate)) return candidate;
1717
+ const parent = path3.dirname(dir);
1718
+ if (parent === dir) break;
1719
+ dir = parent;
1720
+ }
1721
+ return null;
1722
+ }
1697
1723
  async function compilePlugin(tsEntryPath) {
1698
1724
  const outfile = tsEntryPath.replace(/\.ts$/, ".compiled.mjs");
1699
1725
  const pluginDir = path3.dirname(tsEntryPath);
@@ -1709,6 +1735,7 @@ async function compilePlugin(tsEntryPath) {
1709
1735
  }
1710
1736
  }
1711
1737
  pluginLogger.debug({ tsEntryPath, outfile }, "Compiling plugin with esbuild");
1738
+ const pkgNodeModules = findNodeModules();
1712
1739
  const esbuild = await import("esbuild");
1713
1740
  await esbuild.build({
1714
1741
  entryPoints: [tsEntryPath],
@@ -1717,9 +1744,11 @@ async function compilePlugin(tsEntryPath) {
1717
1744
  platform: "node",
1718
1745
  target: "node20",
1719
1746
  outfile,
1720
- // Externalize all bare-specifier packages (node_modules) but bundle
1721
- // local relative imports (./auth.js ./auth.ts, ./tools.js, etc.)
1722
- packages: "external",
1747
+ // Bundle EVERYTHING including node_modules packages — so the
1748
+ // compiled plugin is fully self-contained and works regardless of
1749
+ // which directory the user runs co-assistant from.
1750
+ // esbuild's nodePaths lets us find the package's own deps.
1751
+ nodePaths: pkgNodeModules ? [pkgNodeModules] : [],
1723
1752
  logLevel: "warning"
1724
1753
  });
1725
1754
  pluginLogger.debug({ outfile }, "Plugin compiled successfully");
@@ -1845,15 +1874,15 @@ var PluginManager = class {
1845
1874
  }
1846
1875
  const plugin = factory();
1847
1876
  const context = this.buildPluginContext(pluginId, creds);
1848
- const initResult = await this.sandbox.safeExecute(
1877
+ await this.sandbox.safeExecute(
1849
1878
  pluginId,
1850
1879
  "initialize",
1851
1880
  () => plugin.initialize(context)
1852
1881
  );
1853
- if (initResult === void 0 && manifest.requiredCredentials.length > 0) {
1882
+ if (this.sandbox.getFailureCount(pluginId) > 0) {
1854
1883
  this.logger.warn(
1855
1884
  { pluginId },
1856
- `Plugin "${pluginId}" initialize() did not succeed \u2014 marking as error`
1885
+ `Plugin "${pluginId}" initialize() failed \u2014 check credentials and plugin health`
1857
1886
  );
1858
1887
  }
1859
1888
  this.plugins.set(pluginId, plugin);
@@ -3194,7 +3223,11 @@ ${state.processedIds.map((id) => `- ${id}`).join("\n")}` : "No previously proces
3194
3223
  `;
3195
3224
  const chunks = splitMessage(header + clean);
3196
3225
  for (const chunk of chunks) {
3197
- await ctx.reply(chunk, { parse_mode: "Markdown", ...replyOpts });
3226
+ await safeSendMarkdown(
3227
+ (text, extra) => ctx.reply(text, extra),
3228
+ chunk,
3229
+ replyOpts
3230
+ );
3198
3231
  }
3199
3232
  }
3200
3233
  } catch (err) {
@@ -3285,7 +3318,10 @@ ${state.processedIds.map((id) => `- ${id}`).join("\n")}` : "No previously proces
3285
3318
  const fullMessage = header + response;
3286
3319
  const chunks = splitMessage(fullMessage);
3287
3320
  for (const chunk of chunks) {
3288
- await bot.getBot().telegram.sendMessage(chatId, chunk, { parse_mode: "Markdown" });
3321
+ await safeSendMarkdown(
3322
+ (text, extra) => bot.getBot().telegram.sendMessage(chatId, text, extra),
3323
+ chunk
3324
+ );
3289
3325
  }
3290
3326
  } catch (err) {
3291
3327
  this.logger.error({ err, eventName }, "Failed to send heartbeat response via Telegram");
@@ -4016,9 +4052,9 @@ import {
4016
4052
  cpSync
4017
4053
  } from "fs";
4018
4054
  import path4 from "path";
4019
- import { fileURLToPath } from "url";
4055
+ import { fileURLToPath as fileURLToPath2 } from "url";
4020
4056
  function getPackagePluginsDir() {
4021
- const thisFile = fileURLToPath(import.meta.url);
4057
+ const thisFile = fileURLToPath2(import.meta.url);
4022
4058
  const pkgRoot = path4.resolve(path4.dirname(thisFile), "..", "..", "..");
4023
4059
  const pluginsDir = path4.join(pkgRoot, "plugins");
4024
4060
  if (!existsSync7(pluginsDir)) {
@@ -4317,7 +4353,10 @@ async function handleInstall(pluginId, options) {
4317
4353
  skipped++;
4318
4354
  continue;
4319
4355
  }
4320
- cpSync(plugin.sourcePath, destDir, { recursive: true });
4356
+ cpSync(plugin.sourcePath, destDir, {
4357
+ recursive: true,
4358
+ filter: (src) => !src.endsWith(".compiled.mjs")
4359
+ });
4321
4360
  console.log(` \u2705 ${plugin.id} \u2014 installed to plugins/${plugin.id}/`);
4322
4361
  installed++;
4323
4362
  }
@@ -4563,7 +4602,7 @@ function registerHeartbeatCommand(program2) {
4563
4602
  const { getConfig: getConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
4564
4603
  const { copilotClient: copilotClient2 } = await Promise.resolve().then(() => (init_client(), client_exports));
4565
4604
  const { sessionManager: sessionManager2 } = await Promise.resolve().then(() => (init_session(), session_exports));
4566
- const { splitMessage: splitMessage2 } = await Promise.resolve().then(() => (init_message(), message_exports));
4605
+ const { splitMessage: splitMessage2, safeSendMarkdown: safeSendMarkdown2 } = await Promise.resolve().then(() => (init_message(), message_exports));
4567
4606
  let config;
4568
4607
  try {
4569
4608
  config = getConfig2();
@@ -4654,7 +4693,10 @@ ${state.processedIds.map((id) => `- ${id}`).join("\n")}` : "No previously proces
4654
4693
  `;
4655
4694
  const chunks = splitMessage2(header + cleanResponse);
4656
4695
  for (const chunk of chunks) {
4657
- await telegram.sendMessage(chatId, chunk, { parse_mode: "Markdown" });
4696
+ await safeSendMarkdown2(
4697
+ (text, extra) => telegram.sendMessage(chatId, text, extra),
4698
+ chunk
4699
+ );
4658
4700
  }
4659
4701
  console.log(" \u2713 Sent to Telegram");
4660
4702
  } catch (err) {