replicas-engine 0.1.258 → 0.1.260
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/README.md +6 -6
- package/dist/src/index.js +110 -47
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,10 +31,10 @@ Chats:
|
|
|
31
31
|
- `POST /chats/:chatId/messages`
|
|
32
32
|
- `POST /chats/:chatId/interrupt`
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
Canvas:
|
|
35
35
|
|
|
36
|
-
- `GET /
|
|
37
|
-
- `GET /
|
|
36
|
+
- `GET /canvas`
|
|
37
|
+
- `GET /canvas/:filename`
|
|
38
38
|
|
|
39
39
|
Repos and hooks:
|
|
40
40
|
|
|
@@ -93,9 +93,9 @@ Engine persistence locations:
|
|
|
93
93
|
- `~/.replicas/engine/events.jsonl`
|
|
94
94
|
- `~/.replicas/engine-state.json`
|
|
95
95
|
- `~/.replicas/startHooks.log`
|
|
96
|
-
-
|
|
97
|
-
- `~/.claude/plans`
|
|
98
|
-
- `~/.replicas/
|
|
96
|
+
- Canvas read locations (for `/canvas` endpoints):
|
|
97
|
+
- `~/.claude/plans` (where Claude Code writes its plans)
|
|
98
|
+
- `~/.replicas/canvas`
|
|
99
99
|
- Health endpoint readiness signal file:
|
|
100
100
|
- `/var/log/cloud-init-output.log` (if missing, `/health` reports `initializing`)
|
|
101
101
|
|
package/dist/src/index.js
CHANGED
|
@@ -127,7 +127,7 @@ function detectLanguageByPath(filePath) {
|
|
|
127
127
|
|
|
128
128
|
// ../shared/src/context-usage.ts
|
|
129
129
|
var CODEX_CATEGORY_COLORS = {
|
|
130
|
-
input: "#
|
|
130
|
+
input: "#3eeba3",
|
|
131
131
|
output: "#56b6c2"
|
|
132
132
|
};
|
|
133
133
|
function clampPercentage(value) {
|
|
@@ -286,7 +286,7 @@ var WORKSPACE_SIZES = ["small", "large"];
|
|
|
286
286
|
var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
|
|
287
287
|
|
|
288
288
|
// ../shared/src/e2b.ts
|
|
289
|
-
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-
|
|
289
|
+
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-04-v2";
|
|
290
290
|
|
|
291
291
|
// ../shared/src/runtime-env.ts
|
|
292
292
|
function parsePosixEnvFile(content) {
|
|
@@ -1643,6 +1643,7 @@ var DEFAULT_DEFAULT_SKILLS = {
|
|
|
1643
1643
|
};
|
|
1644
1644
|
|
|
1645
1645
|
// ../shared/src/prompts.ts
|
|
1646
|
+
var MAX_CODEX_GOAL_OBJECTIVE_CHARS = 4e3;
|
|
1646
1647
|
function parseGoalCommand(message) {
|
|
1647
1648
|
const match = message.trim().match(/^\/goal(?:\s+([\s\S]*))?$/i);
|
|
1648
1649
|
const value = match?.[1]?.trim();
|
|
@@ -1650,6 +1651,13 @@ function parseGoalCommand(message) {
|
|
|
1650
1651
|
if (/^(clear|reset|unset)$/i.test(value)) return { type: "clear" };
|
|
1651
1652
|
return { type: "set", objective: value };
|
|
1652
1653
|
}
|
|
1654
|
+
function getGoalCommandObjectiveValidationError(message) {
|
|
1655
|
+
const command = parseGoalCommand(message);
|
|
1656
|
+
if (command?.type !== "set") return null;
|
|
1657
|
+
const length = command.objective.length;
|
|
1658
|
+
if (length <= MAX_CODEX_GOAL_OBJECTIVE_CHARS) return null;
|
|
1659
|
+
return `Goal objective must be at most ${MAX_CODEX_GOAL_OBJECTIVE_CHARS} characters (${length} provided). Shorten the /goal objective, or send the extra details as a regular message after setting the goal.`;
|
|
1660
|
+
}
|
|
1653
1661
|
|
|
1654
1662
|
// ../shared/src/replicas-config.ts
|
|
1655
1663
|
import { parse as parseYaml } from "yaml";
|
|
@@ -1831,6 +1839,29 @@ var MODEL_LABELS = {
|
|
|
1831
1839
|
"gpt-5": "GPT-5"
|
|
1832
1840
|
};
|
|
1833
1841
|
var IMAGE_MEDIA_TYPES = ["image/png", "image/jpeg", "image/gif", "image/webp"];
|
|
1842
|
+
var CANVAS_KIND_BY_EXTENSION = {
|
|
1843
|
+
".md": { kind: "markdown", mimeType: "text/markdown; charset=utf-8" },
|
|
1844
|
+
".markdown": { kind: "markdown", mimeType: "text/markdown; charset=utf-8" },
|
|
1845
|
+
".html": { kind: "html", mimeType: "text/html; charset=utf-8" },
|
|
1846
|
+
".htm": { kind: "html", mimeType: "text/html; charset=utf-8" },
|
|
1847
|
+
".png": { kind: "image", mimeType: "image/png" },
|
|
1848
|
+
".jpg": { kind: "image", mimeType: "image/jpeg" },
|
|
1849
|
+
".jpeg": { kind: "image", mimeType: "image/jpeg" },
|
|
1850
|
+
".gif": { kind: "image", mimeType: "image/gif" },
|
|
1851
|
+
".webp": { kind: "image", mimeType: "image/webp" },
|
|
1852
|
+
".svg": { kind: "image", mimeType: "image/svg+xml" },
|
|
1853
|
+
".mp4": { kind: "video", mimeType: "video/mp4" },
|
|
1854
|
+
".webm": { kind: "video", mimeType: "video/webm" },
|
|
1855
|
+
".mov": { kind: "video", mimeType: "video/quicktime" },
|
|
1856
|
+
".mp3": { kind: "audio", mimeType: "audio/mpeg" },
|
|
1857
|
+
".wav": { kind: "audio", mimeType: "audio/wav" },
|
|
1858
|
+
".ogg": { kind: "audio", mimeType: "audio/ogg" }
|
|
1859
|
+
};
|
|
1860
|
+
function classifyCanvasFilename(filename) {
|
|
1861
|
+
const idx = filename.lastIndexOf(".");
|
|
1862
|
+
const ext = idx === -1 ? "" : filename.slice(idx).toLowerCase();
|
|
1863
|
+
return CANVAS_KIND_BY_EXTENSION[ext] ?? { kind: "other", mimeType: "application/octet-stream" };
|
|
1864
|
+
}
|
|
1834
1865
|
|
|
1835
1866
|
// ../shared/src/engine/v1.ts
|
|
1836
1867
|
var MERGED_MESSAGE_SEPARATOR = "\n\n<!-- replicas:merged -->\n\n";
|
|
@@ -6341,7 +6372,7 @@ var AspClient = class {
|
|
|
6341
6372
|
// src/managers/codex-asp/app-server-process.ts
|
|
6342
6373
|
var DEFAULT_CODEX_BINARY = "codex";
|
|
6343
6374
|
var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
6344
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
6375
|
+
var ENGINE_PACKAGE_VERSION = "0.1.260";
|
|
6345
6376
|
var INITIALIZE_METHOD = "initialize";
|
|
6346
6377
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
6347
6378
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -9896,60 +9927,88 @@ var RepoFileService = class {
|
|
|
9896
9927
|
// src/v1-routes.ts
|
|
9897
9928
|
import { Hono } from "hono";
|
|
9898
9929
|
import { z as z2 } from "zod";
|
|
9899
|
-
import { readdir as readdir6, stat as
|
|
9930
|
+
import { readdir as readdir6, stat as stat5, readFile as readFile14 } from "fs/promises";
|
|
9900
9931
|
import { join as join20, resolve as resolve2 } from "path";
|
|
9901
9932
|
|
|
9902
|
-
// src/services/
|
|
9903
|
-
import { readdir as readdir4, readFile as readFile11 } from "fs/promises";
|
|
9933
|
+
// src/services/canvas-service.ts
|
|
9934
|
+
import { readdir as readdir4, readFile as readFile11, stat as stat4 } from "fs/promises";
|
|
9904
9935
|
import { homedir as homedir14 } from "os";
|
|
9905
9936
|
import { basename, join as join17 } from "path";
|
|
9906
|
-
var
|
|
9937
|
+
var CANVAS_DIRECTORIES = [
|
|
9907
9938
|
join17(homedir14(), ".claude", "plans"),
|
|
9908
|
-
join17(homedir14(), ".replicas", "
|
|
9939
|
+
join17(homedir14(), ".replicas", "canvas")
|
|
9909
9940
|
];
|
|
9910
|
-
|
|
9911
|
-
|
|
9941
|
+
var MAX_CANVAS_FILE_BYTES = 5 * 1024 * 1024;
|
|
9942
|
+
function isTextKind(kind) {
|
|
9943
|
+
return kind === "markdown" || kind === "html";
|
|
9912
9944
|
}
|
|
9913
|
-
function
|
|
9945
|
+
function sanitizeFilename(filename) {
|
|
9914
9946
|
return basename(filename);
|
|
9915
9947
|
}
|
|
9916
|
-
var
|
|
9917
|
-
async
|
|
9918
|
-
const
|
|
9919
|
-
for (const directory of
|
|
9948
|
+
var CanvasService = class {
|
|
9949
|
+
async listItems() {
|
|
9950
|
+
const items = /* @__PURE__ */ new Map();
|
|
9951
|
+
for (const directory of CANVAS_DIRECTORIES) {
|
|
9952
|
+
let entries;
|
|
9920
9953
|
try {
|
|
9921
|
-
|
|
9922
|
-
for (const entry of entries) {
|
|
9923
|
-
if (!entry.isFile()) {
|
|
9924
|
-
continue;
|
|
9925
|
-
}
|
|
9926
|
-
if (!isMarkdownFile(entry.name)) {
|
|
9927
|
-
continue;
|
|
9928
|
-
}
|
|
9929
|
-
planNames.add(entry.name);
|
|
9930
|
-
}
|
|
9954
|
+
entries = await readdir4(directory, { withFileTypes: true });
|
|
9931
9955
|
} catch {
|
|
9956
|
+
continue;
|
|
9957
|
+
}
|
|
9958
|
+
for (const entry of entries) {
|
|
9959
|
+
if (!entry.isFile()) continue;
|
|
9960
|
+
if (entry.name.startsWith(".")) continue;
|
|
9961
|
+
if (items.has(entry.name)) continue;
|
|
9962
|
+
const { kind } = classifyCanvasFilename(entry.name);
|
|
9963
|
+
let sizeBytes = 0;
|
|
9964
|
+
try {
|
|
9965
|
+
const s = await stat4(join17(directory, entry.name));
|
|
9966
|
+
sizeBytes = s.size;
|
|
9967
|
+
} catch {
|
|
9968
|
+
continue;
|
|
9969
|
+
}
|
|
9970
|
+
items.set(entry.name, { filename: entry.name, kind, sizeBytes });
|
|
9932
9971
|
}
|
|
9933
9972
|
}
|
|
9934
|
-
return Array.from(
|
|
9973
|
+
return Array.from(items.values()).sort((a, b) => a.filename.localeCompare(b.filename));
|
|
9935
9974
|
}
|
|
9936
|
-
async
|
|
9937
|
-
const
|
|
9938
|
-
if (!
|
|
9939
|
-
|
|
9940
|
-
|
|
9941
|
-
|
|
9942
|
-
|
|
9975
|
+
async getItem(filename) {
|
|
9976
|
+
const safe = sanitizeFilename(filename);
|
|
9977
|
+
if (!safe || safe !== filename || safe.startsWith(".")) return null;
|
|
9978
|
+
const { kind, mimeType } = classifyCanvasFilename(safe);
|
|
9979
|
+
for (const directory of CANVAS_DIRECTORIES) {
|
|
9980
|
+
const filePath = join17(directory, safe);
|
|
9981
|
+
let sizeBytes = 0;
|
|
9982
|
+
try {
|
|
9983
|
+
const s = await stat4(filePath);
|
|
9984
|
+
sizeBytes = s.size;
|
|
9985
|
+
} catch {
|
|
9986
|
+
continue;
|
|
9987
|
+
}
|
|
9988
|
+
if (sizeBytes > MAX_CANVAS_FILE_BYTES) {
|
|
9989
|
+
return {
|
|
9990
|
+
filename: safe,
|
|
9991
|
+
kind,
|
|
9992
|
+
sizeBytes,
|
|
9993
|
+
mimeType,
|
|
9994
|
+
tooLarge: true
|
|
9995
|
+
};
|
|
9996
|
+
}
|
|
9943
9997
|
try {
|
|
9944
|
-
|
|
9945
|
-
|
|
9998
|
+
if (isTextKind(kind)) {
|
|
9999
|
+
const content = await readFile11(filePath, "utf-8");
|
|
10000
|
+
return { filename: safe, kind, sizeBytes, mimeType, content };
|
|
10001
|
+
}
|
|
10002
|
+
const buf = await readFile11(filePath);
|
|
10003
|
+
return { filename: safe, kind, sizeBytes, mimeType, base64: buf.toString("base64") };
|
|
9946
10004
|
} catch {
|
|
10005
|
+
continue;
|
|
9947
10006
|
}
|
|
9948
10007
|
}
|
|
9949
10008
|
return null;
|
|
9950
10009
|
}
|
|
9951
10010
|
};
|
|
9952
|
-
var
|
|
10011
|
+
var canvasService = new CanvasService();
|
|
9953
10012
|
|
|
9954
10013
|
// src/services/warm-hooks-service.ts
|
|
9955
10014
|
import { spawn as spawn4 } from "child_process";
|
|
@@ -10516,6 +10575,10 @@ function createV1Routes(deps) {
|
|
|
10516
10575
|
app2.post("/chats/:chatId/messages", async (c) => {
|
|
10517
10576
|
try {
|
|
10518
10577
|
const body = sendMessageSchema.parse(await c.req.json());
|
|
10578
|
+
const goalValidationError = getGoalCommandObjectiveValidationError(body.message);
|
|
10579
|
+
if (goalValidationError) {
|
|
10580
|
+
return c.json(jsonError(goalValidationError), 400);
|
|
10581
|
+
}
|
|
10519
10582
|
const result = await deps.chatService.sendMessage(c.req.param("chatId"), body);
|
|
10520
10583
|
return c.json(result);
|
|
10521
10584
|
} catch (error) {
|
|
@@ -10636,31 +10699,31 @@ function createV1Routes(deps) {
|
|
|
10636
10699
|
}
|
|
10637
10700
|
return c.json(result);
|
|
10638
10701
|
});
|
|
10639
|
-
app2.get("/
|
|
10702
|
+
app2.get("/canvas", async (c) => {
|
|
10640
10703
|
try {
|
|
10641
|
-
const
|
|
10642
|
-
return c.json({
|
|
10704
|
+
const items = await canvasService.listItems();
|
|
10705
|
+
return c.json({ items });
|
|
10643
10706
|
} catch (error) {
|
|
10644
10707
|
return c.json(
|
|
10645
|
-
jsonError("Failed to list
|
|
10708
|
+
jsonError("Failed to list canvas items", error instanceof Error ? error.message : "Unknown error"),
|
|
10646
10709
|
500
|
|
10647
10710
|
);
|
|
10648
10711
|
}
|
|
10649
10712
|
});
|
|
10650
|
-
app2.get("/
|
|
10713
|
+
app2.get("/canvas/:filename", async (c) => {
|
|
10651
10714
|
try {
|
|
10652
10715
|
const filename = c.req.param("filename");
|
|
10653
10716
|
if (!filename) {
|
|
10654
10717
|
return c.json(jsonError("Filename required"), 400);
|
|
10655
10718
|
}
|
|
10656
|
-
const
|
|
10657
|
-
if (!
|
|
10658
|
-
return c.json(jsonError("
|
|
10719
|
+
const item = await canvasService.getItem(filename);
|
|
10720
|
+
if (!item) {
|
|
10721
|
+
return c.json(jsonError("Canvas item not found"), 404);
|
|
10659
10722
|
}
|
|
10660
|
-
return c.json(
|
|
10723
|
+
return c.json(item);
|
|
10661
10724
|
} catch (error) {
|
|
10662
10725
|
return c.json(
|
|
10663
|
-
jsonError("Failed to read
|
|
10726
|
+
jsonError("Failed to read canvas item", error instanceof Error ? error.message : "Unknown error"),
|
|
10664
10727
|
500
|
|
10665
10728
|
);
|
|
10666
10729
|
}
|
|
@@ -10974,7 +11037,7 @@ function createV1Routes(deps) {
|
|
|
10974
11037
|
const sessions = await Promise.all(
|
|
10975
11038
|
logFiles.map(async (filename) => {
|
|
10976
11039
|
const filePath = join20(LOG_DIR, filename);
|
|
10977
|
-
const fileStat = await
|
|
11040
|
+
const fileStat = await stat5(filePath);
|
|
10978
11041
|
const sessionId = filename.replace(/\.log$/, "");
|
|
10979
11042
|
return {
|
|
10980
11043
|
sessionId,
|