@ubiquity-os/plugin-sdk 3.3.4 → 3.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.mts CHANGED
@@ -129,11 +129,13 @@ interface Options$1 {
129
129
  bypassSignatureVerification?: boolean;
130
130
  returnDataToKernel?: boolean;
131
131
  }
132
+ /**
133
+ * Removes wrapper backticks or fenced blocks that LLMs often return around payloads.
134
+ */
135
+ declare function sanitizeLlmResponse(input: string): string;
132
136
 
133
137
  declare function createActionsPlugin<TConfig = unknown, TEnv = unknown, TCommand = unknown, TSupportedEvents extends EmitterWebhookEventName = EmitterWebhookEventName>(handler: (context: Context<TConfig, TEnv, TCommand, TSupportedEvents>) => HandlerReturn, options?: Options$1): Promise<void>;
134
138
 
135
- declare function createPlugin<TConfig = unknown, TEnv = unknown, TCommand = unknown, TSupportedEvents extends EmitterWebhookEventName = EmitterWebhookEventName>(handler: (context: Context<TConfig, TEnv, TCommand, TSupportedEvents>) => HandlerReturn, manifest: Manifest, options?: Options$1): Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
136
-
137
139
  /**
138
140
  * Options for cleanMarkdown.
139
141
  *
@@ -164,4 +166,6 @@ type Options = {
164
166
  */
165
167
  declare function cleanMarkdown(md: string, options?: Options): string;
166
168
 
167
- export { CommentHandler, type Context, type Options$1 as Options, cleanMarkdown, createActionsPlugin, createPlugin };
169
+ declare function createPlugin<TConfig = unknown, TEnv = unknown, TCommand = unknown, TSupportedEvents extends EmitterWebhookEventName = EmitterWebhookEventName>(handler: (context: Context<TConfig, TEnv, TCommand, TSupportedEvents>) => HandlerReturn, manifest: Manifest, options?: Options$1): Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
170
+
171
+ export { CommentHandler, type Context, type Options$1 as Options, cleanMarkdown, createActionsPlugin, createPlugin, sanitizeLlmResponse };
package/dist/index.d.ts CHANGED
@@ -129,11 +129,13 @@ interface Options$1 {
129
129
  bypassSignatureVerification?: boolean;
130
130
  returnDataToKernel?: boolean;
131
131
  }
132
+ /**
133
+ * Removes wrapper backticks or fenced blocks that LLMs often return around payloads.
134
+ */
135
+ declare function sanitizeLlmResponse(input: string): string;
132
136
 
133
137
  declare function createActionsPlugin<TConfig = unknown, TEnv = unknown, TCommand = unknown, TSupportedEvents extends EmitterWebhookEventName = EmitterWebhookEventName>(handler: (context: Context<TConfig, TEnv, TCommand, TSupportedEvents>) => HandlerReturn, options?: Options$1): Promise<void>;
134
138
 
135
- declare function createPlugin<TConfig = unknown, TEnv = unknown, TCommand = unknown, TSupportedEvents extends EmitterWebhookEventName = EmitterWebhookEventName>(handler: (context: Context<TConfig, TEnv, TCommand, TSupportedEvents>) => HandlerReturn, manifest: Manifest, options?: Options$1): Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
136
-
137
139
  /**
138
140
  * Options for cleanMarkdown.
139
141
  *
@@ -164,4 +166,6 @@ type Options = {
164
166
  */
165
167
  declare function cleanMarkdown(md: string, options?: Options): string;
166
168
 
167
- export { CommentHandler, type Context, type Options$1 as Options, cleanMarkdown, createActionsPlugin, createPlugin };
169
+ declare function createPlugin<TConfig = unknown, TEnv = unknown, TCommand = unknown, TSupportedEvents extends EmitterWebhookEventName = EmitterWebhookEventName>(handler: (context: Context<TConfig, TEnv, TCommand, TSupportedEvents>) => HandlerReturn, manifest: Manifest, options?: Options$1): Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
170
+
171
+ export { CommentHandler, type Context, type Options$1 as Options, cleanMarkdown, createActionsPlugin, createPlugin, sanitizeLlmResponse };
package/dist/index.js CHANGED
@@ -33,7 +33,8 @@ __export(src_exports, {
33
33
  CommentHandler: () => CommentHandler,
34
34
  cleanMarkdown: () => cleanMarkdown,
35
35
  createActionsPlugin: () => createActionsPlugin,
36
- createPlugin: () => createPlugin
36
+ createPlugin: () => createPlugin,
37
+ sanitizeLlmResponse: () => sanitizeLlmResponse
37
38
  });
38
39
  module.exports = __toCommonJS(src_exports);
39
40
 
@@ -156,6 +157,24 @@ JQIDAQAB
156
157
  function sanitizeMetadata(obj) {
157
158
  return JSON.stringify(obj, null, 2).replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/--/g, "&#45;&#45;");
158
159
  }
160
+ function sanitizeLlmResponse(input) {
161
+ const trimmed = input.trim();
162
+ if (!trimmed) {
163
+ return trimmed;
164
+ }
165
+ if (trimmed.startsWith("```")) {
166
+ let result = trimmed.replace(/^```[a-z0-9+-]*\s*(?:\r\n|\n)?/i, "");
167
+ if (result.endsWith("```")) {
168
+ result = result.slice(0, -3);
169
+ result = result.replace(/[\r\n]+$/, "");
170
+ }
171
+ return result.trim();
172
+ }
173
+ if (trimmed.startsWith("`") && trimmed.endsWith("`")) {
174
+ return trimmed.slice(1, -1).trim();
175
+ }
176
+ return trimmed;
177
+ }
159
178
  function getPluginOptions(options) {
160
179
  return {
161
180
  // Important to use || and not ?? to not consider empty strings
@@ -553,6 +572,59 @@ async function returnDataToKernel(repoToken, stateId, output) {
553
572
  });
554
573
  }
555
574
 
575
+ // src/markdown.ts
576
+ var VOID_TAGS = /* @__PURE__ */ new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]);
577
+ function cleanMarkdown(md, options = {}) {
578
+ const codeBlockRegex = /(```[\s\S]*?```|~~~[\s\S]*?~~~)/g;
579
+ const { tags = [], shouldCollapseEmptyLines = false } = options;
580
+ const segments = [];
581
+ let lastIndex = 0;
582
+ const matches = [...md.matchAll(codeBlockRegex)];
583
+ for (const match of matches) {
584
+ if (match.index > lastIndex) {
585
+ segments.push(processSegment(md.slice(lastIndex, match.index), tags, shouldCollapseEmptyLines));
586
+ }
587
+ segments.push(match[0]);
588
+ lastIndex = match.index + match[0].length;
589
+ }
590
+ if (lastIndex < md.length) {
591
+ segments.push(processSegment(md.slice(lastIndex), tags, shouldCollapseEmptyLines));
592
+ }
593
+ return segments.join("");
594
+ }
595
+ function processSegment(segment, extraTags, shouldCollapseEmptyLines) {
596
+ const inlineCodeRegex = /`[^`]*`/g;
597
+ const inlineCodes = [];
598
+ let s = segment.replace(inlineCodeRegex, (m) => {
599
+ inlineCodes.push(m);
600
+ return `__INLINE_CODE_${inlineCodes.length - 1}__`;
601
+ });
602
+ s = s.replace(/<!--[\s\S]*?-->/g, "");
603
+ for (const raw of extraTags) {
604
+ if (!raw) continue;
605
+ const tag = raw.toLowerCase().trim().replace(/[^\w:-]/g, "");
606
+ if (!tag) continue;
607
+ if (VOID_TAGS.has(tag)) {
608
+ const voidRe = new RegExp(`<${tag}\\b[^>]*\\/?>`, "gi");
609
+ s = s.replace(voidRe, "");
610
+ continue;
611
+ }
612
+ const pairRe = new RegExp(`<${tag}\\b[^>]*>[\\s\\S]*?<\\/${tag}>`, "gi");
613
+ let prev;
614
+ do {
615
+ prev = s;
616
+ s = s.replace(pairRe, "");
617
+ } while (s !== prev);
618
+ const openCloseRe = new RegExp(`<\\/?${tag}\\b[^>]*>`, "gi");
619
+ s = s.replace(openCloseRe, "");
620
+ }
621
+ s = s.replace(/__INLINE_CODE_(\d+)__/g, (str, idx) => inlineCodes[+idx]);
622
+ if (shouldCollapseEmptyLines) {
623
+ s = s.replace(/[ \t]+$/gm, "").replace(/\n{3,}/g, "\n\n");
624
+ }
625
+ return s;
626
+ }
627
+
556
628
  // src/server.ts
557
629
  var import_value4 = require("@sinclair/typebox/value");
558
630
  var import_ubiquity_os_logger4 = require("@ubiquity-os/ubiquity-os-logger");
@@ -633,63 +705,11 @@ function createPlugin(handler, manifest, options) {
633
705
  });
634
706
  return app;
635
707
  }
636
-
637
- // src/markdown.ts
638
- var VOID_TAGS = /* @__PURE__ */ new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]);
639
- function cleanMarkdown(md, options = {}) {
640
- const codeBlockRegex = /(```[\s\S]*?```|~~~[\s\S]*?~~~)/g;
641
- const { tags = [], shouldCollapseEmptyLines = false } = options;
642
- const segments = [];
643
- let lastIndex = 0;
644
- const matches = [...md.matchAll(codeBlockRegex)];
645
- for (const match of matches) {
646
- if (match.index > lastIndex) {
647
- segments.push(processSegment(md.slice(lastIndex, match.index), tags, shouldCollapseEmptyLines));
648
- }
649
- segments.push(match[0]);
650
- lastIndex = match.index + match[0].length;
651
- }
652
- if (lastIndex < md.length) {
653
- segments.push(processSegment(md.slice(lastIndex), tags, shouldCollapseEmptyLines));
654
- }
655
- return segments.join("");
656
- }
657
- function processSegment(segment, extraTags, shouldCollapseEmptyLines) {
658
- const inlineCodeRegex = /`[^`]*`/g;
659
- const inlineCodes = [];
660
- let s = segment.replace(inlineCodeRegex, (m) => {
661
- inlineCodes.push(m);
662
- return `__INLINE_CODE_${inlineCodes.length - 1}__`;
663
- });
664
- s = s.replace(/<!--[\s\S]*?-->/g, "");
665
- for (const raw of extraTags) {
666
- if (!raw) continue;
667
- const tag = raw.toLowerCase().trim().replace(/[^\w:-]/g, "");
668
- if (!tag) continue;
669
- if (VOID_TAGS.has(tag)) {
670
- const voidRe = new RegExp(`<${tag}\\b[^>]*\\/?>`, "gi");
671
- s = s.replace(voidRe, "");
672
- continue;
673
- }
674
- const pairRe = new RegExp(`<${tag}\\b[^>]*>[\\s\\S]*?<\\/${tag}>`, "gi");
675
- let prev;
676
- do {
677
- prev = s;
678
- s = s.replace(pairRe, "");
679
- } while (s !== prev);
680
- const openCloseRe = new RegExp(`<\\/?${tag}\\b[^>]*>`, "gi");
681
- s = s.replace(openCloseRe, "");
682
- }
683
- s = s.replace(/__INLINE_CODE_(\d+)__/g, (str, idx) => inlineCodes[+idx]);
684
- if (shouldCollapseEmptyLines) {
685
- s = s.replace(/[ \t]+$/gm, "").replace(/\n{3,}/g, "\n\n");
686
- }
687
- return s;
688
- }
689
708
  // Annotate the CommonJS export names for ESM import in node:
690
709
  0 && (module.exports = {
691
710
  CommentHandler,
692
711
  cleanMarkdown,
693
712
  createActionsPlugin,
694
- createPlugin
713
+ createPlugin,
714
+ sanitizeLlmResponse
695
715
  });
package/dist/index.mjs CHANGED
@@ -117,6 +117,24 @@ JQIDAQAB
117
117
  function sanitizeMetadata(obj) {
118
118
  return JSON.stringify(obj, null, 2).replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/--/g, "&#45;&#45;");
119
119
  }
120
+ function sanitizeLlmResponse(input) {
121
+ const trimmed = input.trim();
122
+ if (!trimmed) {
123
+ return trimmed;
124
+ }
125
+ if (trimmed.startsWith("```")) {
126
+ let result = trimmed.replace(/^```[a-z0-9+-]*\s*(?:\r\n|\n)?/i, "");
127
+ if (result.endsWith("```")) {
128
+ result = result.slice(0, -3);
129
+ result = result.replace(/[\r\n]+$/, "");
130
+ }
131
+ return result.trim();
132
+ }
133
+ if (trimmed.startsWith("`") && trimmed.endsWith("`")) {
134
+ return trimmed.slice(1, -1).trim();
135
+ }
136
+ return trimmed;
137
+ }
120
138
  function getPluginOptions(options) {
121
139
  return {
122
140
  // Important to use || and not ?? to not consider empty strings
@@ -514,6 +532,59 @@ async function returnDataToKernel(repoToken, stateId, output) {
514
532
  });
515
533
  }
516
534
 
535
+ // src/markdown.ts
536
+ var VOID_TAGS = /* @__PURE__ */ new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]);
537
+ function cleanMarkdown(md, options = {}) {
538
+ const codeBlockRegex = /(```[\s\S]*?```|~~~[\s\S]*?~~~)/g;
539
+ const { tags = [], shouldCollapseEmptyLines = false } = options;
540
+ const segments = [];
541
+ let lastIndex = 0;
542
+ const matches = [...md.matchAll(codeBlockRegex)];
543
+ for (const match of matches) {
544
+ if (match.index > lastIndex) {
545
+ segments.push(processSegment(md.slice(lastIndex, match.index), tags, shouldCollapseEmptyLines));
546
+ }
547
+ segments.push(match[0]);
548
+ lastIndex = match.index + match[0].length;
549
+ }
550
+ if (lastIndex < md.length) {
551
+ segments.push(processSegment(md.slice(lastIndex), tags, shouldCollapseEmptyLines));
552
+ }
553
+ return segments.join("");
554
+ }
555
+ function processSegment(segment, extraTags, shouldCollapseEmptyLines) {
556
+ const inlineCodeRegex = /`[^`]*`/g;
557
+ const inlineCodes = [];
558
+ let s = segment.replace(inlineCodeRegex, (m) => {
559
+ inlineCodes.push(m);
560
+ return `__INLINE_CODE_${inlineCodes.length - 1}__`;
561
+ });
562
+ s = s.replace(/<!--[\s\S]*?-->/g, "");
563
+ for (const raw of extraTags) {
564
+ if (!raw) continue;
565
+ const tag = raw.toLowerCase().trim().replace(/[^\w:-]/g, "");
566
+ if (!tag) continue;
567
+ if (VOID_TAGS.has(tag)) {
568
+ const voidRe = new RegExp(`<${tag}\\b[^>]*\\/?>`, "gi");
569
+ s = s.replace(voidRe, "");
570
+ continue;
571
+ }
572
+ const pairRe = new RegExp(`<${tag}\\b[^>]*>[\\s\\S]*?<\\/${tag}>`, "gi");
573
+ let prev;
574
+ do {
575
+ prev = s;
576
+ s = s.replace(pairRe, "");
577
+ } while (s !== prev);
578
+ const openCloseRe = new RegExp(`<\\/?${tag}\\b[^>]*>`, "gi");
579
+ s = s.replace(openCloseRe, "");
580
+ }
581
+ s = s.replace(/__INLINE_CODE_(\d+)__/g, (str, idx) => inlineCodes[+idx]);
582
+ if (shouldCollapseEmptyLines) {
583
+ s = s.replace(/[ \t]+$/gm, "").replace(/\n{3,}/g, "\n\n");
584
+ }
585
+ return s;
586
+ }
587
+
517
588
  // src/server.ts
518
589
  import { Value as Value4 } from "@sinclair/typebox/value";
519
590
  import { Logs as Logs2 } from "@ubiquity-os/ubiquity-os-logger";
@@ -594,62 +665,10 @@ function createPlugin(handler, manifest, options) {
594
665
  });
595
666
  return app;
596
667
  }
597
-
598
- // src/markdown.ts
599
- var VOID_TAGS = /* @__PURE__ */ new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]);
600
- function cleanMarkdown(md, options = {}) {
601
- const codeBlockRegex = /(```[\s\S]*?```|~~~[\s\S]*?~~~)/g;
602
- const { tags = [], shouldCollapseEmptyLines = false } = options;
603
- const segments = [];
604
- let lastIndex = 0;
605
- const matches = [...md.matchAll(codeBlockRegex)];
606
- for (const match of matches) {
607
- if (match.index > lastIndex) {
608
- segments.push(processSegment(md.slice(lastIndex, match.index), tags, shouldCollapseEmptyLines));
609
- }
610
- segments.push(match[0]);
611
- lastIndex = match.index + match[0].length;
612
- }
613
- if (lastIndex < md.length) {
614
- segments.push(processSegment(md.slice(lastIndex), tags, shouldCollapseEmptyLines));
615
- }
616
- return segments.join("");
617
- }
618
- function processSegment(segment, extraTags, shouldCollapseEmptyLines) {
619
- const inlineCodeRegex = /`[^`]*`/g;
620
- const inlineCodes = [];
621
- let s = segment.replace(inlineCodeRegex, (m) => {
622
- inlineCodes.push(m);
623
- return `__INLINE_CODE_${inlineCodes.length - 1}__`;
624
- });
625
- s = s.replace(/<!--[\s\S]*?-->/g, "");
626
- for (const raw of extraTags) {
627
- if (!raw) continue;
628
- const tag = raw.toLowerCase().trim().replace(/[^\w:-]/g, "");
629
- if (!tag) continue;
630
- if (VOID_TAGS.has(tag)) {
631
- const voidRe = new RegExp(`<${tag}\\b[^>]*\\/?>`, "gi");
632
- s = s.replace(voidRe, "");
633
- continue;
634
- }
635
- const pairRe = new RegExp(`<${tag}\\b[^>]*>[\\s\\S]*?<\\/${tag}>`, "gi");
636
- let prev;
637
- do {
638
- prev = s;
639
- s = s.replace(pairRe, "");
640
- } while (s !== prev);
641
- const openCloseRe = new RegExp(`<\\/?${tag}\\b[^>]*>`, "gi");
642
- s = s.replace(openCloseRe, "");
643
- }
644
- s = s.replace(/__INLINE_CODE_(\d+)__/g, (str, idx) => inlineCodes[+idx]);
645
- if (shouldCollapseEmptyLines) {
646
- s = s.replace(/[ \t]+$/gm, "").replace(/\n{3,}/g, "\n\n");
647
- }
648
- return s;
649
- }
650
668
  export {
651
669
  CommentHandler,
652
670
  cleanMarkdown,
653
671
  createActionsPlugin,
654
- createPlugin
672
+ createPlugin,
673
+ sanitizeLlmResponse
655
674
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ubiquity-os/plugin-sdk",
3
- "version": "3.3.4",
3
+ "version": "3.4.0",
4
4
  "description": "SDK for plugin support.",
5
5
  "author": "Ubiquity DAO",
6
6
  "license": "MIT",