replicas-engine 0.1.568 → 0.1.570
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 +62 -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\\"}],
|
|
@@ -3439,6 +3439,10 @@ function findPrMergeSignals(request) {
|
|
|
3439
3439
|
return checks.flatMap(([name, pattern]) => pattern.test(combined) ? [name] : []);
|
|
3440
3440
|
}
|
|
3441
3441
|
|
|
3442
|
+
// ../shared/src/routes/client-state.ts
|
|
3443
|
+
var MAX_CLIENT_STATE_REQUEST_BYTES = 5 * 1024 * 1024;
|
|
3444
|
+
var MAX_CLIENT_STATE_BYTES_PER_USER = 10 * 1024 * 1024;
|
|
3445
|
+
|
|
3442
3446
|
// ../shared/src/routes/workspaces.ts
|
|
3443
3447
|
var WORKSPACE_STATUSES = ["active", "sleeping", "archived", "preparing", "error"];
|
|
3444
3448
|
var WORKSPACE_STATUS_FILTERS = WORKSPACE_STATUSES.map((status) => status === "error" ? "failed" : status);
|
|
@@ -5583,7 +5587,7 @@ function loadEngineEnv() {
|
|
|
5583
5587
|
WORKSPACE_ID: readEnv("WORKSPACE_ID"),
|
|
5584
5588
|
LINEAR_SESSION_ID: readEnv("LINEAR_SESSION_ID"),
|
|
5585
5589
|
LINEAR_ACCESS_TOKEN: readEnv("LINEAR_ACCESS_TOKEN"),
|
|
5586
|
-
|
|
5590
|
+
REPLICAS_SLACK_BOT_TOKEN: readEnv("REPLICAS_SLACK_BOT_TOKEN"),
|
|
5587
5591
|
SLACK_CHANNEL_ID: readEnv("SLACK_CHANNEL_ID"),
|
|
5588
5592
|
SLACK_THREAD_TS: readEnv("SLACK_THREAD_TS"),
|
|
5589
5593
|
ANTHROPIC_API_KEY: readEnv("ANTHROPIC_API_KEY"),
|
|
@@ -7218,7 +7222,7 @@ var EnvironmentDetailsService = class {
|
|
|
7218
7222
|
details.gitlabAccessConfigured = gitlabAccessConfigured;
|
|
7219
7223
|
details.gitlabCredentialsConfigured = gitlabAccessConfigured;
|
|
7220
7224
|
details.linearAccessConfigured = Boolean(ENGINE_ENV.LINEAR_SESSION_ID || ENGINE_ENV.LINEAR_ACCESS_TOKEN);
|
|
7221
|
-
details.slackAccessConfigured = Boolean(ENGINE_ENV.
|
|
7225
|
+
details.slackAccessConfigured = Boolean(ENGINE_ENV.REPLICAS_SLACK_BOT_TOKEN);
|
|
7222
7226
|
const freshRepos = repositories.map((repo) => ({
|
|
7223
7227
|
repositoryName: repo.name,
|
|
7224
7228
|
warmHookCompleted: "n/a",
|
|
@@ -8407,9 +8411,9 @@ async function fetchImageAsBase64(url, linearAccessToken) {
|
|
|
8407
8411
|
}
|
|
8408
8412
|
}
|
|
8409
8413
|
if (hostname === "files.slack.com") {
|
|
8410
|
-
const token = ENGINE_ENV.
|
|
8414
|
+
const token = ENGINE_ENV.REPLICAS_SLACK_BOT_TOKEN;
|
|
8411
8415
|
if (!token) {
|
|
8412
|
-
throw new Error(`Cannot fetch Slack file from ${url}:
|
|
8416
|
+
throw new Error(`Cannot fetch Slack file from ${url}: REPLICAS_SLACK_BOT_TOKEN is not configured`);
|
|
8413
8417
|
}
|
|
8414
8418
|
headers["Authorization"] = `Bearer ${token}`;
|
|
8415
8419
|
}
|
|
@@ -10776,7 +10780,7 @@ var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
|
10776
10780
|
var MIN_CODEX_CLI_VERSION = "0.144.6";
|
|
10777
10781
|
var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
|
|
10778
10782
|
var codexCliVersionEnsured = null;
|
|
10779
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
10783
|
+
var ENGINE_PACKAGE_VERSION = "0.1.570";
|
|
10780
10784
|
var INITIALIZE_METHOD = "initialize";
|
|
10781
10785
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
10782
10786
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -11071,6 +11075,7 @@ var THREAD_GOAL_SET_METHOD = "thread/goal/set";
|
|
|
11071
11075
|
var THREAD_GOAL_GET_METHOD = "thread/goal/get";
|
|
11072
11076
|
var THREAD_GOAL_CLEAR_METHOD = "thread/goal/clear";
|
|
11073
11077
|
var THREAD_COMPACT_START_METHOD = "thread/compact/start";
|
|
11078
|
+
var THREAD_INJECT_ITEMS_METHOD = "thread/inject_items";
|
|
11074
11079
|
var THREAD_SETTINGS_UPDATE_METHOD = "thread/settings/update";
|
|
11075
11080
|
var TURN_START_METHOD = "turn/start";
|
|
11076
11081
|
var TURN_INTERRUPT_METHOD = "turn/interrupt";
|
|
@@ -11743,6 +11748,10 @@ var DuplicateDefaultChatError = class extends Error {
|
|
|
11743
11748
|
// src/managers/codex-asp/codex-asp-manager.ts
|
|
11744
11749
|
var GOAL_TURN_CONTINUATION_GRACE_MS = 5e3;
|
|
11745
11750
|
var CODEX_SLASH_COMMANDS_CACHE_MS = 3e4;
|
|
11751
|
+
var POLICY_REASON_INJECTION_TIMEOUT_MS = 5e3;
|
|
11752
|
+
function formatBlockedCommandReason(reason) {
|
|
11753
|
+
return reason?.includes("Blocked by organization policy") ? reason : `Blocked by organization policy: ${reason || "agents may not merge pull requests."}`;
|
|
11754
|
+
}
|
|
11746
11755
|
async function readCodexAspThreadHistory(threadId) {
|
|
11747
11756
|
let entries;
|
|
11748
11757
|
try {
|
|
@@ -12498,6 +12507,11 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
12498
12507
|
serverRequest.params.cwd,
|
|
12499
12508
|
serverRequest.params.commandActions
|
|
12500
12509
|
);
|
|
12510
|
+
await this.injectBlockedCommandReason(
|
|
12511
|
+
host,
|
|
12512
|
+
serverRequest.params.threadId,
|
|
12513
|
+
result.reason
|
|
12514
|
+
);
|
|
12501
12515
|
host.client.respond(requestId, { decision: "decline" });
|
|
12502
12516
|
return;
|
|
12503
12517
|
}
|
|
@@ -12534,6 +12548,11 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
12534
12548
|
serverRequest.params.cwd,
|
|
12535
12549
|
[{ type: "unknown", command }]
|
|
12536
12550
|
);
|
|
12551
|
+
await this.injectBlockedCommandReason(
|
|
12552
|
+
host,
|
|
12553
|
+
this.currentThreadId ?? serverRequest.params.conversationId,
|
|
12554
|
+
result.reason
|
|
12555
|
+
);
|
|
12537
12556
|
host.client.respond(requestId, { decision: "denied" });
|
|
12538
12557
|
return;
|
|
12539
12558
|
}
|
|
@@ -12584,11 +12603,38 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
12584
12603
|
}
|
|
12585
12604
|
host.client.reject(requestId, -32601, `Replicas does not support ASP server request ${method}`);
|
|
12586
12605
|
}
|
|
12606
|
+
async injectBlockedCommandReason(host, threadId, reason) {
|
|
12607
|
+
try {
|
|
12608
|
+
await host.client.request(
|
|
12609
|
+
THREAD_INJECT_ITEMS_METHOD,
|
|
12610
|
+
{
|
|
12611
|
+
threadId,
|
|
12612
|
+
items: [{
|
|
12613
|
+
type: "message",
|
|
12614
|
+
role: "developer",
|
|
12615
|
+
content: [{
|
|
12616
|
+
type: "input_text",
|
|
12617
|
+
text: [
|
|
12618
|
+
"<organization_policy>",
|
|
12619
|
+
"The command currently awaiting approval was rejected for this reason:",
|
|
12620
|
+
formatBlockedCommandReason(reason),
|
|
12621
|
+
"Do not retry the blocked command unchanged. Adjust your approach to comply with this policy.",
|
|
12622
|
+
"</organization_policy>"
|
|
12623
|
+
].join("\n")
|
|
12624
|
+
}]
|
|
12625
|
+
}]
|
|
12626
|
+
},
|
|
12627
|
+
{ timeoutMs: POLICY_REASON_INJECTION_TIMEOUT_MS }
|
|
12628
|
+
);
|
|
12629
|
+
} catch (error) {
|
|
12630
|
+
console.warn("[CodexAspManager] Failed to inject blocked command reason:", error);
|
|
12631
|
+
}
|
|
12632
|
+
}
|
|
12587
12633
|
nextTranscriptSequence() {
|
|
12588
12634
|
return this.codexAspSequence++;
|
|
12589
12635
|
}
|
|
12590
12636
|
recordBlockedCommand(threadId, turnId, itemId, command, reason, startedAtMs, cwd, commandActions) {
|
|
12591
|
-
const output = reason
|
|
12637
|
+
const output = formatBlockedCommandReason(reason);
|
|
12592
12638
|
const timestamp = timestampFromMilliseconds(startedAtMs);
|
|
12593
12639
|
const blockedItem = {
|
|
12594
12640
|
type: "commandExecution",
|