@crewx/cli 0.8.0-rc.66 → 0.8.0-rc.82
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/bin/crewx +2 -0
- package/dist/bootstrap/crewx-cli.d.ts +11 -0
- package/dist/bootstrap/crewx-cli.js +31 -0
- package/dist/builtin.d.ts +15 -0
- package/dist/{cli/builtin.handler.js → builtin.js} +21 -7
- package/dist/commands/agent.d.ts +12 -0
- package/dist/commands/agent.js +246 -0
- package/dist/commands/doctor.d.ts +12 -0
- package/dist/commands/doctor.js +190 -0
- package/dist/commands/execute.d.ts +21 -0
- package/dist/commands/execute.js +117 -0
- package/dist/commands/hook/install.d.ts +21 -0
- package/dist/commands/hook/install.js +175 -0
- package/dist/commands/hook/paths.d.ts +19 -0
- package/dist/commands/hook/paths.js +94 -0
- package/dist/commands/hook/status.d.ts +7 -0
- package/dist/commands/hook/status.js +86 -0
- package/dist/commands/hook/uninstall.d.ts +8 -0
- package/dist/commands/hook/uninstall.js +71 -0
- package/dist/commands/hook-dispatch.d.ts +15 -0
- package/dist/commands/hook-dispatch.js +180 -0
- package/dist/commands/init.d.ts +24 -0
- package/dist/commands/init.js +133 -0
- package/dist/commands/kill.d.ts +12 -0
- package/dist/commands/kill.js +49 -0
- package/dist/commands/log.d.ts +13 -0
- package/dist/commands/log.js +97 -0
- package/dist/commands/parse-agent-message.d.ts +31 -0
- package/dist/commands/parse-agent-message.js +52 -0
- package/dist/commands/parse-common-flags.d.ts +36 -0
- package/dist/commands/parse-common-flags.js +105 -0
- package/dist/commands/ps.d.ts +12 -0
- package/dist/commands/ps.js +71 -0
- package/dist/commands/query.d.ts +21 -0
- package/dist/commands/query.js +117 -0
- package/dist/commands/result.d.ts +13 -0
- package/dist/commands/result.js +73 -0
- package/dist/commands/slack.d.ts +12 -0
- package/dist/commands/slack.js +559 -0
- package/dist/commands/task-db.d.ts +33 -0
- package/dist/commands/task-db.js +107 -0
- package/dist/examples/deny-secrets-plugin.d.ts +22 -0
- package/dist/examples/deny-secrets-plugin.js +40 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -0
- package/dist/logging.d.ts +21 -0
- package/dist/logging.js +86 -0
- package/dist/main.d.ts +10 -0
- package/dist/main.js +246 -256
- package/dist/plugins/examples/echo-hook.d.ts +24 -0
- package/dist/plugins/examples/echo-hook.js +60 -0
- package/dist/plugins/examples/verify-echo-hook.d.ts +8 -0
- package/dist/plugins/examples/verify-echo-hook.js +47 -0
- package/dist/plugins/sqlite-tracing.d.ts +13 -0
- package/dist/plugins/sqlite-tracing.js +20 -0
- package/dist/register-builtin-tools.d.ts +5 -0
- package/dist/register-builtin-tools.js +9 -0
- package/dist/slack/file-download.d.ts +17 -0
- package/dist/slack/file-download.js +134 -0
- package/dist/slack/markdown.d.ts +5 -0
- package/dist/slack/markdown.js +33 -0
- package/dist/utils/env-defaults.d.ts +5 -0
- package/dist/utils/env-defaults.js +10 -0
- package/dist/utils/version.d.ts +1 -0
- package/dist/utils/version.js +28 -0
- package/package.json +32 -115
- package/README.md +0 -663
- package/dist/ai-provider.service.d.ts +0 -36
- package/dist/ai-provider.service.js +0 -315
- package/dist/ai-provider.service.js.map +0 -1
- package/dist/ai.service.d.ts +0 -17
- package/dist/ai.service.js +0 -51
- package/dist/ai.service.js.map +0 -1
- package/dist/app.module.d.ts +0 -5
- package/dist/app.module.js +0 -165
- package/dist/app.module.js.map +0 -1
- package/dist/cli/agent.handler.d.ts +0 -2
- package/dist/cli/agent.handler.js +0 -186
- package/dist/cli/agent.handler.js.map +0 -1
- package/dist/cli/builtin.handler.d.ts +0 -3
- package/dist/cli/builtin.handler.js.map +0 -1
- package/dist/cli/chat.handler.d.ts +0 -20
- package/dist/cli/chat.handler.js +0 -446
- package/dist/cli/chat.handler.js.map +0 -1
- package/dist/cli/cli.handler.d.ts +0 -4
- package/dist/cli/cli.handler.js +0 -119
- package/dist/cli/cli.handler.js.map +0 -1
- package/dist/cli/doctor.handler.d.ts +0 -38
- package/dist/cli/doctor.handler.js +0 -495
- package/dist/cli/doctor.handler.js.map +0 -1
- package/dist/cli/execute.handler.d.ts +0 -2
- package/dist/cli/execute.handler.js +0 -376
- package/dist/cli/execute.handler.js.map +0 -1
- package/dist/cli/help.handler.d.ts +0 -2
- package/dist/cli/help.handler.js +0 -10
- package/dist/cli/help.handler.js.map +0 -1
- package/dist/cli/init.handler.d.ts +0 -26
- package/dist/cli/init.handler.js +0 -450
- package/dist/cli/init.handler.js.map +0 -1
- package/dist/cli/log.handler.d.ts +0 -2
- package/dist/cli/log.handler.js +0 -69
- package/dist/cli/log.handler.js.map +0 -1
- package/dist/cli/mcp.handler.d.ts +0 -3
- package/dist/cli/mcp.handler.js +0 -121
- package/dist/cli/mcp.handler.js.map +0 -1
- package/dist/cli/query.handler.d.ts +0 -2
- package/dist/cli/query.handler.js +0 -392
- package/dist/cli/query.handler.js.map +0 -1
- package/dist/cli/skill.handler.d.ts +0 -2
- package/dist/cli/skill.handler.js +0 -252
- package/dist/cli/skill.handler.js.map +0 -1
- package/dist/cli/slack-files.handler.d.ts +0 -2
- package/dist/cli/slack-files.handler.js +0 -291
- package/dist/cli/slack-files.handler.js.map +0 -1
- package/dist/cli/template.handler.d.ts +0 -2
- package/dist/cli/template.handler.js +0 -188
- package/dist/cli/template.handler.js.map +0 -1
- package/dist/cli/templates.handler.d.ts +0 -2
- package/dist/cli/templates.handler.js +0 -100
- package/dist/cli/templates.handler.js.map +0 -1
- package/dist/cli-options.d.ts +0 -40
- package/dist/cli-options.js +0 -371
- package/dist/cli-options.js.map +0 -1
- package/dist/config/timeout.config.d.ts +0 -14
- package/dist/config/timeout.config.js +0 -34
- package/dist/config/timeout.config.js.map +0 -1
- package/dist/conversation/base-conversation-history.provider.d.ts +0 -12
- package/dist/conversation/base-conversation-history.provider.js +0 -45
- package/dist/conversation/base-conversation-history.provider.js.map +0 -1
- package/dist/conversation/cli-box-reader.adapter.d.ts +0 -6
- package/dist/conversation/cli-box-reader.adapter.js +0 -10
- package/dist/conversation/cli-box-reader.adapter.js.map +0 -1
- package/dist/conversation/cli-conversation-history.provider.d.ts +0 -16
- package/dist/conversation/cli-conversation-history.provider.js +0 -112
- package/dist/conversation/cli-conversation-history.provider.js.map +0 -1
- package/dist/conversation/cli-task-reader.adapter.d.ts +0 -6
- package/dist/conversation/cli-task-reader.adapter.js +0 -25
- package/dist/conversation/cli-task-reader.adapter.js.map +0 -1
- package/dist/conversation/conversation-provider.factory.d.ts +0 -10
- package/dist/conversation/conversation-provider.factory.js +0 -50
- package/dist/conversation/conversation-provider.factory.js.map +0 -1
- package/dist/conversation/index.d.ts +0 -8
- package/dist/conversation/index.js +0 -29
- package/dist/conversation/index.js.map +0 -1
- package/dist/conversation/slack-conversation-history.provider.d.ts +0 -29
- package/dist/conversation/slack-conversation-history.provider.js +0 -302
- package/dist/conversation/slack-conversation-history.provider.js.map +0 -1
- package/dist/crewx.tool.d.ts +0 -360
- package/dist/crewx.tool.js +0 -2531
- package/dist/crewx.tool.js.map +0 -1
- package/dist/crewx.tool.spec.d.ts +0 -1
- package/dist/crewx.tool.spec.js +0 -222
- package/dist/crewx.tool.spec.js.map +0 -1
- package/dist/guards/bearer-auth.guard.d.ts +0 -7
- package/dist/guards/bearer-auth.guard.js +0 -44
- package/dist/guards/bearer-auth.guard.js.map +0 -1
- package/dist/health.controller.d.ts +0 -6
- package/dist/health.controller.js +0 -32
- package/dist/health.controller.js.map +0 -1
- package/dist/main.js.map +0 -1
- package/dist/mcp.controller.d.ts +0 -8
- package/dist/mcp.controller.js +0 -62
- package/dist/mcp.controller.js.map +0 -1
- package/dist/package.json +0 -3
- package/dist/providers/dynamic-provider.factory.d.ts +0 -17
- package/dist/providers/dynamic-provider.factory.js +0 -138
- package/dist/providers/dynamic-provider.factory.js.map +0 -1
- package/dist/providers/logger.adapter.d.ts +0 -7
- package/dist/providers/logger.adapter.js +0 -107
- package/dist/providers/logger.adapter.js.map +0 -1
- package/dist/services/agent-loader.service.d.ts +0 -35
- package/dist/services/agent-loader.service.js +0 -623
- package/dist/services/agent-loader.service.js.map +0 -1
- package/dist/services/auth.service.d.ts +0 -9
- package/dist/services/auth.service.js +0 -47
- package/dist/services/auth.service.js.map +0 -1
- package/dist/services/config-validator.service.d.ts +0 -29
- package/dist/services/config-validator.service.js +0 -483
- package/dist/services/config-validator.service.js.map +0 -1
- package/dist/services/config.service.d.ts +0 -45
- package/dist/services/config.service.js +0 -352
- package/dist/services/config.service.js.map +0 -1
- package/dist/services/document-loader.service.d.ts +0 -26
- package/dist/services/document-loader.service.js +0 -186
- package/dist/services/document-loader.service.js.map +0 -1
- package/dist/services/help.service.d.ts +0 -5
- package/dist/services/help.service.js +0 -139
- package/dist/services/help.service.js.map +0 -1
- package/dist/services/intelligent-compression.service.d.ts +0 -20
- package/dist/services/intelligent-compression.service.js +0 -179
- package/dist/services/intelligent-compression.service.js.map +0 -1
- package/dist/services/mcp-client.service.d.ts +0 -26
- package/dist/services/mcp-client.service.js +0 -81
- package/dist/services/mcp-client.service.js.map +0 -1
- package/dist/services/parallel-processing.service.d.ts +0 -108
- package/dist/services/parallel-processing.service.js +0 -333
- package/dist/services/parallel-processing.service.js.map +0 -1
- package/dist/services/provider-bridge.service.d.ts +0 -35
- package/dist/services/provider-bridge.service.js +0 -224
- package/dist/services/provider-bridge.service.js.map +0 -1
- package/dist/services/remote-agent.service.d.ts +0 -50
- package/dist/services/remote-agent.service.js +0 -171
- package/dist/services/remote-agent.service.js.map +0 -1
- package/dist/services/result-formatter.service.d.ts +0 -27
- package/dist/services/result-formatter.service.js +0 -126
- package/dist/services/result-formatter.service.js.map +0 -1
- package/dist/services/skill-loader.service.d.ts +0 -15
- package/dist/services/skill-loader.service.js +0 -278
- package/dist/services/skill-loader.service.js.map +0 -1
- package/dist/services/skill.service.d.ts +0 -69
- package/dist/services/skill.service.js +0 -779
- package/dist/services/skill.service.js.map +0 -1
- package/dist/services/skill.service.spec.d.ts +0 -1
- package/dist/services/skill.service.spec.js +0 -168
- package/dist/services/skill.service.spec.js.map +0 -1
- package/dist/services/task-management.service.d.ts +0 -71
- package/dist/services/task-management.service.js +0 -324
- package/dist/services/task-management.service.js.map +0 -1
- package/dist/services/template.service.d.ts +0 -61
- package/dist/services/template.service.js +0 -416
- package/dist/services/template.service.js.map +0 -1
- package/dist/services/tool-call.service.d.ts +0 -16
- package/dist/services/tool-call.service.js +0 -302
- package/dist/services/tool-call.service.js.map +0 -1
- package/dist/services/tracing.service.d.ts +0 -197
- package/dist/services/tracing.service.js +0 -1267
- package/dist/services/tracing.service.js.map +0 -1
- package/dist/slack/formatters/message.formatter.d.ts +0 -43
- package/dist/slack/formatters/message.formatter.js +0 -505
- package/dist/slack/formatters/message.formatter.js.map +0 -1
- package/dist/slack/services/slack-file-download.service.d.ts +0 -58
- package/dist/slack/services/slack-file-download.service.js +0 -558
- package/dist/slack/services/slack-file-download.service.js.map +0 -1
- package/dist/slack/slack-bot.d.ts +0 -33
- package/dist/slack/slack-bot.js +0 -568
- package/dist/slack/slack-bot.js.map +0 -1
- package/dist/stderr.logger.d.ts +0 -8
- package/dist/stderr.logger.js +0 -26
- package/dist/stderr.logger.js.map +0 -1
- package/dist/types/usage.types.d.ts +0 -107
- package/dist/types/usage.types.js +0 -3
- package/dist/types/usage.types.js.map +0 -1
- package/dist/utils/config-utils.d.ts +0 -15
- package/dist/utils/config-utils.js +0 -69
- package/dist/utils/config-utils.js.map +0 -1
- package/dist/utils/extract-text.d.ts +0 -1
- package/dist/utils/extract-text.js +0 -15
- package/dist/utils/extract-text.js.map +0 -1
- package/dist/utils/mcp-installer.d.ts +0 -20
- package/dist/utils/mcp-installer.js +0 -199
- package/dist/utils/mcp-installer.js.map +0 -1
- package/dist/utils/project-hash.d.ts +0 -6
- package/dist/utils/project-hash.js +0 -70
- package/dist/utils/project-hash.js.map +0 -1
- package/dist/utils/simple-security.d.ts +0 -3
- package/dist/utils/simple-security.js +0 -20
- package/dist/utils/simple-security.js.map +0 -1
- package/dist/utils/stdin-utils.d.ts +0 -6
- package/dist/utils/stdin-utils.js +0 -109
- package/dist/utils/stdin-utils.js.map +0 -1
- package/dist/utils/template-processor.d.ts +0 -27
- package/dist/utils/template-processor.js +0 -395
- package/dist/utils/template-processor.js.map +0 -1
- package/dist/utils/terminal-message-formatter.d.ts +0 -23
- package/dist/utils/terminal-message-formatter.js +0 -136
- package/dist/utils/terminal-message-formatter.js.map +0 -1
- package/dist/version.d.ts +0 -1
- package/dist/version.js +0 -17
- package/dist/version.js.map +0 -1
- package/dist/workspace.service.d.ts +0 -44
- package/dist/workspace.service.js +0 -299
- package/dist/workspace.service.js.map +0 -1
- package/scripts/backfill-tokens.js +0 -218
- package/scripts/postbuild-cli.mjs +0 -88
- package/scripts/postinstall-cli.mjs +0 -30
- package/templates/agents/default.yaml +0 -490
- package/templates/agents/minimal.yaml +0 -16
- package/templates/documents/conversation-history-default.hbs +0 -17
- package/templates/documents/crewx-manual.md +0 -2278
- package/templates/documents/crewx-quick-guide.md +0 -147
- package/templates/versions.json +0 -19
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Slack files command — crewx slack:files [--thread <thread_ts>] [--list] [--clean]
|
|
4
|
+
*
|
|
5
|
+
* Ported 1:1 from packages/cli-bak/src/cli/slack-files.handler.ts.
|
|
6
|
+
* Implements download/list/clean operations without NestJS or @slack/web-api.
|
|
7
|
+
* Uses Node.js built-in https and fetch for Slack API calls.
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.handleSlack = handleSlack;
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const https = __importStar(require("https"));
|
|
47
|
+
const adapter_slack_1 = require("@crewx/adapter-slack");
|
|
48
|
+
const crewx_cli_1 = require("../bootstrap/crewx-cli");
|
|
49
|
+
const markdown_1 = require("../slack/markdown");
|
|
50
|
+
const file_download_1 = require("../slack/file-download");
|
|
51
|
+
// ─── Entry point ──────────────────────────────────────────────────────────
|
|
52
|
+
/**
|
|
53
|
+
* Handle `crewx slack` / `crewx slack:files` commands.
|
|
54
|
+
* Subcommand is determined by flags: --list → list, --clean → clean, default → download.
|
|
55
|
+
*/
|
|
56
|
+
async function handleSlack(args) {
|
|
57
|
+
if (args.includes('--mode') || args.includes('--agent')) {
|
|
58
|
+
return await handleBotMode(args);
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const subCommand = getSubcommand(args);
|
|
62
|
+
const threadId = getThreadOption(args);
|
|
63
|
+
const botToken = process.env.SLACK_BOT_TOKEN;
|
|
64
|
+
if (!botToken && subCommand === 'download') {
|
|
65
|
+
console.error('\n❌ Error: SLACK_BOT_TOKEN environment variable not found\n');
|
|
66
|
+
console.log('Set your Slack bot token:');
|
|
67
|
+
console.log(' export SLACK_BOT_TOKEN=xoxb-your-token\n');
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
switch (subCommand) {
|
|
71
|
+
case 'list':
|
|
72
|
+
await handleListFiles(threadId);
|
|
73
|
+
break;
|
|
74
|
+
case 'clean':
|
|
75
|
+
await handleCleanFiles(threadId);
|
|
76
|
+
break;
|
|
77
|
+
case 'download':
|
|
78
|
+
default:
|
|
79
|
+
await handleDownloadFiles(botToken, threadId);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
85
|
+
console.error(`\n❌ Slack files command failed:\n${errorMessage}\n`);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// ─── Subcommand resolution ───────────────────────────────────────────────
|
|
90
|
+
function getSubcommand(args) {
|
|
91
|
+
if (args.includes('--list') || args.includes('-l'))
|
|
92
|
+
return 'list';
|
|
93
|
+
if (args.includes('--clean'))
|
|
94
|
+
return 'clean';
|
|
95
|
+
return 'download';
|
|
96
|
+
}
|
|
97
|
+
function getThreadOption(args) {
|
|
98
|
+
const idx = args.findIndex(a => a === '--thread' || a === '-t');
|
|
99
|
+
if (idx !== -1 && idx + 1 < args.length) {
|
|
100
|
+
return args[idx + 1];
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
// ─── Download ────────────────────────────────────────────────────────────
|
|
105
|
+
async function handleDownloadFiles(botToken, threadId) {
|
|
106
|
+
if (!threadId) {
|
|
107
|
+
console.error('\n❌ Error: --thread option is required for download\n');
|
|
108
|
+
console.log('Usage: crewx slack:files --thread <thread_ts>\n');
|
|
109
|
+
console.log('Example:');
|
|
110
|
+
console.log(' crewx slack:files --thread 1234567890.123456\n');
|
|
111
|
+
process.exit(1);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const validThreadId = threadId;
|
|
115
|
+
console.log(`\n📥 Downloading files from thread: ${validThreadId}\n`);
|
|
116
|
+
const channelId = validThreadId.includes('.')
|
|
117
|
+
? (validThreadId.split('.')[0] || validThreadId)
|
|
118
|
+
: validThreadId;
|
|
119
|
+
// Fetch conversation history from Slack API
|
|
120
|
+
const messages = await slackConversationsHistory(botToken, channelId, validThreadId);
|
|
121
|
+
if (!messages || messages.length === 0) {
|
|
122
|
+
console.log('⚠️ No messages found in thread\n');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// Collect files from messages
|
|
126
|
+
const files = [];
|
|
127
|
+
for (const message of messages) {
|
|
128
|
+
if (message.files) {
|
|
129
|
+
for (const file of message.files) {
|
|
130
|
+
files.push({
|
|
131
|
+
id: file.id,
|
|
132
|
+
name: file.name,
|
|
133
|
+
userId: message.user || 'unknown',
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (files.length === 0) {
|
|
139
|
+
console.log('ℹ️ No files found in thread\n');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
console.log(`Found ${files.length} file${files.length > 1 ? 's' : ''} to download:\n`);
|
|
143
|
+
let downloadedCount = 0;
|
|
144
|
+
let skippedCount = 0;
|
|
145
|
+
let failedCount = 0;
|
|
146
|
+
for (const file of files) {
|
|
147
|
+
try {
|
|
148
|
+
const metadata = await downloadSlackFile(botToken, file.id, file.name, validThreadId, channelId, file.userId);
|
|
149
|
+
const wasSkipped = fs.existsSync(metadata.filePath) &&
|
|
150
|
+
fs.statSync(metadata.filePath).mtime < metadata.downloadedAt;
|
|
151
|
+
if (wasSkipped) {
|
|
152
|
+
console.log(` ⏭️ ${file.name} (already exists)`);
|
|
153
|
+
skippedCount++;
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
console.log(` ✅ ${file.name} (${formatFileSize(metadata.fileSize)})`);
|
|
157
|
+
downloadedCount++;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
162
|
+
console.log(` ❌ ${file.name} - ${errorMessage}`);
|
|
163
|
+
failedCount++;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
console.log(`\n📊 Summary:`);
|
|
167
|
+
if (downloadedCount > 0)
|
|
168
|
+
console.log(` Downloaded: ${downloadedCount} file${downloadedCount > 1 ? 's' : ''}`);
|
|
169
|
+
if (skippedCount > 0)
|
|
170
|
+
console.log(` Skipped: ${skippedCount} file${skippedCount > 1 ? 's' : ''} (already exists)`);
|
|
171
|
+
if (failedCount > 0)
|
|
172
|
+
console.log(` Failed: ${failedCount} file${failedCount > 1 ? 's' : ''}`);
|
|
173
|
+
console.log('');
|
|
174
|
+
}
|
|
175
|
+
// ─── List ────────────────────────────────────────────────────────────────
|
|
176
|
+
async function handleListFiles(threadId) {
|
|
177
|
+
const downloadDir = path.join(process.cwd(), '.crewx', 'slack-files');
|
|
178
|
+
if (threadId) {
|
|
179
|
+
console.log(`\n📋 Files in thread ${threadId}:\n`);
|
|
180
|
+
const files = getThreadFilesMetadata(threadId, downloadDir);
|
|
181
|
+
if (files.length === 0) {
|
|
182
|
+
console.log(' No files downloaded for this thread\n');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
for (const file of files) {
|
|
186
|
+
console.log(` 📎 ${file.fileName}`);
|
|
187
|
+
console.log(` Size: ${formatFileSize(file.fileSize)}`);
|
|
188
|
+
console.log(` Path: ${file.filePath}`);
|
|
189
|
+
console.log(` Downloaded: ${file.downloadedAt.toLocaleString()}`);
|
|
190
|
+
console.log('');
|
|
191
|
+
}
|
|
192
|
+
console.log(`Total: ${files.length} file${files.length > 1 ? 's' : ''}\n`);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
console.log('\n📋 All downloaded Slack files:\n');
|
|
196
|
+
if (!fs.existsSync(downloadDir)) {
|
|
197
|
+
console.log(' No files downloaded yet\n');
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const threadDirs = fs.readdirSync(downloadDir).filter(name => fs.statSync(path.join(downloadDir, name)).isDirectory());
|
|
201
|
+
if (threadDirs.length === 0) {
|
|
202
|
+
console.log(' No files downloaded yet\n');
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
let totalFiles = 0;
|
|
206
|
+
for (const threadDir of threadDirs) {
|
|
207
|
+
const files = getThreadFilesMetadata(threadDir, downloadDir);
|
|
208
|
+
if (files.length > 0) {
|
|
209
|
+
console.log(` Thread: ${threadDir}`);
|
|
210
|
+
for (const file of files) {
|
|
211
|
+
console.log(` 📎 ${file.fileName} (${formatFileSize(file.fileSize)})`);
|
|
212
|
+
totalFiles++;
|
|
213
|
+
}
|
|
214
|
+
console.log('');
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
console.log(`Total: ${totalFiles} file${totalFiles > 1 ? 's' : ''} in ${threadDirs.length} thread${threadDirs.length > 1 ? 's' : ''}\n`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// ─── Clean ───────────────────────────────────────────────────────────────
|
|
221
|
+
async function handleCleanFiles(threadId) {
|
|
222
|
+
const downloadDir = path.join(process.cwd(), '.crewx', 'slack-files');
|
|
223
|
+
if (threadId) {
|
|
224
|
+
console.log(`\n🧹 Cleaning files for thread ${threadId}...\n`);
|
|
225
|
+
const safeThreadDir = threadId.replace(/:/g, '_');
|
|
226
|
+
const threadDir = path.join(downloadDir, safeThreadDir);
|
|
227
|
+
if (!fs.existsSync(threadDir)) {
|
|
228
|
+
console.log(' No files to clean\n');
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const files = fs.readdirSync(threadDir);
|
|
232
|
+
for (const file of files) {
|
|
233
|
+
fs.unlinkSync(path.join(threadDir, file));
|
|
234
|
+
}
|
|
235
|
+
fs.rmdirSync(threadDir);
|
|
236
|
+
console.log(`✅ Cleaned ${files.length} file${files.length > 1 ? 's' : ''}\n`);
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
console.log('\n🧹 Cleaning all downloaded files...\n');
|
|
240
|
+
if (!fs.existsSync(downloadDir)) {
|
|
241
|
+
console.log(' No files to clean\n');
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
let totalFiles = 0;
|
|
245
|
+
let totalThreads = 0;
|
|
246
|
+
const threadDirs = fs.readdirSync(downloadDir).filter(name => fs.statSync(path.join(downloadDir, name)).isDirectory());
|
|
247
|
+
for (const threadDir of threadDirs) {
|
|
248
|
+
const threadPath = path.join(downloadDir, threadDir);
|
|
249
|
+
const files = fs.readdirSync(threadPath);
|
|
250
|
+
for (const file of files) {
|
|
251
|
+
fs.unlinkSync(path.join(threadPath, file));
|
|
252
|
+
totalFiles++;
|
|
253
|
+
}
|
|
254
|
+
fs.rmdirSync(threadPath);
|
|
255
|
+
totalThreads++;
|
|
256
|
+
}
|
|
257
|
+
console.log(`✅ Cleaned ${totalFiles} file${totalFiles > 1 ? 's' : ''} from ${totalThreads} thread${totalThreads > 1 ? 's' : ''}\n`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// ─── Slack API helpers ───────────────────────────────────────────────────
|
|
261
|
+
/**
|
|
262
|
+
* Call Slack conversations.history API using Node.js https.
|
|
263
|
+
* Returns array of message objects.
|
|
264
|
+
*/
|
|
265
|
+
async function slackConversationsHistory(token, channel, latest) {
|
|
266
|
+
const params = new URLSearchParams({
|
|
267
|
+
channel,
|
|
268
|
+
latest,
|
|
269
|
+
inclusive: 'true',
|
|
270
|
+
limit: '100',
|
|
271
|
+
});
|
|
272
|
+
const data = await slackApiGet(token, `conversations.history?${params.toString()}`);
|
|
273
|
+
if (!data.ok) {
|
|
274
|
+
throw new Error(`Slack API error: ${data.error ?? 'unknown_error'}`);
|
|
275
|
+
}
|
|
276
|
+
return data.messages ?? [];
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Download a single Slack file and save it to disk.
|
|
280
|
+
*/
|
|
281
|
+
async function downloadSlackFile(botToken, fileId, fileName, threadId, channelId, userId) {
|
|
282
|
+
// Get file info
|
|
283
|
+
const infoData = await slackApiGet(botToken, `files.info?file=${fileId}`);
|
|
284
|
+
if (!infoData.ok) {
|
|
285
|
+
throw new Error(`Failed to get file info: ${infoData.error ?? 'unknown_error'}`);
|
|
286
|
+
}
|
|
287
|
+
const fileInfo = infoData.file;
|
|
288
|
+
if (!fileInfo?.url_private) {
|
|
289
|
+
throw new Error('No private download URL available for this file');
|
|
290
|
+
}
|
|
291
|
+
// Build save path
|
|
292
|
+
const sanitized = sanitizeFileName(fileName);
|
|
293
|
+
const uniqueName = `${fileId}${path.extname(sanitized)}`;
|
|
294
|
+
const safeThreadDir = threadId.replace(/:/g, '_');
|
|
295
|
+
const downloadDir = path.join(process.cwd(), '.crewx', 'slack-files');
|
|
296
|
+
const savePath = path.join(downloadDir, safeThreadDir, uniqueName);
|
|
297
|
+
// Duplicate check
|
|
298
|
+
if (fs.existsSync(savePath)) {
|
|
299
|
+
const stats = fs.statSync(savePath);
|
|
300
|
+
return {
|
|
301
|
+
fileId,
|
|
302
|
+
fileName: sanitized,
|
|
303
|
+
filePath: savePath,
|
|
304
|
+
fileSize: stats.size,
|
|
305
|
+
mimeType: fileInfo.mimetype ?? 'application/octet-stream',
|
|
306
|
+
uploadedBy: userId,
|
|
307
|
+
uploadedAt: new Date((fileInfo.timestamp ?? 0) * 1000),
|
|
308
|
+
threadId,
|
|
309
|
+
channelId,
|
|
310
|
+
downloadedAt: new Date(stats.mtime),
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
// Fetch file content from Slack private URL
|
|
314
|
+
const fileBuffer = await fetchPrivateUrl(botToken, fileInfo.url_private);
|
|
315
|
+
// Save to disk
|
|
316
|
+
await fs.promises.mkdir(path.dirname(savePath), { recursive: true });
|
|
317
|
+
await fs.promises.writeFile(savePath, fileBuffer);
|
|
318
|
+
return {
|
|
319
|
+
fileId,
|
|
320
|
+
fileName: sanitized,
|
|
321
|
+
filePath: savePath,
|
|
322
|
+
fileSize: fileBuffer.length,
|
|
323
|
+
mimeType: fileInfo.mimetype ?? 'application/octet-stream',
|
|
324
|
+
uploadedBy: userId,
|
|
325
|
+
uploadedAt: new Date((fileInfo.timestamp ?? 0) * 1000),
|
|
326
|
+
threadId,
|
|
327
|
+
channelId,
|
|
328
|
+
downloadedAt: new Date(),
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Make a GET request to a Slack API endpoint.
|
|
333
|
+
*/
|
|
334
|
+
async function slackApiGet(token, endpoint) {
|
|
335
|
+
return new Promise((resolve, reject) => {
|
|
336
|
+
const options = {
|
|
337
|
+
hostname: 'slack.com',
|
|
338
|
+
path: `/api/${endpoint}`,
|
|
339
|
+
method: 'GET',
|
|
340
|
+
headers: {
|
|
341
|
+
Authorization: `Bearer ${token}`,
|
|
342
|
+
'Content-Type': 'application/json',
|
|
343
|
+
},
|
|
344
|
+
};
|
|
345
|
+
const req = https.request(options, res => {
|
|
346
|
+
let body = '';
|
|
347
|
+
res.on('data', chunk => { body += chunk; });
|
|
348
|
+
res.on('end', () => {
|
|
349
|
+
try {
|
|
350
|
+
resolve(JSON.parse(body));
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
reject(new Error(`Failed to parse Slack API response: ${body}`));
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
req.on('error', reject);
|
|
358
|
+
req.setTimeout(30000, () => {
|
|
359
|
+
req.destroy();
|
|
360
|
+
reject(new Error('Slack API request timed out'));
|
|
361
|
+
});
|
|
362
|
+
req.end();
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Download content from a Slack private URL using Bearer auth.
|
|
367
|
+
*/
|
|
368
|
+
async function fetchPrivateUrl(token, url) {
|
|
369
|
+
const parsed = new URL(url);
|
|
370
|
+
return new Promise((resolve, reject) => {
|
|
371
|
+
const options = {
|
|
372
|
+
hostname: parsed.hostname,
|
|
373
|
+
path: parsed.pathname + parsed.search,
|
|
374
|
+
method: 'GET',
|
|
375
|
+
headers: {
|
|
376
|
+
Authorization: `Bearer ${token}`,
|
|
377
|
+
},
|
|
378
|
+
};
|
|
379
|
+
const req = https.request(options, res => {
|
|
380
|
+
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
381
|
+
// Follow redirect
|
|
382
|
+
const location = res.headers.location;
|
|
383
|
+
if (!location) {
|
|
384
|
+
reject(new Error('Redirect without location header'));
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
fetchPrivateUrl(token, location).then(resolve).catch(reject);
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
if (res.statusCode !== 200) {
|
|
391
|
+
reject(new Error(`HTTP ${res.statusCode} while downloading file`));
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const chunks = [];
|
|
395
|
+
res.on('data', (chunk) => chunks.push(chunk));
|
|
396
|
+
res.on('end', () => resolve(Buffer.concat(chunks)));
|
|
397
|
+
res.on('error', reject);
|
|
398
|
+
});
|
|
399
|
+
req.on('error', reject);
|
|
400
|
+
req.setTimeout(30000, () => {
|
|
401
|
+
req.destroy();
|
|
402
|
+
reject(new Error('File download timed out'));
|
|
403
|
+
});
|
|
404
|
+
req.end();
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
// ─── Local file helpers ───────────────────────────────────────────────────
|
|
408
|
+
function getThreadFilesMetadata(threadId, downloadDir) {
|
|
409
|
+
const safeThreadDir = threadId.replace(/:/g, '_');
|
|
410
|
+
const threadDir = path.join(downloadDir, safeThreadDir);
|
|
411
|
+
if (!fs.existsSync(threadDir))
|
|
412
|
+
return [];
|
|
413
|
+
const files = fs.readdirSync(threadDir);
|
|
414
|
+
const metadata = [];
|
|
415
|
+
for (const file of files) {
|
|
416
|
+
try {
|
|
417
|
+
const filePath = path.join(threadDir, file);
|
|
418
|
+
const stats = fs.statSync(filePath);
|
|
419
|
+
metadata.push({
|
|
420
|
+
fileId: '',
|
|
421
|
+
fileName: file,
|
|
422
|
+
filePath,
|
|
423
|
+
fileSize: stats.size,
|
|
424
|
+
mimeType: guessMimeType(file),
|
|
425
|
+
uploadedBy: '',
|
|
426
|
+
uploadedAt: new Date(stats.birthtime),
|
|
427
|
+
threadId,
|
|
428
|
+
channelId: '',
|
|
429
|
+
downloadedAt: new Date(stats.mtime),
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
catch {
|
|
433
|
+
// ignore unreadable files
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return metadata;
|
|
437
|
+
}
|
|
438
|
+
function sanitizeFileName(fileName) {
|
|
439
|
+
let safeName = fileName.replace(/[/\\]/g, '_');
|
|
440
|
+
safeName = safeName.replace(/\.\./g, '_');
|
|
441
|
+
safeName = safeName.replace(/[\x00-\x1f\x80-\x9f<>:"|?*]/g, '_');
|
|
442
|
+
safeName = safeName.replace(/^\.+|\.+$/g, '');
|
|
443
|
+
safeName = safeName.trim();
|
|
444
|
+
if (!safeName)
|
|
445
|
+
safeName = 'unnamed_file';
|
|
446
|
+
return safeName;
|
|
447
|
+
}
|
|
448
|
+
function guessMimeType(fileName) {
|
|
449
|
+
const ext = path.extname(fileName).toLowerCase();
|
|
450
|
+
const mimeTypes = {
|
|
451
|
+
'.pdf': 'application/pdf',
|
|
452
|
+
'.png': 'image/png',
|
|
453
|
+
'.jpg': 'image/jpeg',
|
|
454
|
+
'.jpeg': 'image/jpeg',
|
|
455
|
+
'.gif': 'image/gif',
|
|
456
|
+
'.txt': 'text/plain',
|
|
457
|
+
'.md': 'text/markdown',
|
|
458
|
+
'.csv': 'text/csv',
|
|
459
|
+
'.json': 'application/json',
|
|
460
|
+
'.xml': 'application/xml',
|
|
461
|
+
'.zip': 'application/zip',
|
|
462
|
+
'.doc': 'application/msword',
|
|
463
|
+
'.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
464
|
+
'.xls': 'application/vnd.ms-excel',
|
|
465
|
+
'.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
466
|
+
};
|
|
467
|
+
return mimeTypes[ext] ?? 'application/octet-stream';
|
|
468
|
+
}
|
|
469
|
+
function formatFileSize(bytes) {
|
|
470
|
+
if (bytes < 1024)
|
|
471
|
+
return `${bytes}B`;
|
|
472
|
+
if (bytes < 1024 * 1024)
|
|
473
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
474
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
475
|
+
}
|
|
476
|
+
// ─── Bot mode ────────────────────────────────────────────────────────────
|
|
477
|
+
function parseFlag(args, flag) {
|
|
478
|
+
const idx = args.indexOf(flag);
|
|
479
|
+
if (idx !== -1 && idx + 1 < args.length) {
|
|
480
|
+
return args[idx + 1];
|
|
481
|
+
}
|
|
482
|
+
const prefix = `${flag}=`;
|
|
483
|
+
const found = args.find(a => a.startsWith(prefix));
|
|
484
|
+
return found ? found.slice(prefix.length) : undefined;
|
|
485
|
+
}
|
|
486
|
+
async function handleBotMode(args) {
|
|
487
|
+
const mode = parseFlag(args, '--mode') ?? 'query';
|
|
488
|
+
const agent = parseFlag(args, '--agent');
|
|
489
|
+
if (!agent) {
|
|
490
|
+
console.error('Error: --agent required for bot mode');
|
|
491
|
+
console.error('Usage: crewx slack --mode <query|execute> --agent <agent-id>');
|
|
492
|
+
process.exit(1);
|
|
493
|
+
}
|
|
494
|
+
if (mode !== 'query' && mode !== 'execute') {
|
|
495
|
+
console.error(`Error: invalid mode "${mode}" — must be query or execute`);
|
|
496
|
+
process.exit(1);
|
|
497
|
+
}
|
|
498
|
+
const botToken = process.env.SLACK_BOT_TOKEN;
|
|
499
|
+
const appToken = process.env.SLACK_APP_TOKEN;
|
|
500
|
+
if (!botToken || !appToken) {
|
|
501
|
+
console.error('Error: SLACK_BOT_TOKEN and SLACK_APP_TOKEN environment variables required');
|
|
502
|
+
process.exit(1);
|
|
503
|
+
}
|
|
504
|
+
const configPath = process.env.CREWX_CONFIG ?? './crewx.yaml';
|
|
505
|
+
let crewx;
|
|
506
|
+
try {
|
|
507
|
+
crewx = await (0, crewx_cli_1.createCliCrewx)(configPath);
|
|
508
|
+
}
|
|
509
|
+
catch (err) {
|
|
510
|
+
console.error(`Failed to load config: ${configPath}`);
|
|
511
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
512
|
+
process.exit(1);
|
|
513
|
+
}
|
|
514
|
+
const adapter = new adapter_slack_1.SlackAdapter();
|
|
515
|
+
await crewx.registerChannelAdapter({
|
|
516
|
+
adapter,
|
|
517
|
+
instanceId: `slack-${agent}`,
|
|
518
|
+
config: { mode: 'socket', botToken, appToken },
|
|
519
|
+
defaultMode: mode,
|
|
520
|
+
defaultAgent: agent,
|
|
521
|
+
onInbound: async (msg) => {
|
|
522
|
+
if (msg.attachments && msg.attachments.length > 0) {
|
|
523
|
+
try {
|
|
524
|
+
await (0, file_download_1.downloadInboundFiles)(botToken, msg.attachments.map(a => ({
|
|
525
|
+
url_private: a.url,
|
|
526
|
+
mimetype: a.mimeType ?? 'application/octet-stream',
|
|
527
|
+
name: a.name ?? 'unnamed',
|
|
528
|
+
})), msg.threadId);
|
|
529
|
+
}
|
|
530
|
+
catch (err) {
|
|
531
|
+
console.error('File download failed:', err instanceof Error ? err.message : String(err));
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
const fn = mode === 'execute' ? crewx.execute.bind(crewx) : crewx.query.bind(crewx);
|
|
535
|
+
const result = await fn(`@${agent}`, msg.text, { threadId: msg.threadId, platform: adapter.manifest.platform });
|
|
536
|
+
const rawOutput = result.ok
|
|
537
|
+
? result.data
|
|
538
|
+
: (result.error?.message ?? 'Error');
|
|
539
|
+
return { accepted: true, output: (0, markdown_1.markdownToMrkdwn)(rawOutput) };
|
|
540
|
+
},
|
|
541
|
+
});
|
|
542
|
+
console.log(`Slack bot started (agent=${agent}, mode=${mode}, instance=slack-${agent})`);
|
|
543
|
+
console.log('Press Ctrl+C to shut down.');
|
|
544
|
+
await new Promise((resolve) => {
|
|
545
|
+
const shutdown = async () => {
|
|
546
|
+
console.log('\nShutting down...');
|
|
547
|
+
try {
|
|
548
|
+
await crewx.stopAllAdapters({ timeoutMs: 5000 });
|
|
549
|
+
}
|
|
550
|
+
catch (err) {
|
|
551
|
+
console.error('Shutdown error:', err instanceof Error ? err.message : String(err));
|
|
552
|
+
}
|
|
553
|
+
resolve();
|
|
554
|
+
};
|
|
555
|
+
process.once('SIGINT', shutdown);
|
|
556
|
+
process.once('SIGTERM', shutdown);
|
|
557
|
+
});
|
|
558
|
+
process.exit(0);
|
|
559
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared SQLite helper for ps/kill/result CLI commands.
|
|
3
|
+
* Reads from (or writes to) the global ~/.crewx/crewx.db
|
|
4
|
+
* populated by SqliteTracingPlugin.
|
|
5
|
+
*/
|
|
6
|
+
import BetterSqlite3 from 'better-sqlite3';
|
|
7
|
+
export type TaskStatus = 'running' | 'success' | 'failed';
|
|
8
|
+
export interface TaskRow {
|
|
9
|
+
id: string;
|
|
10
|
+
agent_id: string;
|
|
11
|
+
prompt: string;
|
|
12
|
+
mode: string;
|
|
13
|
+
status: TaskStatus;
|
|
14
|
+
pid: number | null;
|
|
15
|
+
started_at: string;
|
|
16
|
+
completed_at: string | null;
|
|
17
|
+
result: string | null;
|
|
18
|
+
error: string | null;
|
|
19
|
+
duration_ms: number | null;
|
|
20
|
+
}
|
|
21
|
+
export declare function getDbPath(dbRoot?: string): string;
|
|
22
|
+
export declare function openDb(readonly?: boolean, dbRoot?: string): InstanceType<typeof BetterSqlite3> | null;
|
|
23
|
+
/** Return all tasks with status='running'. */
|
|
24
|
+
export declare function getRunningTasks(dbRoot?: string): TaskRow[];
|
|
25
|
+
/** Return all tasks ordered by started_at desc. */
|
|
26
|
+
export declare function getAllTasks(dbRoot?: string): TaskRow[];
|
|
27
|
+
/** Return a single task by id, or undefined if not found. */
|
|
28
|
+
export declare function getTask(id: string, dbRoot?: string): TaskRow | undefined;
|
|
29
|
+
/** Send SIGTERM to the task's pid and mark it failed. Returns ok/message. */
|
|
30
|
+
export declare function killTask(id: string, dbRoot?: string): {
|
|
31
|
+
ok: boolean;
|
|
32
|
+
message: string;
|
|
33
|
+
};
|