replicas-engine 0.1.34 → 0.1.36
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
CHANGED
|
@@ -716,6 +716,21 @@ var MessageQueue = class {
|
|
|
716
716
|
clearQueue() {
|
|
717
717
|
this.queue = [];
|
|
718
718
|
}
|
|
719
|
+
drainQueue(options) {
|
|
720
|
+
const maxItems = options?.maxItems ?? this.queue.length;
|
|
721
|
+
const maxChars = options?.maxChars ?? Number.POSITIVE_INFINITY;
|
|
722
|
+
const drained = [];
|
|
723
|
+
let totalChars = 0;
|
|
724
|
+
for (const message of this.queue) {
|
|
725
|
+
if (drained.length >= maxItems) break;
|
|
726
|
+
const text = message.message;
|
|
727
|
+
if (totalChars + text.length > maxChars) break;
|
|
728
|
+
drained.push(text);
|
|
729
|
+
totalChars += text.length;
|
|
730
|
+
}
|
|
731
|
+
this.queue = [];
|
|
732
|
+
return drained;
|
|
733
|
+
}
|
|
719
734
|
/**
|
|
720
735
|
* Reset everything including clearing processing state
|
|
721
736
|
*/
|
|
@@ -746,12 +761,19 @@ function inferMediaType(url, contentType) {
|
|
|
746
761
|
}
|
|
747
762
|
async function fetchImageAsBase64(url) {
|
|
748
763
|
const headers = {};
|
|
749
|
-
|
|
764
|
+
const hostname = new URL(url).hostname;
|
|
765
|
+
if (hostname === "uploads.linear.app") {
|
|
750
766
|
const token = process.env.LINEAR_TOKEN;
|
|
751
767
|
if (token) {
|
|
752
768
|
headers["Authorization"] = `Bearer ${token}`;
|
|
753
769
|
}
|
|
754
770
|
}
|
|
771
|
+
if (hostname === "files.slack.com") {
|
|
772
|
+
const token = process.env.SLACK_BOT_TOKEN;
|
|
773
|
+
if (token) {
|
|
774
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
755
777
|
const response = await fetch(url, { headers });
|
|
756
778
|
if (!response.ok) {
|
|
757
779
|
throw new Error(`Failed to fetch image from ${url}: ${response.status} ${response.statusText}`);
|
|
@@ -1009,6 +1031,8 @@ var replicasConfigService = new ReplicasConfigService();
|
|
|
1009
1031
|
import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
|
|
1010
1032
|
var DEFAULT_MODEL = "gpt-5.2-codex";
|
|
1011
1033
|
var CODEX_CONFIG_PATH = join3(homedir3(), ".codex", "config.toml");
|
|
1034
|
+
var MAX_INTERRUPT_QUEUE_ITEMS = 1e3;
|
|
1035
|
+
var MAX_INTERRUPT_QUEUE_CHARS = 2e5;
|
|
1012
1036
|
var CodexManager = class {
|
|
1013
1037
|
codex;
|
|
1014
1038
|
currentThreadId = null;
|
|
@@ -1018,6 +1042,7 @@ var CodexManager = class {
|
|
|
1018
1042
|
baseSystemPrompt;
|
|
1019
1043
|
tempImageDir;
|
|
1020
1044
|
initialized;
|
|
1045
|
+
activeAbortController = null;
|
|
1021
1046
|
constructor(workingDirectory) {
|
|
1022
1047
|
this.codex = new Codex();
|
|
1023
1048
|
if (workingDirectory) {
|
|
@@ -1060,6 +1085,33 @@ var CodexManager = class {
|
|
|
1060
1085
|
getQueueStatus() {
|
|
1061
1086
|
return this.messageQueue.getStatus();
|
|
1062
1087
|
}
|
|
1088
|
+
async interrupt() {
|
|
1089
|
+
const queue = this.messageQueue.drainQueue({
|
|
1090
|
+
maxItems: MAX_INTERRUPT_QUEUE_ITEMS,
|
|
1091
|
+
maxChars: MAX_INTERRUPT_QUEUE_CHARS
|
|
1092
|
+
});
|
|
1093
|
+
const isProcessing = this.messageQueue.isProcessing();
|
|
1094
|
+
if (isProcessing && this.activeAbortController) {
|
|
1095
|
+
try {
|
|
1096
|
+
this.activeAbortController.abort();
|
|
1097
|
+
} catch {
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
const linearSessionId = process.env.LINEAR_SESSION_ID;
|
|
1101
|
+
if (linearSessionId && queue.length > 0) {
|
|
1102
|
+
const body = ["Interrupted. Cleared queue:", ...queue].join("\n");
|
|
1103
|
+
const thoughtEvent = {
|
|
1104
|
+
linearSessionId,
|
|
1105
|
+
content: {
|
|
1106
|
+
type: "thought",
|
|
1107
|
+
body
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1110
|
+
monolithService.sendEvent({ type: "agent_update", payload: thoughtEvent }).catch(() => {
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
return { interrupted: isProcessing || queue.length > 0, queue };
|
|
1114
|
+
}
|
|
1063
1115
|
/**
|
|
1064
1116
|
* Set the base system prompt from replicas.json
|
|
1065
1117
|
* This will be combined with any custom instructions passed to individual messages
|
|
@@ -1165,11 +1217,13 @@ var CodexManager = class {
|
|
|
1165
1217
|
model: model || DEFAULT_MODEL,
|
|
1166
1218
|
webSearchMode: "live"
|
|
1167
1219
|
};
|
|
1220
|
+
const abortController = new AbortController();
|
|
1221
|
+
this.activeAbortController = abortController;
|
|
1168
1222
|
if (this.currentThreadId) {
|
|
1169
1223
|
this.currentThread = this.codex.resumeThread(this.currentThreadId, threadOptions);
|
|
1170
1224
|
} else {
|
|
1171
1225
|
this.currentThread = this.codex.startThread(threadOptions);
|
|
1172
|
-
const { events: events2 } = await this.currentThread.runStreamed("Hello");
|
|
1226
|
+
const { events: events2 } = await this.currentThread.runStreamed("Hello", { signal: abortController.signal });
|
|
1173
1227
|
for await (const event of events2) {
|
|
1174
1228
|
if (event.type === "thread.started") {
|
|
1175
1229
|
this.currentThreadId = event.thread_id;
|
|
@@ -1193,7 +1247,7 @@ var CodexManager = class {
|
|
|
1193
1247
|
} else {
|
|
1194
1248
|
input = message;
|
|
1195
1249
|
}
|
|
1196
|
-
const { events } = await this.currentThread.runStreamed(input);
|
|
1250
|
+
const { events } = await this.currentThread.runStreamed(input, { signal: abortController.signal });
|
|
1197
1251
|
let latestThoughtEvent = null;
|
|
1198
1252
|
for await (const event of events) {
|
|
1199
1253
|
if (linearSessionId) {
|
|
@@ -1219,6 +1273,7 @@ var CodexManager = class {
|
|
|
1219
1273
|
});
|
|
1220
1274
|
}
|
|
1221
1275
|
} finally {
|
|
1276
|
+
this.activeAbortController = null;
|
|
1222
1277
|
const status = await getGitStatus(this.workingDirectory);
|
|
1223
1278
|
const payload = linearSessionId ? { linearSessionId, status } : { status };
|
|
1224
1279
|
monolithService.sendEvent({ type: "agent_turn_complete", payload }).catch(() => {
|
|
@@ -1507,6 +1562,22 @@ codex.post("/reset", async (c) => {
|
|
|
1507
1562
|
);
|
|
1508
1563
|
}
|
|
1509
1564
|
});
|
|
1565
|
+
codex.post("/interrupt", async (c) => {
|
|
1566
|
+
try {
|
|
1567
|
+
const result = await codexManager.interrupt();
|
|
1568
|
+
const response = result;
|
|
1569
|
+
return c.json(response);
|
|
1570
|
+
} catch (error) {
|
|
1571
|
+
console.error("Error in /codex/interrupt:", error);
|
|
1572
|
+
return c.json(
|
|
1573
|
+
{
|
|
1574
|
+
error: "Failed to interrupt thread",
|
|
1575
|
+
details: error instanceof Error ? error.message : "Unknown error"
|
|
1576
|
+
},
|
|
1577
|
+
500
|
|
1578
|
+
);
|
|
1579
|
+
}
|
|
1580
|
+
});
|
|
1510
1581
|
var codex_default = codex;
|
|
1511
1582
|
|
|
1512
1583
|
// src/routes/claude.ts
|
|
@@ -1519,6 +1590,8 @@ import {
|
|
|
1519
1590
|
import { join as join4 } from "path";
|
|
1520
1591
|
import { mkdir as mkdir4, appendFile as appendFile2, rm } from "fs/promises";
|
|
1521
1592
|
import { homedir as homedir4 } from "os";
|
|
1593
|
+
var MAX_INTERRUPT_QUEUE_ITEMS2 = 1e3;
|
|
1594
|
+
var MAX_INTERRUPT_QUEUE_CHARS2 = 2e5;
|
|
1522
1595
|
var ClaudeManager = class {
|
|
1523
1596
|
workingDirectory;
|
|
1524
1597
|
historyFile;
|
|
@@ -1526,6 +1599,7 @@ var ClaudeManager = class {
|
|
|
1526
1599
|
initialized;
|
|
1527
1600
|
messageQueue;
|
|
1528
1601
|
baseSystemPrompt;
|
|
1602
|
+
activeQuery = null;
|
|
1529
1603
|
constructor(workingDirectory) {
|
|
1530
1604
|
if (workingDirectory) {
|
|
1531
1605
|
this.workingDirectory = workingDirectory;
|
|
@@ -1560,6 +1634,33 @@ var ClaudeManager = class {
|
|
|
1560
1634
|
getQueueStatus() {
|
|
1561
1635
|
return this.messageQueue.getStatus();
|
|
1562
1636
|
}
|
|
1637
|
+
async interrupt() {
|
|
1638
|
+
const queue = this.messageQueue.drainQueue({
|
|
1639
|
+
maxItems: MAX_INTERRUPT_QUEUE_ITEMS2,
|
|
1640
|
+
maxChars: MAX_INTERRUPT_QUEUE_CHARS2
|
|
1641
|
+
});
|
|
1642
|
+
const isProcessing = this.messageQueue.isProcessing();
|
|
1643
|
+
if (isProcessing && this.activeQuery) {
|
|
1644
|
+
try {
|
|
1645
|
+
await this.activeQuery.interrupt();
|
|
1646
|
+
} catch {
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
const linearSessionId = process.env.LINEAR_SESSION_ID;
|
|
1650
|
+
if (linearSessionId && queue.length > 0) {
|
|
1651
|
+
const body = ["Interrupted. Cleared queue:", ...queue].join("\n");
|
|
1652
|
+
const thoughtEvent = {
|
|
1653
|
+
linearSessionId,
|
|
1654
|
+
content: {
|
|
1655
|
+
type: "thought",
|
|
1656
|
+
body
|
|
1657
|
+
}
|
|
1658
|
+
};
|
|
1659
|
+
monolithService.sendEvent({ type: "agent_update", payload: thoughtEvent }).catch(() => {
|
|
1660
|
+
});
|
|
1661
|
+
}
|
|
1662
|
+
return { interrupted: isProcessing || queue.length > 0, queue };
|
|
1663
|
+
}
|
|
1563
1664
|
/**
|
|
1564
1665
|
* Set the base system prompt from replicas.json
|
|
1565
1666
|
* This will be combined with any custom instructions passed to individual messages
|
|
@@ -1667,6 +1768,7 @@ var ClaudeManager = class {
|
|
|
1667
1768
|
model: model || "opus"
|
|
1668
1769
|
}
|
|
1669
1770
|
});
|
|
1771
|
+
this.activeQuery = response;
|
|
1670
1772
|
let latestThoughtEvent = null;
|
|
1671
1773
|
for await (const msg of response) {
|
|
1672
1774
|
await this.handleMessage(msg);
|
|
@@ -1693,6 +1795,7 @@ var ClaudeManager = class {
|
|
|
1693
1795
|
});
|
|
1694
1796
|
}
|
|
1695
1797
|
} finally {
|
|
1798
|
+
this.activeQuery = null;
|
|
1696
1799
|
const status = await getGitStatus(this.workingDirectory);
|
|
1697
1800
|
const payload = linearSessionId ? { linearSessionId, status } : { status };
|
|
1698
1801
|
monolithService.sendEvent({ type: "agent_turn_complete", payload }).catch(() => {
|
|
@@ -1919,6 +2022,22 @@ claude.post("/reset", async (c) => {
|
|
|
1919
2022
|
);
|
|
1920
2023
|
}
|
|
1921
2024
|
});
|
|
2025
|
+
claude.post("/interrupt", async (c) => {
|
|
2026
|
+
try {
|
|
2027
|
+
const result = await claudeManager.interrupt();
|
|
2028
|
+
const response = result;
|
|
2029
|
+
return c.json(response);
|
|
2030
|
+
} catch (error) {
|
|
2031
|
+
console.error("Error in /claude/interrupt:", error);
|
|
2032
|
+
return c.json(
|
|
2033
|
+
{
|
|
2034
|
+
error: "Failed to interrupt session",
|
|
2035
|
+
details: error instanceof Error ? error.message : "Unknown error"
|
|
2036
|
+
},
|
|
2037
|
+
500
|
|
2038
|
+
);
|
|
2039
|
+
}
|
|
2040
|
+
});
|
|
1922
2041
|
var claude_default = claude;
|
|
1923
2042
|
|
|
1924
2043
|
// src/routes/plans.ts
|
|
@@ -2104,6 +2223,10 @@ var ClaudeTokenManager = class {
|
|
|
2104
2223
|
REFRESH_INTERVAL_MS = 45 * 60 * 1e3;
|
|
2105
2224
|
// 45 minutes
|
|
2106
2225
|
async start() {
|
|
2226
|
+
if (process.env.ANTHROPIC_API_KEY) {
|
|
2227
|
+
console.log("[ClaudeTokenManager] Skipping: ANTHROPIC_API_KEY is set");
|
|
2228
|
+
return;
|
|
2229
|
+
}
|
|
2107
2230
|
const monolithUrl = process.env.MONOLITH_URL;
|
|
2108
2231
|
const workspaceId = process.env.WORKSPACE_ID;
|
|
2109
2232
|
const engineSecret = process.env.REPLICAS_ENGINE_SECRET;
|
|
@@ -2128,6 +2251,9 @@ var ClaudeTokenManager = class {
|
|
|
2128
2251
|
}
|
|
2129
2252
|
}
|
|
2130
2253
|
async refreshCredentials() {
|
|
2254
|
+
if (process.env.ANTHROPIC_API_KEY) {
|
|
2255
|
+
return;
|
|
2256
|
+
}
|
|
2131
2257
|
const monolithUrl = process.env.MONOLITH_URL;
|
|
2132
2258
|
const workspaceId = process.env.WORKSPACE_ID;
|
|
2133
2259
|
const engineSecret = process.env.REPLICAS_ENGINE_SECRET;
|
|
@@ -167,8 +167,8 @@ var require_utils = __commonJS({
|
|
|
167
167
|
Object.defineProperty(target, keys[i], Object.getOwnPropertyDescriptor(source, keys[i]));
|
|
168
168
|
}
|
|
169
169
|
};
|
|
170
|
-
module.exports.wrapperSymbol =
|
|
171
|
-
module.exports.implSymbol =
|
|
170
|
+
module.exports.wrapperSymbol = Symbol("wrapper");
|
|
171
|
+
module.exports.implSymbol = Symbol("impl");
|
|
172
172
|
module.exports.wrapperForImpl = function(impl) {
|
|
173
173
|
return impl[module.exports.wrapperSymbol];
|
|
174
174
|
};
|
|
@@ -361,7 +361,7 @@ var require_url_state_machine = __commonJS({
|
|
|
361
361
|
ws: 80,
|
|
362
362
|
wss: 443
|
|
363
363
|
};
|
|
364
|
-
var failure =
|
|
364
|
+
var failure = Symbol("failure");
|
|
365
365
|
function countSymbols(str) {
|
|
366
366
|
return punycode.ucs2.decode(str).length;
|
|
367
367
|
}
|
|
@@ -1787,8 +1787,8 @@ var require_lib2 = __commonJS({
|
|
|
1787
1787
|
var https = _interopDefault(__require("https"));
|
|
1788
1788
|
var zlib = _interopDefault(__require("zlib"));
|
|
1789
1789
|
var Readable = Stream.Readable;
|
|
1790
|
-
var BUFFER =
|
|
1791
|
-
var TYPE =
|
|
1790
|
+
var BUFFER = Symbol("buffer");
|
|
1791
|
+
var TYPE = Symbol("type");
|
|
1792
1792
|
var Blob = class _Blob {
|
|
1793
1793
|
constructor() {
|
|
1794
1794
|
this[TYPE] = "";
|
|
@@ -1899,7 +1899,7 @@ var require_lib2 = __commonJS({
|
|
|
1899
1899
|
FetchError.prototype.constructor = FetchError;
|
|
1900
1900
|
FetchError.prototype.name = "FetchError";
|
|
1901
1901
|
var convert;
|
|
1902
|
-
var INTERNALS =
|
|
1902
|
+
var INTERNALS = Symbol("Body internals");
|
|
1903
1903
|
var PassThrough = Stream.PassThrough;
|
|
1904
1904
|
function Body(body) {
|
|
1905
1905
|
var _this = this;
|
|
@@ -2239,7 +2239,7 @@ var require_lib2 = __commonJS({
|
|
|
2239
2239
|
}
|
|
2240
2240
|
return void 0;
|
|
2241
2241
|
}
|
|
2242
|
-
var MAP =
|
|
2242
|
+
var MAP = Symbol("map");
|
|
2243
2243
|
var Headers = class _Headers {
|
|
2244
2244
|
/**
|
|
2245
2245
|
* Headers class
|
|
@@ -2447,7 +2447,7 @@ var require_lib2 = __commonJS({
|
|
|
2447
2447
|
return [k.toLowerCase(), headers[MAP][k].join(", ")];
|
|
2448
2448
|
});
|
|
2449
2449
|
}
|
|
2450
|
-
var INTERNAL =
|
|
2450
|
+
var INTERNAL = Symbol("internal");
|
|
2451
2451
|
function createHeadersIterator(target, kind) {
|
|
2452
2452
|
const iterator = Object.create(HeadersIteratorPrototype);
|
|
2453
2453
|
iterator[INTERNAL] = {
|
|
@@ -2516,7 +2516,7 @@ var require_lib2 = __commonJS({
|
|
|
2516
2516
|
}
|
|
2517
2517
|
return headers;
|
|
2518
2518
|
}
|
|
2519
|
-
var INTERNALS$1 =
|
|
2519
|
+
var INTERNALS$1 = Symbol("Response internals");
|
|
2520
2520
|
var STATUS_CODES = http.STATUS_CODES;
|
|
2521
2521
|
var Response = class _Response {
|
|
2522
2522
|
constructor() {
|
|
@@ -2592,7 +2592,7 @@ var require_lib2 = __commonJS({
|
|
|
2592
2592
|
enumerable: false,
|
|
2593
2593
|
configurable: true
|
|
2594
2594
|
});
|
|
2595
|
-
var INTERNALS$2 =
|
|
2595
|
+
var INTERNALS$2 = Symbol("Request internals");
|
|
2596
2596
|
var URL = Url.URL || whatwgUrl.URL;
|
|
2597
2597
|
var parse_url = Url.parse;
|
|
2598
2598
|
var format_url = Url.format;
|