replicas-engine 0.1.568 → 0.1.569
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/src/index.js +58 -16
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -2114,7 +2114,7 @@ LENGTH=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
|
|
|
2114
2114
|
|
|
2115
2115
|
# 1. Reserve an upload URL + file ID.
|
|
2116
2116
|
RESERVE=$(curl -s -G "https://slack.com/api/files.getUploadURLExternal" \\
|
|
2117
|
-
-H "Authorization: Bearer $
|
|
2117
|
+
-H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN" \\
|
|
2118
2118
|
--data-urlencode "filename=$FILENAME" \\
|
|
2119
2119
|
--data-urlencode "length=$LENGTH")
|
|
2120
2120
|
UPLOAD_URL=$(echo "$RESERVE" | jq -r '.upload_url')
|
|
@@ -2129,7 +2129,7 @@ curl -s -X POST "$UPLOAD_URL" \\
|
|
|
2129
2129
|
|
|
2130
2130
|
# 3. Complete the upload, sharing it into the channel/thread with the dashboard link.
|
|
2131
2131
|
curl -s -X POST "https://slack.com/api/files.completeUploadExternal" \\
|
|
2132
|
-
-H "Authorization: Bearer $
|
|
2132
|
+
-H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN" \\
|
|
2133
2133
|
-H "Content-Type: application/json; charset=utf-8" \\
|
|
2134
2134
|
-d "{
|
|
2135
2135
|
\\"files\\": [{\\"id\\": \\"$FILE_ID\\", \\"title\\": \\"Screenshot\\"}],
|
|
@@ -2640,10 +2640,10 @@ This guide covers how to interact with Slack from within your Replicas workspace
|
|
|
2640
2640
|
|
|
2641
2641
|
## Prerequisites
|
|
2642
2642
|
|
|
2643
|
-
Check if the \`
|
|
2643
|
+
Check if the \`REPLICAS_SLACK_BOT_TOKEN\` environment variable is set:
|
|
2644
2644
|
|
|
2645
2645
|
\`\`\`bash
|
|
2646
|
-
echo "\${
|
|
2646
|
+
echo "\${REPLICAS_SLACK_BOT_TOKEN:+set}"
|
|
2647
2647
|
\`\`\`
|
|
2648
2648
|
|
|
2649
2649
|
- If **set**: Your workspace has Slack access. You can use the Slack Web API as described below.
|
|
@@ -2651,7 +2651,7 @@ echo "\${SLACK_BOT_TOKEN:+set}"
|
|
|
2651
2651
|
|
|
2652
2652
|
## Using the Slack API
|
|
2653
2653
|
|
|
2654
|
-
All requests use the \`$
|
|
2654
|
+
All requests use the \`$REPLICAS_SLACK_BOT_TOKEN\` for authentication via the Slack Web API.
|
|
2655
2655
|
|
|
2656
2656
|
### Fetching a Thread from a Slack Link
|
|
2657
2657
|
|
|
@@ -2662,14 +2662,14 @@ If you encounter a Slack message link (e.g. \`https://team.slack.com/archives/C0
|
|
|
2662
2662
|
|
|
2663
2663
|
\`\`\`bash
|
|
2664
2664
|
curl -s "https://slack.com/api/conversations.replies?channel=CHANNEL_ID&ts=THREAD_TS" \\
|
|
2665
|
-
-H "Authorization: Bearer $
|
|
2665
|
+
-H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN"
|
|
2666
2666
|
\`\`\`
|
|
2667
2667
|
|
|
2668
2668
|
### Sending a Message
|
|
2669
2669
|
|
|
2670
2670
|
\`\`\`bash
|
|
2671
2671
|
curl -s -X POST "https://slack.com/api/chat.postMessage" \\
|
|
2672
|
-
-H "Authorization: Bearer $
|
|
2672
|
+
-H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN" \\
|
|
2673
2673
|
-H "Content-Type: application/json" \\
|
|
2674
2674
|
-d '{
|
|
2675
2675
|
"channel": "CHANNEL_ID",
|
|
@@ -2708,7 +2708,7 @@ The channel and thread flags default to \`SLACK_CHANNEL_ID\` and \`SLACK_THREAD_
|
|
|
2708
2708
|
|
|
2709
2709
|
\`\`\`bash
|
|
2710
2710
|
curl -s "https://slack.com/api/search.messages?query=YOUR_SEARCH_QUERY" \\
|
|
2711
|
-
-H "Authorization: Bearer $
|
|
2711
|
+
-H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN"
|
|
2712
2712
|
\`\`\`
|
|
2713
2713
|
|
|
2714
2714
|
### Uploading Files
|
|
@@ -2722,7 +2722,7 @@ LENGTH=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
|
|
|
2722
2722
|
|
|
2723
2723
|
# 1. Reserve an upload URL + file ID.
|
|
2724
2724
|
RESERVE=$(curl -s -G "https://slack.com/api/files.getUploadURLExternal" \\
|
|
2725
|
-
-H "Authorization: Bearer $
|
|
2725
|
+
-H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN" \\
|
|
2726
2726
|
--data-urlencode "filename=$FILENAME" \\
|
|
2727
2727
|
--data-urlencode "length=$LENGTH")
|
|
2728
2728
|
UPLOAD_URL=$(echo "$RESERVE" | jq -r '.upload_url')
|
|
@@ -2737,7 +2737,7 @@ curl -s -X POST "$UPLOAD_URL" \\
|
|
|
2737
2737
|
|
|
2738
2738
|
# 3. Complete the upload and share into a channel (and optionally a thread).
|
|
2739
2739
|
curl -s -X POST "https://slack.com/api/files.completeUploadExternal" \\
|
|
2740
|
-
-H "Authorization: Bearer $
|
|
2740
|
+
-H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN" \\
|
|
2741
2741
|
-H "Content-Type: application/json; charset=utf-8" \\
|
|
2742
2742
|
-d "{
|
|
2743
2743
|
\\"files\\": [{\\"id\\": \\"$FILE_ID\\", \\"title\\": \\"File title\\"}],
|
|
@@ -5583,7 +5583,7 @@ function loadEngineEnv() {
|
|
|
5583
5583
|
WORKSPACE_ID: readEnv("WORKSPACE_ID"),
|
|
5584
5584
|
LINEAR_SESSION_ID: readEnv("LINEAR_SESSION_ID"),
|
|
5585
5585
|
LINEAR_ACCESS_TOKEN: readEnv("LINEAR_ACCESS_TOKEN"),
|
|
5586
|
-
|
|
5586
|
+
REPLICAS_SLACK_BOT_TOKEN: readEnv("REPLICAS_SLACK_BOT_TOKEN"),
|
|
5587
5587
|
SLACK_CHANNEL_ID: readEnv("SLACK_CHANNEL_ID"),
|
|
5588
5588
|
SLACK_THREAD_TS: readEnv("SLACK_THREAD_TS"),
|
|
5589
5589
|
ANTHROPIC_API_KEY: readEnv("ANTHROPIC_API_KEY"),
|
|
@@ -7218,7 +7218,7 @@ var EnvironmentDetailsService = class {
|
|
|
7218
7218
|
details.gitlabAccessConfigured = gitlabAccessConfigured;
|
|
7219
7219
|
details.gitlabCredentialsConfigured = gitlabAccessConfigured;
|
|
7220
7220
|
details.linearAccessConfigured = Boolean(ENGINE_ENV.LINEAR_SESSION_ID || ENGINE_ENV.LINEAR_ACCESS_TOKEN);
|
|
7221
|
-
details.slackAccessConfigured = Boolean(ENGINE_ENV.
|
|
7221
|
+
details.slackAccessConfigured = Boolean(ENGINE_ENV.REPLICAS_SLACK_BOT_TOKEN);
|
|
7222
7222
|
const freshRepos = repositories.map((repo) => ({
|
|
7223
7223
|
repositoryName: repo.name,
|
|
7224
7224
|
warmHookCompleted: "n/a",
|
|
@@ -8407,9 +8407,9 @@ async function fetchImageAsBase64(url, linearAccessToken) {
|
|
|
8407
8407
|
}
|
|
8408
8408
|
}
|
|
8409
8409
|
if (hostname === "files.slack.com") {
|
|
8410
|
-
const token = ENGINE_ENV.
|
|
8410
|
+
const token = ENGINE_ENV.REPLICAS_SLACK_BOT_TOKEN;
|
|
8411
8411
|
if (!token) {
|
|
8412
|
-
throw new Error(`Cannot fetch Slack file from ${url}:
|
|
8412
|
+
throw new Error(`Cannot fetch Slack file from ${url}: REPLICAS_SLACK_BOT_TOKEN is not configured`);
|
|
8413
8413
|
}
|
|
8414
8414
|
headers["Authorization"] = `Bearer ${token}`;
|
|
8415
8415
|
}
|
|
@@ -10776,7 +10776,7 @@ var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
|
10776
10776
|
var MIN_CODEX_CLI_VERSION = "0.144.6";
|
|
10777
10777
|
var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
|
|
10778
10778
|
var codexCliVersionEnsured = null;
|
|
10779
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
10779
|
+
var ENGINE_PACKAGE_VERSION = "0.1.569";
|
|
10780
10780
|
var INITIALIZE_METHOD = "initialize";
|
|
10781
10781
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
10782
10782
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -11071,6 +11071,7 @@ var THREAD_GOAL_SET_METHOD = "thread/goal/set";
|
|
|
11071
11071
|
var THREAD_GOAL_GET_METHOD = "thread/goal/get";
|
|
11072
11072
|
var THREAD_GOAL_CLEAR_METHOD = "thread/goal/clear";
|
|
11073
11073
|
var THREAD_COMPACT_START_METHOD = "thread/compact/start";
|
|
11074
|
+
var THREAD_INJECT_ITEMS_METHOD = "thread/inject_items";
|
|
11074
11075
|
var THREAD_SETTINGS_UPDATE_METHOD = "thread/settings/update";
|
|
11075
11076
|
var TURN_START_METHOD = "turn/start";
|
|
11076
11077
|
var TURN_INTERRUPT_METHOD = "turn/interrupt";
|
|
@@ -11743,6 +11744,10 @@ var DuplicateDefaultChatError = class extends Error {
|
|
|
11743
11744
|
// src/managers/codex-asp/codex-asp-manager.ts
|
|
11744
11745
|
var GOAL_TURN_CONTINUATION_GRACE_MS = 5e3;
|
|
11745
11746
|
var CODEX_SLASH_COMMANDS_CACHE_MS = 3e4;
|
|
11747
|
+
var POLICY_REASON_INJECTION_TIMEOUT_MS = 5e3;
|
|
11748
|
+
function formatBlockedCommandReason(reason) {
|
|
11749
|
+
return reason?.includes("Blocked by organization policy") ? reason : `Blocked by organization policy: ${reason || "agents may not merge pull requests."}`;
|
|
11750
|
+
}
|
|
11746
11751
|
async function readCodexAspThreadHistory(threadId) {
|
|
11747
11752
|
let entries;
|
|
11748
11753
|
try {
|
|
@@ -12498,6 +12503,11 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
12498
12503
|
serverRequest.params.cwd,
|
|
12499
12504
|
serverRequest.params.commandActions
|
|
12500
12505
|
);
|
|
12506
|
+
await this.injectBlockedCommandReason(
|
|
12507
|
+
host,
|
|
12508
|
+
serverRequest.params.threadId,
|
|
12509
|
+
result.reason
|
|
12510
|
+
);
|
|
12501
12511
|
host.client.respond(requestId, { decision: "decline" });
|
|
12502
12512
|
return;
|
|
12503
12513
|
}
|
|
@@ -12534,6 +12544,11 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
12534
12544
|
serverRequest.params.cwd,
|
|
12535
12545
|
[{ type: "unknown", command }]
|
|
12536
12546
|
);
|
|
12547
|
+
await this.injectBlockedCommandReason(
|
|
12548
|
+
host,
|
|
12549
|
+
this.currentThreadId ?? serverRequest.params.conversationId,
|
|
12550
|
+
result.reason
|
|
12551
|
+
);
|
|
12537
12552
|
host.client.respond(requestId, { decision: "denied" });
|
|
12538
12553
|
return;
|
|
12539
12554
|
}
|
|
@@ -12584,11 +12599,38 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
12584
12599
|
}
|
|
12585
12600
|
host.client.reject(requestId, -32601, `Replicas does not support ASP server request ${method}`);
|
|
12586
12601
|
}
|
|
12602
|
+
async injectBlockedCommandReason(host, threadId, reason) {
|
|
12603
|
+
try {
|
|
12604
|
+
await host.client.request(
|
|
12605
|
+
THREAD_INJECT_ITEMS_METHOD,
|
|
12606
|
+
{
|
|
12607
|
+
threadId,
|
|
12608
|
+
items: [{
|
|
12609
|
+
type: "message",
|
|
12610
|
+
role: "developer",
|
|
12611
|
+
content: [{
|
|
12612
|
+
type: "input_text",
|
|
12613
|
+
text: [
|
|
12614
|
+
"<organization_policy>",
|
|
12615
|
+
"The command currently awaiting approval was rejected for this reason:",
|
|
12616
|
+
formatBlockedCommandReason(reason),
|
|
12617
|
+
"Do not retry the blocked command unchanged. Adjust your approach to comply with this policy.",
|
|
12618
|
+
"</organization_policy>"
|
|
12619
|
+
].join("\n")
|
|
12620
|
+
}]
|
|
12621
|
+
}]
|
|
12622
|
+
},
|
|
12623
|
+
{ timeoutMs: POLICY_REASON_INJECTION_TIMEOUT_MS }
|
|
12624
|
+
);
|
|
12625
|
+
} catch (error) {
|
|
12626
|
+
console.warn("[CodexAspManager] Failed to inject blocked command reason:", error);
|
|
12627
|
+
}
|
|
12628
|
+
}
|
|
12587
12629
|
nextTranscriptSequence() {
|
|
12588
12630
|
return this.codexAspSequence++;
|
|
12589
12631
|
}
|
|
12590
12632
|
recordBlockedCommand(threadId, turnId, itemId, command, reason, startedAtMs, cwd, commandActions) {
|
|
12591
|
-
const output = reason
|
|
12633
|
+
const output = formatBlockedCommandReason(reason);
|
|
12592
12634
|
const timestamp = timestampFromMilliseconds(startedAtMs);
|
|
12593
12635
|
const blockedItem = {
|
|
12594
12636
|
type: "commandExecution",
|