@credal/actions 0.2.202 → 0.2.205

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.
@@ -0,0 +1,125 @@
1
+ const JIRA_MENTION_SOURCE = "\\[~accountid:([^\\]]+)\\]";
2
+ const JIRA_MENTION_TEST = new RegExp(JIRA_MENTION_SOURCE);
3
+ const PLACEHOLDER_PREFIX = "\uFFFCMENTION_";
4
+ const PLACEHOLDER_SUFFIX = "\uFFFC";
5
+ /**
6
+ * Extracts [~accountid:XXXXX] patterns from raw text and replaces them with
7
+ * safe placeholders that won't be mangled by markdown parsers.
8
+ *
9
+ * Use with {@link insertMentionNodes} after markdown-to-ADF conversion.
10
+ */
11
+ export function extractMentions(text) {
12
+ const mentions = [];
13
+ const sanitized = text.replace(new RegExp(JIRA_MENTION_SOURCE, "g"), (_match, id) => {
14
+ const index = mentions.length;
15
+ mentions.push(id);
16
+ return `${PLACEHOLDER_PREFIX}${index}${PLACEHOLDER_SUFFIX}`;
17
+ });
18
+ return { sanitized, mentions };
19
+ }
20
+ /**
21
+ * Walks an ADF tree and replaces placeholder tokens (produced by
22
+ * {@link extractMentions}) with proper ADF mention nodes.
23
+ */
24
+ export function insertMentionNodes(adf, mentions) {
25
+ if (mentions.length === 0)
26
+ return adf;
27
+ const placeholderRegex = new RegExp(`${escapeRegex(PLACEHOLDER_PREFIX)}(\\d+)${escapeRegex(PLACEHOLDER_SUFFIX)}`);
28
+ return walkAndReplace(adf, placeholderRegex, mentions);
29
+ }
30
+ /**
31
+ * Walks an ADF tree and converts raw [~accountid:XXXXX] text patterns into
32
+ * ADF mention nodes. Works reliably for single mentions per paragraph; for
33
+ * multiple mentions use extractMentions + insertMentionNodes instead.
34
+ */
35
+ export function convertMentionsInAdf(adf) {
36
+ if (!adf || typeof adf !== "object")
37
+ return adf;
38
+ if (Array.isArray(adf))
39
+ return adf.flatMap(item => {
40
+ const result = convertMentionsInAdf(item);
41
+ return Array.isArray(result) ? result : [result];
42
+ });
43
+ const node = adf;
44
+ if (node.type === "text" && typeof node.text === "string" && JIRA_MENTION_TEST.test(node.text)) {
45
+ return splitTextNodeWithMentions(node, new RegExp(JIRA_MENTION_SOURCE, "g"), (_match, groups) => groups[0]);
46
+ }
47
+ if (Array.isArray(node.content)) {
48
+ const newContent = [];
49
+ for (const child of node.content) {
50
+ const result = convertMentionsInAdf(child);
51
+ if (Array.isArray(result)) {
52
+ newContent.push(...result);
53
+ }
54
+ else {
55
+ newContent.push(result);
56
+ }
57
+ }
58
+ return { ...node, content: newContent };
59
+ }
60
+ return node;
61
+ }
62
+ // ---------------------------------------------------------------------------
63
+ // Internal helpers
64
+ // ---------------------------------------------------------------------------
65
+ function walkAndReplace(adf, regex, mentions) {
66
+ if (!adf || typeof adf !== "object")
67
+ return adf;
68
+ if (Array.isArray(adf))
69
+ return adf.flatMap(item => {
70
+ const result = walkAndReplace(item, regex, mentions);
71
+ return Array.isArray(result) ? result : [result];
72
+ });
73
+ const node = adf;
74
+ if (node.type === "text" && typeof node.text === "string" && regex.test(node.text)) {
75
+ return splitTextNodeWithMentions(node, new RegExp(`${escapeRegex(PLACEHOLDER_PREFIX)}(\\d+)${escapeRegex(PLACEHOLDER_SUFFIX)}`, "g"), (_match, groups) => mentions[parseInt(groups[0], 10)]);
76
+ }
77
+ if (Array.isArray(node.content)) {
78
+ const newContent = [];
79
+ for (const child of node.content) {
80
+ const result = walkAndReplace(child, regex, mentions);
81
+ if (Array.isArray(result)) {
82
+ newContent.push(...result);
83
+ }
84
+ else {
85
+ newContent.push(result);
86
+ }
87
+ }
88
+ return { ...node, content: newContent };
89
+ }
90
+ return node;
91
+ }
92
+ function splitTextNodeWithMentions(node, regex, resolveId) {
93
+ const text = node.text;
94
+ const marks = node.marks;
95
+ const results = [];
96
+ let lastIndex = 0;
97
+ let match;
98
+ while ((match = regex.exec(text)) !== null) {
99
+ if (match.index > lastIndex) {
100
+ const textNode = { type: "text", text: text.slice(lastIndex, match.index) };
101
+ if (marks)
102
+ textNode.marks = marks;
103
+ results.push(textNode);
104
+ }
105
+ results.push({
106
+ type: "mention",
107
+ attrs: {
108
+ id: resolveId(match[0], match.slice(1)),
109
+ text: `@${resolveId(match[0], match.slice(1))}`,
110
+ accessLevel: "",
111
+ },
112
+ });
113
+ lastIndex = match.index + match[0].length;
114
+ }
115
+ if (lastIndex < text.length) {
116
+ const textNode = { type: "text", text: text.slice(lastIndex) };
117
+ if (marks)
118
+ textNode.marks = marks;
119
+ results.push(textNode);
120
+ }
121
+ return results;
122
+ }
123
+ function escapeRegex(str) {
124
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
125
+ }
@@ -70,5 +70,5 @@ export declare function getUserInfoFromAccountId(accountId: string | undefined,
70
70
  name: string | undefined;
71
71
  email: string | undefined;
72
72
  } | null>;
73
+ export { convertMentionsInAdf } from "./convertMentionsInAdf.js";
73
74
  export declare function extractPlainText(adf: unknown): string;
74
- export {};
@@ -200,6 +200,7 @@ export async function getUserInfoFromAccountId(accountId, client) {
200
200
  return null;
201
201
  }
202
202
  }
203
+ export { convertMentionsInAdf } from "./convertMentionsInAdf.js";
203
204
  export function extractPlainText(adf) {
204
205
  if (!adf || typeof adf !== "object")
205
206
  return "";
@@ -0,0 +1,3 @@
1
+ import type { linearCreateIssueFunction } from "../../autogen/types";
2
+ declare const createIssue: linearCreateIssueFunction;
3
+ export default createIssue;
@@ -0,0 +1,90 @@
1
+ const createIssue = async ({ params, authParams, }) => {
2
+ const { authToken } = authParams;
3
+ const { title, description, teamId, assigneeId, priority, projectId, dueDate, labelIds, estimate } = params;
4
+ if (!authToken) {
5
+ throw new Error("Valid auth token is required to create a Linear issue");
6
+ }
7
+ const mutation = `
8
+ mutation CreateIssue($input: IssueCreateInput!) {
9
+ issueCreate(input: $input) {
10
+ success
11
+ issue {
12
+ id
13
+ title
14
+ url
15
+ identifier
16
+ }
17
+ }
18
+ }
19
+ `;
20
+ const input = {
21
+ title,
22
+ teamId,
23
+ };
24
+ if (description !== undefined) {
25
+ input.description = description;
26
+ }
27
+ if (assigneeId !== undefined) {
28
+ input.assigneeId = assigneeId;
29
+ }
30
+ if (priority !== undefined) {
31
+ input.priority = priority;
32
+ }
33
+ if (projectId !== undefined) {
34
+ input.projectId = projectId;
35
+ }
36
+ if (dueDate !== undefined) {
37
+ input.dueDate = dueDate;
38
+ }
39
+ if (labelIds !== undefined) {
40
+ input.labelIds = labelIds;
41
+ }
42
+ if (estimate !== undefined) {
43
+ input.estimate = estimate;
44
+ }
45
+ try {
46
+ const response = await fetch("https://api.linear.app/graphql", {
47
+ method: "POST",
48
+ headers: {
49
+ "Content-Type": "application/json",
50
+ Authorization: `Bearer ${authToken}`,
51
+ },
52
+ body: JSON.stringify({
53
+ query: mutation,
54
+ variables: { input },
55
+ }),
56
+ });
57
+ if (!response.ok) {
58
+ const errorText = await response.text();
59
+ throw new Error(`HTTP error: status: ${response.status}, body: ${errorText}`);
60
+ }
61
+ const data = await response.json();
62
+ if (data.errors) {
63
+ throw new Error(`GraphQL errors: ${JSON.stringify(data.errors)}`);
64
+ }
65
+ const result = data.data?.issueCreate;
66
+ if (!result?.success) {
67
+ return {
68
+ success: false,
69
+ error: "Failed to create issue",
70
+ };
71
+ }
72
+ return {
73
+ success: true,
74
+ issue: {
75
+ id: result.issue.id,
76
+ title: result.issue.title,
77
+ url: result.issue.url,
78
+ identifier: result.issue.identifier,
79
+ },
80
+ };
81
+ }
82
+ catch (error) {
83
+ console.error("Error creating Linear issue: ", error);
84
+ return {
85
+ success: false,
86
+ error: error instanceof Error ? error.message : "Unknown error",
87
+ };
88
+ }
89
+ };
90
+ export default createIssue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@credal/actions",
3
- "version": "0.2.202",
3
+ "version": "0.2.205",
4
4
  "type": "module",
5
5
  "description": "AI Actions by Credal AI",
6
6
  "sideEffects": false,
@@ -51,6 +51,7 @@
51
51
  "typescript-eslint": "^8.56.0"
52
52
  },
53
53
  "dependencies": {
54
+ "@googleapis/docs": "^9.2.1",
54
55
  "@mendable/firecrawl-js": "^4.3.4",
55
56
  "@microsoft/microsoft-graph-client": "^3.0.7",
56
57
  "@octokit/core": "^6.1.6",
@@ -69,6 +70,7 @@
69
70
  "jsonwebtoken": "^9.0.2",
70
71
  "limiter": "^3.0.0",
71
72
  "mammoth": "^1.11.00",
73
+ "marked": "^16.3.0",
72
74
  "marklassian": "^1.1.0",
73
75
  "mongodb": "^6.13.1",
74
76
  "node-forge": "^1.3.3",