@cremini/skillpack 1.0.8 → 1.0.9-im.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/README.md +3 -1
- package/dist/cli.js +45 -11
- package/package.json +3 -2
- package/runtime/server/dist/adapters/markdown.js +74 -0
- package/runtime/server/dist/adapters/markdown.js.map +1 -0
- package/runtime/server/dist/adapters/slack.js +369 -0
- package/runtime/server/dist/adapters/slack.js.map +1 -0
- package/runtime/server/dist/adapters/telegram.js +199 -0
- package/runtime/server/dist/adapters/telegram.js.map +1 -0
- package/runtime/server/dist/adapters/types.js +2 -0
- package/runtime/server/dist/adapters/types.js.map +1 -0
- package/runtime/server/dist/adapters/web.js +168 -0
- package/runtime/server/dist/adapters/web.js.map +1 -0
- package/runtime/server/dist/agent.js +219 -0
- package/runtime/server/dist/agent.js.map +1 -0
- package/runtime/server/dist/config.js +73 -0
- package/runtime/server/dist/config.js.map +1 -0
- package/runtime/server/dist/index.js +122 -0
- package/runtime/server/dist/index.js.map +1 -0
- package/runtime/server/package-lock.json +2768 -121
- package/runtime/server/package.json +13 -3
- package/runtime/start.bat +2 -2
- package/runtime/start.sh +1 -1
- package/runtime/web/index.html +58 -15
- package/runtime/web/js/api.js +13 -0
- package/runtime/web/{app.js → js/chat.js} +126 -193
- package/runtime/web/js/config.js +15 -0
- package/runtime/web/js/main.js +47 -0
- package/runtime/web/js/settings.js +132 -0
- package/runtime/web/styles.css +171 -0
- package/runtime/server/chat-proxy.js +0 -161
- package/runtime/server/index.js +0 -63
- package/runtime/server/routes.js +0 -104
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# SkillPack.sh - Pack AI Skills into Standalone Apps
|
|
2
2
|
|
|
3
|
+
Skillpack by Cremini is built on the idea of distributed intelligence, much like cremini mushrooms that grow from a vast, interconnected mycelial network.
|
|
4
|
+
|
|
3
5
|
Go to [skillpack.sh](https://skillpack.sh) to pack skills and try existing skill packs.
|
|
4
6
|
|
|
5
|
-
One command to orchestrate [Skills](https://skills.sh), tools, mcps into a standalone app users can download and use on their own computer!
|
|
7
|
+
One command to orchestrate [Skills](https://skills.sh), tools, mcps into a standalone app users can download and use on their own computer to address a well-defined problem or complete specific tasks!
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
10
|
npx @cremini/skillpack create
|
package/dist/cli.js
CHANGED
|
@@ -342,6 +342,10 @@ function collectRuntimeTemplateEntries(runtimeDir) {
|
|
|
342
342
|
if (dirEntry.name === "node_modules") {
|
|
343
343
|
continue;
|
|
344
344
|
}
|
|
345
|
+
const currentRelative = relativeDir ? path3.posix.join(relativeDir, dirEntry.name) : dirEntry.name;
|
|
346
|
+
if (currentRelative === "server/src" || currentRelative === "server/tsconfig.json") {
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
345
349
|
const absolutePath = path3.join(currentDir, dirEntry.name);
|
|
346
350
|
const relativePath = relativeDir ? path3.posix.join(relativeDir, dirEntry.name) : dirEntry.name;
|
|
347
351
|
const stats = fs3.statSync(absolutePath);
|
|
@@ -450,6 +454,25 @@ async function bundle(workDir) {
|
|
|
450
454
|
function parseSkillNames(value) {
|
|
451
455
|
return value.split(",").map((name) => name.trim()).filter(Boolean);
|
|
452
456
|
}
|
|
457
|
+
function normalizeSourceInput(value) {
|
|
458
|
+
return value.trim().replace(/^npx\s+skills\s+add\s+/u, "");
|
|
459
|
+
}
|
|
460
|
+
function parseSourceInput(value) {
|
|
461
|
+
const trimmedValue = normalizeSourceInput(value);
|
|
462
|
+
const skillFlagIndex = trimmedValue.indexOf(" --skill ");
|
|
463
|
+
if (skillFlagIndex === -1) {
|
|
464
|
+
return {
|
|
465
|
+
source: trimmedValue,
|
|
466
|
+
inlineSkillNames: []
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
const source = trimmedValue.slice(0, skillFlagIndex).trim();
|
|
470
|
+
const inlineSkillValue = trimmedValue.slice(skillFlagIndex + " --skill ".length).trim();
|
|
471
|
+
return {
|
|
472
|
+
source,
|
|
473
|
+
inlineSkillNames: inlineSkillValue.split(/[,\s]+/).map((name) => name.trim()).filter(Boolean)
|
|
474
|
+
};
|
|
475
|
+
}
|
|
453
476
|
async function createCommand(directory) {
|
|
454
477
|
const workDir = directory ? path5.resolve(directory) : process.cwd();
|
|
455
478
|
if (directory) {
|
|
@@ -493,7 +516,10 @@ async function createCommand(directory) {
|
|
|
493
516
|
chalk3.dim(" Supported formats: owner/repo, GitHub URL, or local path")
|
|
494
517
|
);
|
|
495
518
|
console.log(chalk3.dim(" Example source: vercel-labs/agent-skills"));
|
|
496
|
-
console.log(
|
|
519
|
+
console.log(
|
|
520
|
+
chalk3.dim(" Example inline skill: vercel-labs/agent-skills --skill find-skills")
|
|
521
|
+
);
|
|
522
|
+
console.log();
|
|
497
523
|
while (true) {
|
|
498
524
|
const { source } = await inquirer.prompt([
|
|
499
525
|
{
|
|
@@ -505,16 +531,24 @@ async function createCommand(directory) {
|
|
|
505
531
|
if (!source.trim()) {
|
|
506
532
|
break;
|
|
507
533
|
}
|
|
508
|
-
const
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
534
|
+
const parsedSource = parseSourceInput(source);
|
|
535
|
+
let skillNames = parsedSource.inlineSkillNames;
|
|
536
|
+
if (skillNames.length === 0) {
|
|
537
|
+
console.log(
|
|
538
|
+
chalk3.dim(" Example skill names: frontend-design, skill-creator")
|
|
539
|
+
);
|
|
540
|
+
const promptResult = await inquirer.prompt([
|
|
541
|
+
{
|
|
542
|
+
type: "input",
|
|
543
|
+
name: "skillNames",
|
|
544
|
+
message: "Skill names (comma-separated):",
|
|
545
|
+
validate: (value) => parseSkillNames(value).length > 0 ? true : "Enter at least one skill name"
|
|
546
|
+
}
|
|
547
|
+
]);
|
|
548
|
+
skillNames = parseSkillNames(promptResult.skillNames);
|
|
549
|
+
}
|
|
550
|
+
const nextSkills = skillNames.map((skillName) => ({
|
|
551
|
+
source: parsedSource.source,
|
|
518
552
|
name: skillName,
|
|
519
553
|
description: ""
|
|
520
554
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cremini/skillpack",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9-im.1",
|
|
4
4
|
"description": "Turn Skills into a Standalone App with UI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"node": ">=20"
|
|
25
25
|
},
|
|
26
26
|
"scripts": {
|
|
27
|
-
"build": "tsup",
|
|
27
|
+
"build": "npm run build:runtime && tsup",
|
|
28
|
+
"build:runtime": "cd runtime/server && npx tsc",
|
|
28
29
|
"dev": "tsup --watch",
|
|
29
30
|
"check": "tsc --noEmit",
|
|
30
31
|
"format": "prettier --write .",
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const MARKDOWN_SOURCE_BLOCK_RE = /```(?:md|markdown)\s*\n([\s\S]*?)```/gi;
|
|
2
|
+
const FENCED_CODE_BLOCK_RE = /```[^\n]*\n[\s\S]*?```/g;
|
|
3
|
+
const INLINE_CODE_RE = /`([^`\n]+)`/g;
|
|
4
|
+
const LINK_RE = /\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g;
|
|
5
|
+
const PLACEHOLDER_START = "\uE000";
|
|
6
|
+
const PLACEHOLDER_END = "\uE001";
|
|
7
|
+
function unwrapMarkdownSourceBlocks(text) {
|
|
8
|
+
return text.replace(MARKDOWN_SOURCE_BLOCK_RE, (_, content) => content.trim());
|
|
9
|
+
}
|
|
10
|
+
function escapeHtml(text) {
|
|
11
|
+
return text
|
|
12
|
+
.replace(/&/g, "&")
|
|
13
|
+
.replace(/</g, "<")
|
|
14
|
+
.replace(/>/g, ">");
|
|
15
|
+
}
|
|
16
|
+
function escapeHtmlAttribute(text) {
|
|
17
|
+
return escapeHtml(text).replace(/"/g, """);
|
|
18
|
+
}
|
|
19
|
+
function protect(text, pattern, placeholders, render) {
|
|
20
|
+
const nextText = text.replace(pattern, (...args) => {
|
|
21
|
+
const match = args[0];
|
|
22
|
+
const groups = args.slice(1, -2);
|
|
23
|
+
const token = `${PLACEHOLDER_START}${placeholders.length}${PLACEHOLDER_END}`;
|
|
24
|
+
placeholders.push(render(match, ...groups));
|
|
25
|
+
return token;
|
|
26
|
+
});
|
|
27
|
+
return nextText;
|
|
28
|
+
}
|
|
29
|
+
function restore(text, placeholders) {
|
|
30
|
+
return text.replace(new RegExp(`${PLACEHOLDER_START}(\\d+)${PLACEHOLDER_END}`, "g"), (_, index) => placeholders[Number(index)] ?? "");
|
|
31
|
+
}
|
|
32
|
+
function formatSlackInline(text) {
|
|
33
|
+
let formatted = text;
|
|
34
|
+
formatted = formatted.replace(LINK_RE, (_, label, url) => {
|
|
35
|
+
return `<${url}|${label}>`;
|
|
36
|
+
});
|
|
37
|
+
formatted = formatted.replace(/^(#{1,6})[ \t]+(.+)$/gm, (_, __, content) => `*${content.trim()}*`);
|
|
38
|
+
formatted = formatted.replace(/\*\*([^*\n]+)\*\*/g, "*$1*");
|
|
39
|
+
formatted = formatted.replace(/__([^_\n]+)__/g, "*$1*");
|
|
40
|
+
return formatted;
|
|
41
|
+
}
|
|
42
|
+
function formatTelegramInline(text) {
|
|
43
|
+
let formatted = escapeHtml(text);
|
|
44
|
+
formatted = formatted.replace(LINK_RE, (_, label, url) => {
|
|
45
|
+
return `<a href="${escapeHtmlAttribute(url)}">${escapeHtml(label)}</a>`;
|
|
46
|
+
});
|
|
47
|
+
formatted = formatted.replace(/^(#{1,6})[ \t]+(.+)$/gm, (_, __, content) => `<b>${content.trim()}</b>`);
|
|
48
|
+
formatted = formatted.replace(/\*\*([^*\n]+)\*\*/g, "<b>$1</b>");
|
|
49
|
+
formatted = formatted.replace(/__([^_\n]+)__/g, "<b>$1</b>");
|
|
50
|
+
formatted = formatted.replace(/(^|[^\w<])\*([^*\n]+)\*(?=[^\w>]|$)/g, "$1<i>$2</i>");
|
|
51
|
+
formatted = formatted.replace(/(^|[^\w<])_([^_\n]+)_(?=[^\w>]|$)/g, "$1<i>$2</i>");
|
|
52
|
+
formatted = formatted.replace(/^(?:-|\*) /gm, "• ");
|
|
53
|
+
return formatted;
|
|
54
|
+
}
|
|
55
|
+
export function formatSlackMessage(text) {
|
|
56
|
+
const unwrapped = unwrapMarkdownSourceBlocks(text);
|
|
57
|
+
const placeholders = [];
|
|
58
|
+
const withFenced = protect(unwrapped, FENCED_CODE_BLOCK_RE, placeholders, (block) => block);
|
|
59
|
+
const withInline = protect(withFenced, INLINE_CODE_RE, placeholders, (_match, code) => `\`${code}\``);
|
|
60
|
+
return restore(formatSlackInline(withInline), placeholders);
|
|
61
|
+
}
|
|
62
|
+
export function formatTelegramMessage(text) {
|
|
63
|
+
const unwrapped = unwrapMarkdownSourceBlocks(text);
|
|
64
|
+
const placeholders = [];
|
|
65
|
+
const withFenced = protect(unwrapped, FENCED_CODE_BLOCK_RE, placeholders, (block) => {
|
|
66
|
+
const content = block
|
|
67
|
+
.replace(/^```[^\n]*\n/, "")
|
|
68
|
+
.replace(/\n```$/, "");
|
|
69
|
+
return `<pre><code>${escapeHtml(content)}</code></pre>`;
|
|
70
|
+
});
|
|
71
|
+
const withInline = protect(withFenced, INLINE_CODE_RE, placeholders, (_match, code) => `<code>${escapeHtml(code)}</code>`);
|
|
72
|
+
return restore(formatTelegramInline(withInline), placeholders);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/adapters/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
import { App, LogLevel } from "@slack/bolt";
|
|
2
|
+
import { formatSlackMessage } from "./markdown.js";
|
|
3
|
+
const INLINE_COMMANDS = {
|
|
4
|
+
"/clear": "clear",
|
|
5
|
+
"/restart": "restart",
|
|
6
|
+
"/shutdown": "shutdown",
|
|
7
|
+
};
|
|
8
|
+
const SLASH_COMMANDS = {
|
|
9
|
+
"/skillpack-clear": "clear",
|
|
10
|
+
"/skillpack-restart": "restart",
|
|
11
|
+
"/skillpack-shutdown": "shutdown",
|
|
12
|
+
};
|
|
13
|
+
const MAX_MESSAGE_LENGTH = 3500;
|
|
14
|
+
const ACK_REACTION = "eyes";
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// SlackAdapter
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
export class SlackAdapter {
|
|
19
|
+
name = "slack";
|
|
20
|
+
app = null;
|
|
21
|
+
agent = null;
|
|
22
|
+
options;
|
|
23
|
+
botUserId = null;
|
|
24
|
+
lastThreadByChannel = new Map();
|
|
25
|
+
constructor(options) {
|
|
26
|
+
this.options = options;
|
|
27
|
+
}
|
|
28
|
+
async start(ctx) {
|
|
29
|
+
this.agent = ctx.agent;
|
|
30
|
+
this.app = new App({
|
|
31
|
+
token: this.options.botToken,
|
|
32
|
+
appToken: this.options.appToken,
|
|
33
|
+
socketMode: true,
|
|
34
|
+
ignoreSelf: true,
|
|
35
|
+
logLevel: LogLevel.INFO,
|
|
36
|
+
});
|
|
37
|
+
const auth = await this.app.client.auth.test({
|
|
38
|
+
token: this.options.botToken,
|
|
39
|
+
});
|
|
40
|
+
this.botUserId =
|
|
41
|
+
typeof auth.user_id === "string" ? auth.user_id : null;
|
|
42
|
+
this.registerListeners(this.app);
|
|
43
|
+
await this.app.start();
|
|
44
|
+
const identity = this.botUserId ? `<@${this.botUserId}>` : "Slack bot";
|
|
45
|
+
console.log(`[SlackAdapter] Started as ${identity}`);
|
|
46
|
+
}
|
|
47
|
+
async stop() {
|
|
48
|
+
if (this.app) {
|
|
49
|
+
await this.app.stop();
|
|
50
|
+
this.app = null;
|
|
51
|
+
}
|
|
52
|
+
console.log("[SlackAdapter] Stopped");
|
|
53
|
+
}
|
|
54
|
+
// -------------------------------------------------------------------------
|
|
55
|
+
// Listener registration
|
|
56
|
+
// -------------------------------------------------------------------------
|
|
57
|
+
registerListeners(app) {
|
|
58
|
+
app.event("message", async (args) => {
|
|
59
|
+
try {
|
|
60
|
+
await this.handleDirectMessage(args);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
console.error("[Slack] Error handling DM:", err);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
app.event("app_mention", async (args) => {
|
|
67
|
+
try {
|
|
68
|
+
await this.handleMention(args);
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
console.error("[Slack] Error handling mention:", err);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
for (const commandName of Object.keys(SLASH_COMMANDS)) {
|
|
75
|
+
app.command(commandName, async (args) => {
|
|
76
|
+
try {
|
|
77
|
+
await this.handleSlashCommand(args);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
console.error(`[Slack] Error handling ${commandName}:`, err);
|
|
81
|
+
await this.safeAck(args.ack, `❌ Error: ${this.getErrorMessage(err)}`);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// -------------------------------------------------------------------------
|
|
87
|
+
// Event handlers
|
|
88
|
+
// -------------------------------------------------------------------------
|
|
89
|
+
async handleDirectMessage({ event, body, context, client, }) {
|
|
90
|
+
if (!this.agent || !this.isSupportedDmEvent(event)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const text = (event.text || "").trim();
|
|
94
|
+
if (!text)
|
|
95
|
+
return;
|
|
96
|
+
const teamId = this.getTeamId(body, context);
|
|
97
|
+
const channelId = `slack-dm-${teamId}-${event.channel}`;
|
|
98
|
+
const route = { channel: event.channel };
|
|
99
|
+
await this.tryAckReaction(client, event);
|
|
100
|
+
if (await this.tryHandleInlineCommand(text, channelId, client, route)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
await this.runAgent(channelId, text, client, route);
|
|
104
|
+
}
|
|
105
|
+
async handleMention({ event, body, context, client, }) {
|
|
106
|
+
if (!this.agent || !this.isSupportedMentionEvent(event)) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const teamId = this.getTeamId(body, context);
|
|
110
|
+
const threadTs = event.thread_ts || event.ts;
|
|
111
|
+
const channelId = `slack-thread-${teamId}-${event.channel}-${threadTs}`;
|
|
112
|
+
const route = {
|
|
113
|
+
channel: event.channel,
|
|
114
|
+
threadTs,
|
|
115
|
+
};
|
|
116
|
+
this.lastThreadByChannel.set(this.getChannelKey(teamId, event.channel), threadTs);
|
|
117
|
+
const text = this.stripBotMention(event.text || "").trim();
|
|
118
|
+
if (!text) {
|
|
119
|
+
await this.sendSafe(client, route, "Mention me with a message, or use `/clear` to reset this thread.");
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
await this.tryAckReaction(client, event);
|
|
123
|
+
if (await this.tryHandleInlineCommand(text, channelId, client, route)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
await this.runAgent(channelId, text, client, route);
|
|
127
|
+
}
|
|
128
|
+
async handleSlashCommand({ command, body, context, ack, }) {
|
|
129
|
+
const commandName = command?.command;
|
|
130
|
+
const mapped = commandName ? SLASH_COMMANDS[commandName] : undefined;
|
|
131
|
+
if (!this.agent || !mapped) {
|
|
132
|
+
await this.safeAck(ack, "Unsupported slash command.");
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const resolved = this.resolveSlashCommandTarget(body || command, context);
|
|
136
|
+
if (!resolved.channelId) {
|
|
137
|
+
await this.safeAck(ack, resolved.message);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const result = await this.agent.handleCommand(mapped, resolved.channelId);
|
|
141
|
+
const parts = [result.message || `${commandName} executed.`];
|
|
142
|
+
if (resolved.note) {
|
|
143
|
+
parts.push(resolved.note);
|
|
144
|
+
}
|
|
145
|
+
await this.safeAck(ack, parts.join("\n"));
|
|
146
|
+
}
|
|
147
|
+
// -------------------------------------------------------------------------
|
|
148
|
+
// Agent bridge
|
|
149
|
+
// -------------------------------------------------------------------------
|
|
150
|
+
async runAgent(channelId, text, client, route) {
|
|
151
|
+
if (!this.agent)
|
|
152
|
+
return;
|
|
153
|
+
let finalText = "";
|
|
154
|
+
let hasError = false;
|
|
155
|
+
let errorMessage = "";
|
|
156
|
+
const onEvent = (event) => {
|
|
157
|
+
if (event.type === "text_delta") {
|
|
158
|
+
finalText += event.delta;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
try {
|
|
162
|
+
const result = await this.agent.handleMessage(channelId, text, onEvent);
|
|
163
|
+
if (result.errorMessage) {
|
|
164
|
+
hasError = true;
|
|
165
|
+
errorMessage = result.errorMessage;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
hasError = true;
|
|
170
|
+
errorMessage = this.getErrorMessage(err);
|
|
171
|
+
}
|
|
172
|
+
if (hasError) {
|
|
173
|
+
await this.sendSafe(client, route, `❌ Error: ${errorMessage}`);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (!finalText.trim()) {
|
|
177
|
+
await this.sendSafe(client, route, "(No response generated)");
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
await this.sendLongMessage(client, route, finalText);
|
|
181
|
+
}
|
|
182
|
+
// -------------------------------------------------------------------------
|
|
183
|
+
// Helpers
|
|
184
|
+
// -------------------------------------------------------------------------
|
|
185
|
+
async tryHandleInlineCommand(text, channelId, client, route) {
|
|
186
|
+
if (!this.agent)
|
|
187
|
+
return false;
|
|
188
|
+
const commandKey = text.split(/\s/)[0].toLowerCase();
|
|
189
|
+
const command = INLINE_COMMANDS[commandKey];
|
|
190
|
+
if (!command)
|
|
191
|
+
return false;
|
|
192
|
+
const result = await this.agent.handleCommand(command, channelId);
|
|
193
|
+
await this.sendSafe(client, route, result.message || `${commandKey} executed.`);
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
resolveSlashCommandTarget(payload, context) {
|
|
197
|
+
const teamId = this.getTeamId(payload, context);
|
|
198
|
+
const channel = payload?.channel_id;
|
|
199
|
+
if (!channel) {
|
|
200
|
+
return { message: "Missing Slack channel context." };
|
|
201
|
+
}
|
|
202
|
+
if (this.isDmChannelId(channel)) {
|
|
203
|
+
return {
|
|
204
|
+
channelId: `slack-dm-${teamId}-${channel}`,
|
|
205
|
+
message: "",
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const threadTs = this.lastThreadByChannel.get(this.getChannelKey(teamId, channel));
|
|
209
|
+
if (!threadTs) {
|
|
210
|
+
return {
|
|
211
|
+
message: "No active Skillpack thread found in this channel. Mention the bot first, or run the command inside the thread as `@bot /clear`.",
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
channelId: `slack-thread-${teamId}-${channel}-${threadTs}`,
|
|
216
|
+
message: "",
|
|
217
|
+
note: "Applied to the most recent active Skillpack thread in this channel.",
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
isSupportedDmEvent(event) {
|
|
221
|
+
if (!event || event.type !== "message")
|
|
222
|
+
return false;
|
|
223
|
+
if (event.channel_type !== "im")
|
|
224
|
+
return false;
|
|
225
|
+
if (event.subtype)
|
|
226
|
+
return false;
|
|
227
|
+
if (event.bot_id)
|
|
228
|
+
return false;
|
|
229
|
+
if (!event.user || typeof event.text !== "string")
|
|
230
|
+
return false;
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
isSupportedMentionEvent(event) {
|
|
234
|
+
if (!event || event.type !== "app_mention")
|
|
235
|
+
return false;
|
|
236
|
+
if (event.subtype)
|
|
237
|
+
return false;
|
|
238
|
+
if (event.bot_id)
|
|
239
|
+
return false;
|
|
240
|
+
if (!event.user || typeof event.text !== "string")
|
|
241
|
+
return false;
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
stripBotMention(text) {
|
|
245
|
+
const mention = this.botUserId
|
|
246
|
+
? new RegExp(`^\\s*<@${this.escapeRegExp(this.botUserId)}>\\s*`)
|
|
247
|
+
: /^\s*<@[^>]+>\s*/;
|
|
248
|
+
return text.replace(mention, "");
|
|
249
|
+
}
|
|
250
|
+
splitMessage(text) {
|
|
251
|
+
if (text.length <= MAX_MESSAGE_LENGTH) {
|
|
252
|
+
return [text];
|
|
253
|
+
}
|
|
254
|
+
const chunks = [];
|
|
255
|
+
let remaining = text;
|
|
256
|
+
while (remaining.length > 0) {
|
|
257
|
+
if (remaining.length <= MAX_MESSAGE_LENGTH) {
|
|
258
|
+
chunks.push(remaining);
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
let splitAt = remaining.lastIndexOf("\n\n", MAX_MESSAGE_LENGTH);
|
|
262
|
+
if (splitAt < MAX_MESSAGE_LENGTH * 0.5) {
|
|
263
|
+
splitAt = remaining.lastIndexOf("\n", MAX_MESSAGE_LENGTH);
|
|
264
|
+
}
|
|
265
|
+
if (splitAt < MAX_MESSAGE_LENGTH * 0.3) {
|
|
266
|
+
splitAt = remaining.lastIndexOf(" ", MAX_MESSAGE_LENGTH);
|
|
267
|
+
}
|
|
268
|
+
if (splitAt < 1) {
|
|
269
|
+
splitAt = MAX_MESSAGE_LENGTH;
|
|
270
|
+
}
|
|
271
|
+
chunks.push(remaining.slice(0, splitAt));
|
|
272
|
+
remaining = remaining.slice(splitAt).trimStart();
|
|
273
|
+
}
|
|
274
|
+
return chunks;
|
|
275
|
+
}
|
|
276
|
+
async sendLongMessage(client, route, text) {
|
|
277
|
+
for (const chunk of this.splitMessage(text)) {
|
|
278
|
+
await this.sendWithRetry(client, route, chunk);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
async sendSafe(client, route, text) {
|
|
282
|
+
try {
|
|
283
|
+
await this.sendWithRetry(client, route, text);
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
console.error("[Slack] Failed to send message:", err);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
async sendWithRetry(client, route, text, maxRetries = 3) {
|
|
290
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
291
|
+
try {
|
|
292
|
+
await client.chat.postMessage({
|
|
293
|
+
channel: route.channel,
|
|
294
|
+
text: formatSlackMessage(text),
|
|
295
|
+
mrkdwn: true,
|
|
296
|
+
thread_ts: route.threadTs,
|
|
297
|
+
reply_broadcast: false,
|
|
298
|
+
});
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
catch (err) {
|
|
302
|
+
const retryAfter = this.getRetryAfterSeconds(err);
|
|
303
|
+
if (retryAfter && attempt < maxRetries) {
|
|
304
|
+
console.log(`[Slack] Rate limited, retrying after ${retryAfter}s...`);
|
|
305
|
+
await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
throw err;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
async tryAckReaction(client, event) {
|
|
313
|
+
try {
|
|
314
|
+
await client.reactions.add({
|
|
315
|
+
channel: event.channel,
|
|
316
|
+
timestamp: event.ts,
|
|
317
|
+
name: ACK_REACTION,
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
catch (err) {
|
|
321
|
+
console.error("[Slack] Failed to add ack reaction:", err);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
async safeAck(ack, message) {
|
|
325
|
+
if (!ack)
|
|
326
|
+
return;
|
|
327
|
+
try {
|
|
328
|
+
await ack(message);
|
|
329
|
+
}
|
|
330
|
+
catch (err) {
|
|
331
|
+
console.error("[Slack] Failed to ack slash command:", err);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
getRetryAfterSeconds(err) {
|
|
335
|
+
const candidates = [
|
|
336
|
+
err?.data?.retryAfter,
|
|
337
|
+
err?.retryAfter,
|
|
338
|
+
err?.headers?.["retry-after"],
|
|
339
|
+
err?.data?.headers?.["retry-after"],
|
|
340
|
+
];
|
|
341
|
+
for (const value of candidates) {
|
|
342
|
+
const seconds = Number(value);
|
|
343
|
+
if (Number.isFinite(seconds) && seconds > 0) {
|
|
344
|
+
return seconds;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
getTeamId(payload, context) {
|
|
350
|
+
return (context?.teamId ||
|
|
351
|
+
payload?.team_id ||
|
|
352
|
+
payload?.team?.id ||
|
|
353
|
+
payload?.authorizations?.[0]?.team_id ||
|
|
354
|
+
"unknown");
|
|
355
|
+
}
|
|
356
|
+
getChannelKey(teamId, channelId) {
|
|
357
|
+
return `${teamId}:${channelId}`;
|
|
358
|
+
}
|
|
359
|
+
isDmChannelId(channelId) {
|
|
360
|
+
return channelId.startsWith("D");
|
|
361
|
+
}
|
|
362
|
+
getErrorMessage(err) {
|
|
363
|
+
return err instanceof Error ? err.message : String(err);
|
|
364
|
+
}
|
|
365
|
+
escapeRegExp(value) {
|
|
366
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
//# sourceMappingURL=slack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack.js","sourceRoot":"","sources":["../../src/adapters/slack.ts"],"names":[],"mappings":"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"}
|