cyrus-edge-worker 0.2.61 → 0.2.63
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/ChatSessionHandler.d.ts +23 -4
- package/dist/ChatSessionHandler.d.ts.map +1 -1
- package/dist/ChatSessionHandler.js +49 -17
- package/dist/ChatSessionHandler.js.map +1 -1
- package/dist/ConfigManager.d.ts.map +1 -1
- package/dist/ConfigManager.js +4 -0
- package/dist/ConfigManager.js.map +1 -1
- package/dist/EdgeWorker.d.ts +8 -0
- package/dist/EdgeWorker.d.ts.map +1 -1
- package/dist/EdgeWorker.js +31 -3
- package/dist/EdgeWorker.js.map +1 -1
- package/dist/GitService.d.ts +14 -0
- package/dist/GitService.d.ts.map +1 -1
- package/dist/GitService.js +26 -0
- package/dist/GitService.js.map +1 -1
- package/dist/RunnerConfigBuilder.d.ts.map +1 -1
- package/dist/RunnerConfigBuilder.js +3 -2
- package/dist/RunnerConfigBuilder.js.map +1 -1
- package/dist/RunnerSelectionService.d.ts.map +1 -1
- package/dist/RunnerSelectionService.js +13 -8
- package/dist/RunnerSelectionService.js.map +1 -1
- package/dist/SlackChatAdapter.d.ts +50 -0
- package/dist/SlackChatAdapter.d.ts.map +1 -1
- package/dist/SlackChatAdapter.js +97 -2
- package/dist/SlackChatAdapter.js.map +1 -1
- package/dist/prompts/cloudRuntimePromptAddendum.d.ts +22 -0
- package/dist/prompts/cloudRuntimePromptAddendum.d.ts.map +1 -0
- package/dist/prompts/cloudRuntimePromptAddendum.js +57 -0
- package/dist/prompts/cloudRuntimePromptAddendum.js.map +1 -0
- package/package.json +17 -17
package/dist/SlackChatAdapter.js
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
import { createLogger } from "cyrus-core";
|
|
2
2
|
import { SlackMessageService, SlackReactionService, stripMention as stripSlackMention, } from "cyrus-slack-event-transport";
|
|
3
|
+
/**
|
|
4
|
+
* Sentinel the agent emits when it has decided a Slack message does not warrant
|
|
5
|
+
* a reply. `postReply` recognizes it and stays silent instead of posting.
|
|
6
|
+
*
|
|
7
|
+
* This is what makes the "only respond when relevant" policy in the system
|
|
8
|
+
* prompt actually take effect: because every completed turn would otherwise be
|
|
9
|
+
* posted back to the thread, the agent needs an explicit way to say "nothing to
|
|
10
|
+
* post here". Kept as a single constant so the prompt and the suppression check
|
|
11
|
+
* can never drift apart.
|
|
12
|
+
*/
|
|
13
|
+
export const SLACK_NO_RESPONSE_SENTINEL = "<<NO_RESPONSE>>";
|
|
14
|
+
/**
|
|
15
|
+
* Route of the hosted Behaviours settings page (relative to the Cyrus app
|
|
16
|
+
* base URL) where automatic Slack thread listening can be turned off.
|
|
17
|
+
*/
|
|
18
|
+
export const BEHAVIOURS_PAGE_ROUTE = "/settings/behaviours";
|
|
19
|
+
/** Reaction added when a message is received and queued for processing (👀) */
|
|
20
|
+
export const RECEIPT_REACTION = "eyes";
|
|
21
|
+
/** Reaction that replaces the receipt one once the agent finished its turn (✅) */
|
|
22
|
+
export const PROCESSED_REACTION = "white_check_mark";
|
|
3
23
|
/**
|
|
4
24
|
* Slack implementation of ChatPlatformAdapter.
|
|
5
25
|
*
|
|
@@ -11,12 +31,17 @@ export class SlackChatAdapter {
|
|
|
11
31
|
platformName = "slack";
|
|
12
32
|
repositoryProvider;
|
|
13
33
|
repositoryRoutingContext;
|
|
34
|
+
behavioursPageUrl;
|
|
14
35
|
logger;
|
|
15
36
|
selfBotId;
|
|
16
37
|
constructor(repositoryProvider, logger, options) {
|
|
17
38
|
this.repositoryProvider = repositoryProvider;
|
|
18
39
|
this.repositoryRoutingContext =
|
|
19
40
|
options?.repositoryRoutingContext?.trim() || "";
|
|
41
|
+
const appBaseUrl = options?.cyrusAppBaseUrl?.trim().replace(/\/+$/, "");
|
|
42
|
+
this.behavioursPageUrl = appBaseUrl
|
|
43
|
+
? `${appBaseUrl}${BEHAVIOURS_PAGE_ROUTE}`
|
|
44
|
+
: "";
|
|
20
45
|
this.logger = logger ?? createLogger({ component: "SlackChatAdapter" });
|
|
21
46
|
}
|
|
22
47
|
/**
|
|
@@ -48,6 +73,23 @@ export class SlackChatAdapter {
|
|
|
48
73
|
extractTaskInstructions(event) {
|
|
49
74
|
return (stripSlackMention(event.payload.text) || "Ask the user for more context");
|
|
50
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Decide whether an event may start a session when the runtime has no
|
|
78
|
+
* in-memory binding for its thread.
|
|
79
|
+
*
|
|
80
|
+
* - An explicit @mention always may.
|
|
81
|
+
* - A plain `message` event may only when it was upstream-gated (proxy mode):
|
|
82
|
+
* CYHOST forwards `message` events solely for threads it has a persistent
|
|
83
|
+
* binding row for, so reaching us means the thread is genuinely bound. This
|
|
84
|
+
* is what lets Cyrus keep answering follow-ups after a process restart wipes
|
|
85
|
+
* the in-memory binding — the prior Slack thread is rehydrated via
|
|
86
|
+
* `fetchThreadContext`. In direct mode (`upstreamGated` false) there is no
|
|
87
|
+
* such guarantee, so an unbound plain message is ignored to avoid starting a
|
|
88
|
+
* session for arbitrary channel chatter.
|
|
89
|
+
*/
|
|
90
|
+
isSessionInitiatingEvent(event) {
|
|
91
|
+
return event.eventType === "app_mention" || event.upstreamGated === true;
|
|
92
|
+
}
|
|
51
93
|
getThreadKey(event) {
|
|
52
94
|
const threadTs = event.payload.thread_ts || event.payload.ts;
|
|
53
95
|
return `${event.payload.channel}:${threadTs}`;
|
|
@@ -72,12 +114,30 @@ ${repositoryPaths.map((path) => `- ${path}`).join("\n")}
|
|
|
72
114
|
: `
|
|
73
115
|
## Repository Access
|
|
74
116
|
- No repository paths are configured for this chat session.`;
|
|
75
|
-
|
|
117
|
+
const stopListeningSection = this.behavioursPageUrl
|
|
118
|
+
? `
|
|
119
|
+
|
|
120
|
+
## Stopping Automatic Listening
|
|
121
|
+
- If the user asks you to stop listening to, following, or responding in this thread:
|
|
122
|
+
- Tell them automatic thread listening can be turned off on the Behaviours page: <${this.behavioursPageUrl}|Behaviours page>.
|
|
123
|
+
- From that point on, treat this thread as muted: stay silent (emit \`${SLACK_NO_RESPONSE_SENTINEL}\` and nothing else) for every subsequent message until someone asks you a direct question — addressing you by name ("Cyrus, …") or with an @mention. When you resume responding, just answer — do not announce that you are listening again.`
|
|
124
|
+
: "";
|
|
125
|
+
return `You are participating in a Slack thread.
|
|
76
126
|
|
|
77
127
|
## Context
|
|
78
128
|
- **Requested by**: ${event.payload.user}
|
|
79
129
|
- **Channel**: ${event.payload.channel}
|
|
80
130
|
|
|
131
|
+
## When to Respond (IMPORTANT)
|
|
132
|
+
- After you are first @mentioned, you receive **every** subsequent message in this thread, not just the ones aimed at you. Do not treat every message as a request for you.
|
|
133
|
+
- Respond ONLY when at least one of these is true:
|
|
134
|
+
1. The message asks a question you can genuinely and helpfully answer, OR
|
|
135
|
+
2. Someone addresses you directly — by name ("Cyrus, …") or with an @mention.
|
|
136
|
+
- For anything else — side conversation between people, acknowledgements ("thanks", "👍"), status chatter, or messages clearly not directed at you — do NOT reply.
|
|
137
|
+
- When you should stay silent, output exactly \`${SLACK_NO_RESPONSE_SENTINEL}\` and nothing else — no reasoning, no explanation, not a single word before or after the token.
|
|
138
|
+
- NEVER narrate your decision about whether to respond. Your entire output is posted verbatim to the thread — there is no private scratchpad. Thoughts like "the user didn't address me by name, so I should stay quiet" or "they addressed me by name, so I'm listening again" must never appear in your output. Either emit the bare token, or reply directly to the user's message as if the decision never happened.
|
|
139
|
+
- When you do respond, be genuinely helpful and concise.${stopListeningSection}
|
|
140
|
+
|
|
81
141
|
## Instructions
|
|
82
142
|
- You are running in a transient workspace, not associated with any code repository
|
|
83
143
|
- Be concise in your responses as they will be posted back to Slack
|
|
@@ -171,6 +231,17 @@ Supported mrkdwn syntax:
|
|
|
171
231
|
summary = textBlock.text;
|
|
172
232
|
}
|
|
173
233
|
}
|
|
234
|
+
// The agent emits the no-response sentinel when it judged this message
|
|
235
|
+
// didn't warrant a reply (see the "When to Respond" system prompt
|
|
236
|
+
// section). Honor that by posting nothing. Deliberately a substring
|
|
237
|
+
// check, not an exact match: agents sometimes narrate their reasoning
|
|
238
|
+
// around the token despite being told not to, and that deliberation
|
|
239
|
+
// must never reach the thread — the token's presence anywhere means
|
|
240
|
+
// "do not post".
|
|
241
|
+
if (summary.includes(SLACK_NO_RESPONSE_SENTINEL)) {
|
|
242
|
+
this.logger.info(`Slack agent opted not to respond in channel ${event.payload.channel} (no-response sentinel)`);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
174
245
|
const token = this.getSlackBotToken(event);
|
|
175
246
|
if (!token) {
|
|
176
247
|
this.logger.warn("Cannot post Slack reply: no slackBotToken available");
|
|
@@ -200,9 +271,33 @@ Supported mrkdwn syntax:
|
|
|
200
271
|
token,
|
|
201
272
|
channel: event.payload.channel,
|
|
202
273
|
timestamp: event.payload.ts,
|
|
203
|
-
name:
|
|
274
|
+
name: RECEIPT_REACTION,
|
|
204
275
|
});
|
|
205
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* Swap the receipt reaction (👀) for a processed one (✅) once the agent
|
|
279
|
+
* has finished its turn for this message. This runs whether or not a reply
|
|
280
|
+
* was posted, so users can tell a silently-skipped message was still seen.
|
|
281
|
+
*/
|
|
282
|
+
async acknowledgeProcessed(event) {
|
|
283
|
+
const token = this.getSlackBotToken(event);
|
|
284
|
+
if (!token) {
|
|
285
|
+
this.logger.warn("Cannot update Slack reaction: no slackBotToken available (SLACK_BOT_TOKEN env var not set)");
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const reactionService = new SlackReactionService();
|
|
289
|
+
const target = {
|
|
290
|
+
token,
|
|
291
|
+
channel: event.payload.channel,
|
|
292
|
+
timestamp: event.payload.ts,
|
|
293
|
+
};
|
|
294
|
+
// Remove the receipt reaction before adding the processed one so the
|
|
295
|
+
// two are never visible together — the swap reads as a clean
|
|
296
|
+
// transition. (Slack has no atomic swap; if the add fails the message
|
|
297
|
+
// is briefly indicator-less, which beats showing both.)
|
|
298
|
+
await reactionService.removeReaction({ ...target, name: RECEIPT_REACTION });
|
|
299
|
+
await reactionService.addReaction({ ...target, name: PROCESSED_REACTION });
|
|
300
|
+
}
|
|
206
301
|
async notifyBusy(event) {
|
|
207
302
|
const token = this.getSlackBotToken(event);
|
|
208
303
|
if (!token) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SlackChatAdapter.js","sourceRoot":"","sources":["../src/SlackChatAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACN,mBAAmB,EACnB,oBAAoB,EAGpB,YAAY,IAAI,iBAAiB,GACjC,MAAM,6BAA6B,CAAC;AAIrC;;;;;;GAMG;AACH,MAAM,OAAO,gBAAgB;IAGnB,YAAY,GAAG,OAAgB,CAAC;IACjC,kBAAkB,CAAyB;IAC3C,wBAAwB,CAAS;IACjC,MAAM,CAAU;IAChB,SAAS,CAAqB;IAEtC,YACC,kBAA0C,EAC1C,MAAgB,EAChB,
|
|
1
|
+
{"version":3,"file":"SlackChatAdapter.js","sourceRoot":"","sources":["../src/SlackChatAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional system-prompt addendum for Cyrus-managed cloud runtimes.
|
|
3
|
+
*
|
|
4
|
+
* On our managed cloud runtimes the dev environment's system-wide packages
|
|
5
|
+
* (`apt` / global `npm`) are provisioned out-of-band from a curated list the
|
|
6
|
+
* user controls at https://app.atcyrus.com/settings/packages. When the agent
|
|
7
|
+
* finds a package missing, installing it ad-hoc inside the session won't
|
|
8
|
+
* persist and may fail on permissions — the correct remedy is to tell the user
|
|
9
|
+
* to add it via that settings page.
|
|
10
|
+
*
|
|
11
|
+
* Only injected when the environment variable `CYRUS_CLOUD_RUNTIME` is set to a
|
|
12
|
+
* truthy value. cyrus-hosted sets this on cloud-runtime droplets and leaves it
|
|
13
|
+
* unset for self-host runtimes (where the user manages their own packages).
|
|
14
|
+
*/
|
|
15
|
+
export declare const CLOUD_RUNTIME_PROMPT_ADDENDUM: string;
|
|
16
|
+
/**
|
|
17
|
+
* Append the cloud-runtime addendum to a system prompt fragment, but only when
|
|
18
|
+
* the `CYRUS_CLOUD_RUNTIME` env var is truthy. Returns the existing prompt
|
|
19
|
+
* unchanged otherwise.
|
|
20
|
+
*/
|
|
21
|
+
export declare function appendCloudRuntimeAddendum(existing: string | undefined | null): string;
|
|
22
|
+
//# sourceMappingURL=cloudRuntimePromptAddendum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudRuntimePromptAddendum.d.ts","sourceRoot":"","sources":["../../src/prompts/cloudRuntimePromptAddendum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,6BAA6B,QAoBlC,CAAC;AAET;;;;GAIG;AACH,wBAAgB,0BAA0B,CACzC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GACjC,MAAM,CAOR"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional system-prompt addendum for Cyrus-managed cloud runtimes.
|
|
3
|
+
*
|
|
4
|
+
* On our managed cloud runtimes the dev environment's system-wide packages
|
|
5
|
+
* (`apt` / global `npm`) are provisioned out-of-band from a curated list the
|
|
6
|
+
* user controls at https://app.atcyrus.com/settings/packages. When the agent
|
|
7
|
+
* finds a package missing, installing it ad-hoc inside the session won't
|
|
8
|
+
* persist and may fail on permissions — the correct remedy is to tell the user
|
|
9
|
+
* to add it via that settings page.
|
|
10
|
+
*
|
|
11
|
+
* Only injected when the environment variable `CYRUS_CLOUD_RUNTIME` is set to a
|
|
12
|
+
* truthy value. cyrus-hosted sets this on cloud-runtime droplets and leaves it
|
|
13
|
+
* unset for self-host runtimes (where the user manages their own packages).
|
|
14
|
+
*/
|
|
15
|
+
export const CLOUD_RUNTIME_PROMPT_ADDENDUM = `
|
|
16
|
+
<cloud_runtime_packages>
|
|
17
|
+
You are running on a Cyrus-managed cloud runtime. The system-wide packages
|
|
18
|
+
available in this environment (\`apt\` packages and global \`npm\` packages) can be
|
|
19
|
+
extended in the Cyrus dashboard.
|
|
20
|
+
|
|
21
|
+
If you discover that a system package, tool, or CLI binary you need is **not
|
|
22
|
+
installed** (for example \`command not found\`, a missing \`apt\` package, or a
|
|
23
|
+
missing global \`npm\` package), do NOT try to install it yourself with
|
|
24
|
+
\`sudo apt install\` / \`npm install -g\` — changes like that will not persist
|
|
25
|
+
across runtime restarts and may fail due to permissions.
|
|
26
|
+
|
|
27
|
+
Instead:
|
|
28
|
+
- Tell the user to visit https://app.atcyrus.com/settings/packages and add the
|
|
29
|
+
required \`apt\` or \`npm\` package(s) there.
|
|
30
|
+
- Name the exact package(s) you need and briefly explain why.
|
|
31
|
+
- Inform the user that after they have installed the packages, they may reprompt in order to continue the work, unblocked.
|
|
32
|
+
- Continue with any work you can complete without the missing package, and
|
|
33
|
+
clearly call out what remains blocked until they install it.
|
|
34
|
+
</cloud_runtime_packages>
|
|
35
|
+
`.trim();
|
|
36
|
+
/**
|
|
37
|
+
* Append the cloud-runtime addendum to a system prompt fragment, but only when
|
|
38
|
+
* the `CYRUS_CLOUD_RUNTIME` env var is truthy. Returns the existing prompt
|
|
39
|
+
* unchanged otherwise.
|
|
40
|
+
*/
|
|
41
|
+
export function appendCloudRuntimeAddendum(existing) {
|
|
42
|
+
const base = (existing ?? "").trimEnd();
|
|
43
|
+
if (!isCloudRuntimeEnabled()) {
|
|
44
|
+
return existing ?? "";
|
|
45
|
+
}
|
|
46
|
+
if (base.length === 0)
|
|
47
|
+
return CLOUD_RUNTIME_PROMPT_ADDENDUM;
|
|
48
|
+
return `${base}\n\n${CLOUD_RUNTIME_PROMPT_ADDENDUM}`;
|
|
49
|
+
}
|
|
50
|
+
function isCloudRuntimeEnabled() {
|
|
51
|
+
const raw = process.env.CYRUS_CLOUD_RUNTIME;
|
|
52
|
+
if (!raw)
|
|
53
|
+
return false;
|
|
54
|
+
const normalized = raw.trim().toLowerCase();
|
|
55
|
+
return normalized === "1" || normalized === "true" || normalized === "yes";
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=cloudRuntimePromptAddendum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudRuntimePromptAddendum.js","sourceRoot":"","sources":["../../src/prompts/cloudRuntimePromptAddendum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG;;;;;;;;;;;;;;;;;;;;CAoB5C,CAAC,IAAI,EAAE,CAAC;AAET;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CACzC,QAAmC;IAEnC,MAAM,IAAI,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;IACxC,IAAI,CAAC,qBAAqB,EAAE,EAAE,CAAC;QAC9B,OAAO,QAAQ,IAAI,EAAE,CAAC;IACvB,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,6BAA6B,CAAC;IAC5D,OAAO,GAAG,IAAI,OAAO,6BAA6B,EAAE,CAAC;AACtD,CAAC;AAED,SAAS,qBAAqB;IAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAC5C,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,OAAO,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,KAAK,CAAC;AAC5E,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cyrus-edge-worker",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.63",
|
|
4
4
|
"description": "Unified edge worker for processing Linear issues with Claude",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"prompts"
|
|
14
14
|
],
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@anthropic-ai/claude-agent-sdk": "0.3.
|
|
16
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.170",
|
|
17
17
|
"@linear/sdk": "^64.0.0",
|
|
18
18
|
"@ngrok/ngrok": "^1.5.1",
|
|
19
19
|
"chokidar": "^4.0.3",
|
|
@@ -23,27 +23,27 @@
|
|
|
23
23
|
"ignore": "^7.0.5",
|
|
24
24
|
"node-forge": "^1.4.0",
|
|
25
25
|
"zod": "4.3.6",
|
|
26
|
-
"cyrus-claude-runner": "0.2.
|
|
27
|
-
"cyrus-cloudflare-tunnel-client": "0.2.
|
|
28
|
-
"cyrus-
|
|
29
|
-
"cyrus-
|
|
30
|
-
"cyrus-
|
|
31
|
-
"cyrus-
|
|
32
|
-
"cyrus-github-event-transport": "0.2.
|
|
33
|
-
"cyrus-
|
|
34
|
-
"cyrus-
|
|
35
|
-
"cyrus-
|
|
36
|
-
"cyrus-
|
|
37
|
-
"cyrus-
|
|
38
|
-
"cyrus-
|
|
26
|
+
"cyrus-claude-runner": "0.2.63",
|
|
27
|
+
"cyrus-cloudflare-tunnel-client": "0.2.63",
|
|
28
|
+
"cyrus-config-updater": "0.2.63",
|
|
29
|
+
"cyrus-codex-runner": "0.2.63",
|
|
30
|
+
"cyrus-core": "0.2.63",
|
|
31
|
+
"cyrus-cursor-runner": "0.2.63",
|
|
32
|
+
"cyrus-github-event-transport": "0.2.63",
|
|
33
|
+
"cyrus-simple-agent-runner": "0.2.63",
|
|
34
|
+
"cyrus-gitlab-event-transport": "0.2.63",
|
|
35
|
+
"cyrus-mcp-tools": "0.2.63",
|
|
36
|
+
"cyrus-linear-event-transport": "0.2.63",
|
|
37
|
+
"cyrus-gemini-runner": "0.2.63",
|
|
38
|
+
"cyrus-slack-event-transport": "0.2.63"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^20.0.0",
|
|
42
42
|
"@types/node-forge": "^1.3.14",
|
|
43
|
-
"@vitest/coverage-v8": "^
|
|
43
|
+
"@vitest/coverage-v8": "^4.1.0",
|
|
44
44
|
"axios": "^1.16.0",
|
|
45
45
|
"typescript": "^5.3.3",
|
|
46
|
-
"vitest": "^
|
|
46
|
+
"vitest": "^4.1.0",
|
|
47
47
|
"vitest-mock-extended": "^3.1.0"
|
|
48
48
|
},
|
|
49
49
|
"publishConfig": {
|