replicas-engine 0.1.328 → 0.1.329
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 +197 -54
- package/package.json +2 -1
package/dist/src/index.js
CHANGED
|
@@ -287,7 +287,7 @@ var WORKSPACE_SIZES = ["small", "large"];
|
|
|
287
287
|
var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
|
|
288
288
|
|
|
289
289
|
// ../shared/src/e2b.ts
|
|
290
|
-
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-19-
|
|
290
|
+
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-19-v3";
|
|
291
291
|
|
|
292
292
|
// ../shared/src/runtime-env.ts
|
|
293
293
|
function parsePosixEnvFile(content) {
|
|
@@ -2123,11 +2123,13 @@ var DESKTOP_NOVNC_PORT = 6080;
|
|
|
2123
2123
|
var DEFAULT_CHAT_TITLES = {
|
|
2124
2124
|
claude: "Claude Code",
|
|
2125
2125
|
codex: "Codex",
|
|
2126
|
+
cursor: "Cursor",
|
|
2126
2127
|
relay: "Relay"
|
|
2127
2128
|
};
|
|
2128
2129
|
var CLAUDE_OPUS_1M_MODEL = "opus[1m]";
|
|
2129
2130
|
var LEGACY_CLAUDE_OPUS_1M_MODEL = "opus-1m";
|
|
2130
2131
|
var DEFAULT_CODEX_MODEL = "gpt-5.5";
|
|
2132
|
+
var DEFAULT_CURSOR_MODEL = "composer-2";
|
|
2131
2133
|
function normalizeClaudeModel(model) {
|
|
2132
2134
|
if (model === LEGACY_CLAUDE_OPUS_1M_MODEL) {
|
|
2133
2135
|
return CLAUDE_OPUS_1M_MODEL;
|
|
@@ -2137,6 +2139,7 @@ function normalizeClaudeModel(model) {
|
|
|
2137
2139
|
var AGENT_MODELS = {
|
|
2138
2140
|
claude: [CLAUDE_OPUS_1M_MODEL, "sonnet", "haiku"],
|
|
2139
2141
|
codex: [DEFAULT_CODEX_MODEL, "gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex", "gpt-5.2"],
|
|
2142
|
+
cursor: [DEFAULT_CURSOR_MODEL, "composer-2.5"],
|
|
2140
2143
|
relay: [CLAUDE_OPUS_1M_MODEL, "sonnet"]
|
|
2141
2144
|
};
|
|
2142
2145
|
var MODEL_LABELS = {
|
|
@@ -2146,6 +2149,8 @@ var MODEL_LABELS = {
|
|
|
2146
2149
|
[LEGACY_CLAUDE_OPUS_1M_MODEL]: "Opus 4.8 (1M)",
|
|
2147
2150
|
haiku: "Haiku 4.5",
|
|
2148
2151
|
[DEFAULT_CODEX_MODEL]: "GPT-5.5",
|
|
2152
|
+
[DEFAULT_CURSOR_MODEL]: "Composer 2",
|
|
2153
|
+
"composer-2.5": "Composer 2.5",
|
|
2149
2154
|
"gpt-5.4": "GPT-5.4",
|
|
2150
2155
|
"gpt-5.4-mini": "GPT-5.4 Mini",
|
|
2151
2156
|
"gpt-5.3-codex": "GPT-5.3 Codex",
|
|
@@ -2825,6 +2830,7 @@ function loadEngineEnv() {
|
|
|
2825
2830
|
SLACK_THREAD_TS: readEnv("SLACK_THREAD_TS"),
|
|
2826
2831
|
ANTHROPIC_API_KEY: readEnv("ANTHROPIC_API_KEY"),
|
|
2827
2832
|
OPENAI_API_KEY: readEnv("OPENAI_API_KEY"),
|
|
2833
|
+
CURSOR_API_KEY: readEnv("CURSOR_API_KEY"),
|
|
2828
2834
|
CLAUDE_CODE_USE_BEDROCK: readEnv("CLAUDE_CODE_USE_BEDROCK"),
|
|
2829
2835
|
AWS_ACCESS_KEY_ID: readEnv("AWS_ACCESS_KEY_ID"),
|
|
2830
2836
|
AWS_SECRET_ACCESS_KEY: readEnv("AWS_SECRET_ACCESS_KEY"),
|
|
@@ -4198,6 +4204,9 @@ function detectCodexAuthMethod() {
|
|
|
4198
4204
|
}
|
|
4199
4205
|
return "none";
|
|
4200
4206
|
}
|
|
4207
|
+
function detectCursorAuthMethod() {
|
|
4208
|
+
return ENGINE_ENV.CURSOR_API_KEY ? "api_key" : "none";
|
|
4209
|
+
}
|
|
4201
4210
|
async function detectGitIdentityConfigured() {
|
|
4202
4211
|
try {
|
|
4203
4212
|
const { stdout } = await execFileAsync("git", ["config", "--global", "user.name"]);
|
|
@@ -4237,6 +4246,7 @@ function createDefaultDetails() {
|
|
|
4237
4246
|
googleAccessConfigured: false,
|
|
4238
4247
|
claudeAuthMethod: "none",
|
|
4239
4248
|
codexAuthMethod: "none",
|
|
4249
|
+
cursorAuthMethod: "none",
|
|
4240
4250
|
lastUpdatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4241
4251
|
};
|
|
4242
4252
|
}
|
|
@@ -4267,6 +4277,7 @@ var EnvironmentDetailsService = class {
|
|
|
4267
4277
|
details.engineVersion = E2B_TEMPLATE_NAME;
|
|
4268
4278
|
details.claudeAuthMethod = detectClaudeAuthMethod();
|
|
4269
4279
|
details.codexAuthMethod = detectCodexAuthMethod();
|
|
4280
|
+
details.cursorAuthMethod = detectCursorAuthMethod();
|
|
4270
4281
|
details.gitIdentityConfigured = gitIdentityConfigured;
|
|
4271
4282
|
const ghConfigured = existsSync3(GH_HOSTS_PATH);
|
|
4272
4283
|
details.githubAccessConfigured = ghConfigured;
|
|
@@ -5015,9 +5026,9 @@ async function registerDesktopPreview() {
|
|
|
5015
5026
|
|
|
5016
5027
|
// src/services/chat/chat-service.ts
|
|
5017
5028
|
import { existsSync as existsSync7 } from "fs";
|
|
5018
|
-
import { appendFile as
|
|
5029
|
+
import { appendFile as appendFile5, copyFile, mkdir as mkdir12, readFile as readFile13, rename as rename2, rm } from "fs/promises";
|
|
5019
5030
|
import { homedir as homedir14 } from "os";
|
|
5020
|
-
import { join as
|
|
5031
|
+
import { join as join18 } from "path";
|
|
5021
5032
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
5022
5033
|
|
|
5023
5034
|
// src/managers/claude-manager.ts
|
|
@@ -7291,7 +7302,7 @@ var AspClient = class {
|
|
|
7291
7302
|
// src/managers/codex-asp/app-server-process.ts
|
|
7292
7303
|
var DEFAULT_CODEX_BINARY = "codex";
|
|
7293
7304
|
var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
7294
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
7305
|
+
var ENGINE_PACKAGE_VERSION = "0.1.329";
|
|
7295
7306
|
var INITIALIZE_METHOD = "initialize";
|
|
7296
7307
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
7297
7308
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -9089,6 +9100,120 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
9089
9100
|
}
|
|
9090
9101
|
};
|
|
9091
9102
|
|
|
9103
|
+
// src/managers/cursor-manager.ts
|
|
9104
|
+
import { appendFile as appendFile4, mkdir as mkdir11 } from "fs/promises";
|
|
9105
|
+
import { dirname as dirname4, join as join15 } from "path";
|
|
9106
|
+
import { Agent as CursorAgent } from "@cursor/sdk";
|
|
9107
|
+
var CursorManager = class extends CodingAgentManager {
|
|
9108
|
+
agent = null;
|
|
9109
|
+
activeRun = null;
|
|
9110
|
+
historyFile;
|
|
9111
|
+
constructor(options) {
|
|
9112
|
+
super(options);
|
|
9113
|
+
this.historyFile = options.historyFilePath ?? join15(ENGINE_ENV.HOME_DIR, ".replicas", "cursor", "history.jsonl");
|
|
9114
|
+
this.initializeManager(this.processMessageInternal.bind(this));
|
|
9115
|
+
}
|
|
9116
|
+
async initialize() {
|
|
9117
|
+
await mkdir11(dirname4(this.historyFile), { recursive: true });
|
|
9118
|
+
}
|
|
9119
|
+
async interruptActiveTurn() {
|
|
9120
|
+
await this.activeRun?.cancel();
|
|
9121
|
+
}
|
|
9122
|
+
async getHistory() {
|
|
9123
|
+
return {
|
|
9124
|
+
thread_id: this.agent?.agentId ?? this.initialSessionId,
|
|
9125
|
+
events: await readJSONL(this.historyFile),
|
|
9126
|
+
goal: null
|
|
9127
|
+
};
|
|
9128
|
+
}
|
|
9129
|
+
async ensureAgent(request) {
|
|
9130
|
+
if (this.agent) return this.agent;
|
|
9131
|
+
const apiKey = ENGINE_ENV.CURSOR_API_KEY;
|
|
9132
|
+
if (!apiKey) {
|
|
9133
|
+
throw new Error("Cursor API key is not configured for this workspace.");
|
|
9134
|
+
}
|
|
9135
|
+
const model = { id: request.model ?? DEFAULT_CURSOR_MODEL };
|
|
9136
|
+
this.agent = this.initialSessionId ? await CursorAgent.resume(this.initialSessionId, {
|
|
9137
|
+
apiKey,
|
|
9138
|
+
model,
|
|
9139
|
+
local: { cwd: this.workingDirectory }
|
|
9140
|
+
}) : await CursorAgent.create({
|
|
9141
|
+
apiKey,
|
|
9142
|
+
model,
|
|
9143
|
+
local: { cwd: this.workingDirectory }
|
|
9144
|
+
});
|
|
9145
|
+
await this.onSaveSessionId(this.agent.agentId);
|
|
9146
|
+
return this.agent;
|
|
9147
|
+
}
|
|
9148
|
+
async processMessageInternal(request) {
|
|
9149
|
+
try {
|
|
9150
|
+
const agent = await this.ensureAgent(request);
|
|
9151
|
+
const message = await this.toCursorMessage(request);
|
|
9152
|
+
this.recordHistoryEvent("event_msg", {
|
|
9153
|
+
type: "user_message",
|
|
9154
|
+
message: request.message
|
|
9155
|
+
});
|
|
9156
|
+
const run = await agent.send(message, {
|
|
9157
|
+
model: { id: request.model ?? DEFAULT_CURSOR_MODEL },
|
|
9158
|
+
mode: request.planMode ? "plan" : "agent"
|
|
9159
|
+
});
|
|
9160
|
+
this.activeRun = run;
|
|
9161
|
+
for await (const event of run.stream()) {
|
|
9162
|
+
this.recordCursorEvent(event);
|
|
9163
|
+
}
|
|
9164
|
+
const result = await run.wait();
|
|
9165
|
+
if (result.status === "error") {
|
|
9166
|
+
this.recordHistoryEvent("cursor-error", {
|
|
9167
|
+
type: "error",
|
|
9168
|
+
message: result.result || "Cursor run failed",
|
|
9169
|
+
runId: result.id
|
|
9170
|
+
});
|
|
9171
|
+
}
|
|
9172
|
+
} catch (error) {
|
|
9173
|
+
this.recordHistoryEvent("cursor-error", {
|
|
9174
|
+
type: "error",
|
|
9175
|
+
message: error instanceof Error ? error.message : String(error)
|
|
9176
|
+
});
|
|
9177
|
+
} finally {
|
|
9178
|
+
this.activeRun = null;
|
|
9179
|
+
await this.onTurnComplete();
|
|
9180
|
+
}
|
|
9181
|
+
}
|
|
9182
|
+
async toCursorMessage(request) {
|
|
9183
|
+
if (!request.images || request.images.length === 0) {
|
|
9184
|
+
return request.message;
|
|
9185
|
+
}
|
|
9186
|
+
const images = await normalizeImages(request.images);
|
|
9187
|
+
return {
|
|
9188
|
+
text: request.message,
|
|
9189
|
+
images: images.map((image) => ({
|
|
9190
|
+
data: image.source.data,
|
|
9191
|
+
mimeType: image.source.media_type
|
|
9192
|
+
}))
|
|
9193
|
+
};
|
|
9194
|
+
}
|
|
9195
|
+
recordCursorEvent(event) {
|
|
9196
|
+
this.recordHistoryEvent(`cursor-${event.type}`, event);
|
|
9197
|
+
}
|
|
9198
|
+
recordHistoryEvent(type, payload) {
|
|
9199
|
+
const eventPayload = {};
|
|
9200
|
+
if (payload && typeof payload === "object") {
|
|
9201
|
+
Object.assign(eventPayload, payload);
|
|
9202
|
+
} else {
|
|
9203
|
+
eventPayload.value = payload;
|
|
9204
|
+
}
|
|
9205
|
+
const event = {
|
|
9206
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9207
|
+
type,
|
|
9208
|
+
payload: eventPayload
|
|
9209
|
+
};
|
|
9210
|
+
this.onEvent(event);
|
|
9211
|
+
appendFile4(this.historyFile, `${JSON.stringify(event)}
|
|
9212
|
+
`, "utf-8").catch(() => {
|
|
9213
|
+
});
|
|
9214
|
+
}
|
|
9215
|
+
};
|
|
9216
|
+
|
|
9092
9217
|
// src/managers/relay-tools.ts
|
|
9093
9218
|
import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
9094
9219
|
import { z } from "zod";
|
|
@@ -9670,10 +9795,10 @@ var keepAliveService = new KeepAliveService();
|
|
|
9670
9795
|
// src/services/canvas-service.ts
|
|
9671
9796
|
import { readdir as readdir4, readFile as readFile11, stat as stat3 } from "fs/promises";
|
|
9672
9797
|
import { homedir as homedir12 } from "os";
|
|
9673
|
-
import { join as
|
|
9798
|
+
import { join as join16 } from "path";
|
|
9674
9799
|
var CANVAS_DIRECTORIES = [
|
|
9675
|
-
|
|
9676
|
-
|
|
9800
|
+
join16(homedir12(), ".claude", "plans"),
|
|
9801
|
+
join16(homedir12(), ".replicas", "canvas")
|
|
9677
9802
|
];
|
|
9678
9803
|
var CanvasService = class {
|
|
9679
9804
|
async listItems() {
|
|
@@ -9692,7 +9817,7 @@ var CanvasService = class {
|
|
|
9692
9817
|
const { kind } = classifyCanvasFilename(entry.name);
|
|
9693
9818
|
let sizeBytes = 0;
|
|
9694
9819
|
try {
|
|
9695
|
-
const s = await stat3(
|
|
9820
|
+
const s = await stat3(join16(directory, entry.name));
|
|
9696
9821
|
sizeBytes = s.size;
|
|
9697
9822
|
} catch {
|
|
9698
9823
|
continue;
|
|
@@ -9707,7 +9832,7 @@ var CanvasService = class {
|
|
|
9707
9832
|
if (!safe) return null;
|
|
9708
9833
|
const { kind, mimeType } = classifyCanvasFilename(safe);
|
|
9709
9834
|
for (const directory of CANVAS_DIRECTORIES) {
|
|
9710
|
-
const filePath =
|
|
9835
|
+
const filePath = join16(directory, safe);
|
|
9711
9836
|
let sizeBytes = 0;
|
|
9712
9837
|
let updatedAt = "";
|
|
9713
9838
|
try {
|
|
@@ -9844,13 +9969,13 @@ async function reconcileCanvasItems(filenames) {
|
|
|
9844
9969
|
|
|
9845
9970
|
// src/services/upload-chat-transcripts.ts
|
|
9846
9971
|
import { readdir as readdir5, readFile as readFile12 } from "fs/promises";
|
|
9847
|
-
import { basename, join as
|
|
9972
|
+
import { basename, join as join17 } from "path";
|
|
9848
9973
|
import { homedir as homedir13 } from "os";
|
|
9849
|
-
var ENGINE_DIR2 =
|
|
9974
|
+
var ENGINE_DIR2 = join17(homedir13(), ".replicas", "engine");
|
|
9850
9975
|
var HISTORY_DIRS = [
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9976
|
+
join17(ENGINE_DIR2, "claude-histories"),
|
|
9977
|
+
join17(ENGINE_DIR2, "relay-histories"),
|
|
9978
|
+
join17(ENGINE_DIR2, "codex-histories")
|
|
9854
9979
|
];
|
|
9855
9980
|
async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
|
|
9856
9981
|
let flushed = 0;
|
|
@@ -9867,7 +9992,7 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
|
|
|
9867
9992
|
if (!entry.endsWith(".jsonl")) continue;
|
|
9868
9993
|
const chatId = basename(entry, ".jsonl");
|
|
9869
9994
|
tasks.push(
|
|
9870
|
-
uploadChatTranscript(chatId,
|
|
9995
|
+
uploadChatTranscript(chatId, join17(dir, entry), chatsById.get(chatId)).then(() => {
|
|
9871
9996
|
flushed++;
|
|
9872
9997
|
}).catch((err) => {
|
|
9873
9998
|
failed++;
|
|
@@ -9937,18 +10062,20 @@ var DuplicateDefaultChatError = class extends Error {
|
|
|
9937
10062
|
};
|
|
9938
10063
|
|
|
9939
10064
|
// src/services/chat/chat-service.ts
|
|
9940
|
-
var ENGINE_DIR3 =
|
|
9941
|
-
var CHATS_FILE =
|
|
9942
|
-
var CLAUDE_HISTORY_DIR =
|
|
9943
|
-
var RELAY_HISTORY_DIR =
|
|
9944
|
-
var CODEX_HISTORY_DIR =
|
|
10065
|
+
var ENGINE_DIR3 = join18(homedir14(), ".replicas", "engine");
|
|
10066
|
+
var CHATS_FILE = join18(ENGINE_DIR3, "chats.json");
|
|
10067
|
+
var CLAUDE_HISTORY_DIR = join18(ENGINE_DIR3, "claude-histories");
|
|
10068
|
+
var RELAY_HISTORY_DIR = join18(ENGINE_DIR3, "relay-histories");
|
|
10069
|
+
var CODEX_HISTORY_DIR = join18(ENGINE_DIR3, "codex-histories");
|
|
10070
|
+
var CURSOR_HISTORY_DIR = join18(ENGINE_DIR3, "cursor-histories");
|
|
9945
10071
|
var HISTORY_DIR_BY_PROVIDER = {
|
|
9946
10072
|
claude: CLAUDE_HISTORY_DIR,
|
|
9947
10073
|
relay: RELAY_HISTORY_DIR,
|
|
9948
|
-
codex: CODEX_HISTORY_DIR
|
|
10074
|
+
codex: CODEX_HISTORY_DIR,
|
|
10075
|
+
cursor: CURSOR_HISTORY_DIR
|
|
9949
10076
|
};
|
|
9950
|
-
var CHAT_SENDERS_DIR =
|
|
9951
|
-
var CODEX_AUTH_PATH2 =
|
|
10077
|
+
var CHAT_SENDERS_DIR = join18(ENGINE_DIR3, "chat-senders");
|
|
10078
|
+
var CODEX_AUTH_PATH2 = join18(homedir14(), ".codex", "auth.json");
|
|
9952
10079
|
var CHATS_BACKUP_FILE = `${CHATS_FILE}.bak`;
|
|
9953
10080
|
function isChatMessageSender(value) {
|
|
9954
10081
|
if (!isRecord4(value)) return false;
|
|
@@ -9998,7 +10125,7 @@ function isPersistedChat(value) {
|
|
|
9998
10125
|
return false;
|
|
9999
10126
|
}
|
|
10000
10127
|
const candidate = value;
|
|
10001
|
-
return typeof candidate.id === "string" && (candidate.provider === "claude" || candidate.provider === "codex" || candidate.provider === "relay") && typeof candidate.title === "string" && typeof candidate.createdAt === "string" && typeof candidate.updatedAt === "string" && (candidate.providerSessionId === null || typeof candidate.providerSessionId === "string") && (candidate.parentChatId === void 0 || candidate.parentChatId === null || typeof candidate.parentChatId === "string");
|
|
10128
|
+
return typeof candidate.id === "string" && (candidate.provider === "claude" || candidate.provider === "codex" || candidate.provider === "cursor" || candidate.provider === "relay") && typeof candidate.title === "string" && typeof candidate.createdAt === "string" && typeof candidate.updatedAt === "string" && (candidate.providerSessionId === null || typeof candidate.providerSessionId === "string") && (candidate.parentChatId === void 0 || candidate.parentChatId === null || typeof candidate.parentChatId === "string");
|
|
10002
10129
|
}
|
|
10003
10130
|
function normalizePersistedChat(chat) {
|
|
10004
10131
|
const isLegacyCodexSdkChat = chat.provider === "codex" && (chat.codexBackend === "sdk" || chat.codexBackend === void 0 && chat.providerSessionId !== null);
|
|
@@ -10046,11 +10173,12 @@ var ChatService = class {
|
|
|
10046
10173
|
persistInFlight = false;
|
|
10047
10174
|
persistQueued = false;
|
|
10048
10175
|
async initialize() {
|
|
10049
|
-
await
|
|
10050
|
-
await
|
|
10051
|
-
await
|
|
10052
|
-
await
|
|
10053
|
-
await
|
|
10176
|
+
await mkdir12(ENGINE_DIR3, { recursive: true });
|
|
10177
|
+
await mkdir12(CLAUDE_HISTORY_DIR, { recursive: true });
|
|
10178
|
+
await mkdir12(RELAY_HISTORY_DIR, { recursive: true });
|
|
10179
|
+
await mkdir12(CODEX_HISTORY_DIR, { recursive: true });
|
|
10180
|
+
await mkdir12(CURSOR_HISTORY_DIR, { recursive: true });
|
|
10181
|
+
await mkdir12(CHAT_SENDERS_DIR, { recursive: true });
|
|
10054
10182
|
const persisted = await this.loadChats();
|
|
10055
10183
|
for (const chat of persisted) {
|
|
10056
10184
|
const runtime = this.createRuntimeChat(chat);
|
|
@@ -10062,12 +10190,18 @@ var ChatService = class {
|
|
|
10062
10190
|
const hasCodexDefault = [...this.chats.values()].some(
|
|
10063
10191
|
(c) => c.persisted.provider === "codex" && c.persisted.title === "Codex"
|
|
10064
10192
|
);
|
|
10193
|
+
const hasCursorDefault = [...this.chats.values()].some(
|
|
10194
|
+
(c) => c.persisted.provider === "cursor" && c.persisted.title === "Cursor"
|
|
10195
|
+
);
|
|
10065
10196
|
if (!hasClaudeDefault) {
|
|
10066
10197
|
await this.createChat({ provider: "claude", title: "Claude Code" });
|
|
10067
10198
|
}
|
|
10068
10199
|
if (!hasCodexDefault) {
|
|
10069
10200
|
await this.createChat({ provider: "codex", title: "Codex" });
|
|
10070
10201
|
}
|
|
10202
|
+
if (!hasCursorDefault) {
|
|
10203
|
+
await this.createChat({ provider: "cursor", title: "Cursor" });
|
|
10204
|
+
}
|
|
10071
10205
|
const hasRelayDefault = [...this.chats.values()].some(
|
|
10072
10206
|
(c) => c.persisted.provider === "relay" && c.persisted.title === "Relay"
|
|
10073
10207
|
);
|
|
@@ -10149,11 +10283,11 @@ var ChatService = class {
|
|
|
10149
10283
|
};
|
|
10150
10284
|
}
|
|
10151
10285
|
senderFilePath(chatId) {
|
|
10152
|
-
return
|
|
10286
|
+
return join18(CHAT_SENDERS_DIR, `${chatId}.jsonl`);
|
|
10153
10287
|
}
|
|
10154
10288
|
async appendSender(chatId, sender) {
|
|
10155
10289
|
try {
|
|
10156
|
-
await
|
|
10290
|
+
await appendFile5(this.senderFilePath(chatId), JSON.stringify(sender) + "\n", "utf-8");
|
|
10157
10291
|
} catch (error) {
|
|
10158
10292
|
console.error("[ChatService] Failed to append sender record:", error);
|
|
10159
10293
|
}
|
|
@@ -10305,7 +10439,7 @@ var ChatService = class {
|
|
|
10305
10439
|
return descendants;
|
|
10306
10440
|
}
|
|
10307
10441
|
async deleteHistoryFile(persisted) {
|
|
10308
|
-
await rm(
|
|
10442
|
+
await rm(join18(HISTORY_DIR_BY_PROVIDER[persisted.provider], `${persisted.id}.jsonl`), { force: true });
|
|
10309
10443
|
await rm(this.senderFilePath(persisted.id), { force: true });
|
|
10310
10444
|
}
|
|
10311
10445
|
async getChatHistory(chatId) {
|
|
@@ -10376,7 +10510,7 @@ var ChatService = class {
|
|
|
10376
10510
|
if (persisted.provider === "claude") {
|
|
10377
10511
|
provider = new ClaudeManager({
|
|
10378
10512
|
workingDirectory: this.workingDirectory,
|
|
10379
|
-
historyFilePath:
|
|
10513
|
+
historyFilePath: join18(CLAUDE_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
10380
10514
|
initialSessionId: persisted.providerSessionId,
|
|
10381
10515
|
onSaveSessionId: saveSession,
|
|
10382
10516
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -10385,7 +10519,7 @@ var ChatService = class {
|
|
|
10385
10519
|
} else if (persisted.provider === "relay") {
|
|
10386
10520
|
provider = new RelayManager({
|
|
10387
10521
|
workingDirectory: this.workingDirectory,
|
|
10388
|
-
historyFilePath:
|
|
10522
|
+
historyFilePath: join18(RELAY_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
10389
10523
|
initialSessionId: persisted.providerSessionId,
|
|
10390
10524
|
onSaveSessionId: saveSession,
|
|
10391
10525
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -10393,10 +10527,19 @@ var ChatService = class {
|
|
|
10393
10527
|
chatId: persisted.id,
|
|
10394
10528
|
codexAvailable: isCodexAvailable()
|
|
10395
10529
|
});
|
|
10530
|
+
} else if (persisted.provider === "cursor") {
|
|
10531
|
+
provider = new CursorManager({
|
|
10532
|
+
workingDirectory: this.workingDirectory,
|
|
10533
|
+
historyFilePath: join18(CURSOR_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
10534
|
+
initialSessionId: persisted.providerSessionId,
|
|
10535
|
+
onSaveSessionId: saveSession,
|
|
10536
|
+
onTurnComplete: onProviderTurnComplete,
|
|
10537
|
+
onEvent: onProviderEvent
|
|
10538
|
+
});
|
|
10396
10539
|
} else {
|
|
10397
10540
|
provider = new CodexAspManager({
|
|
10398
10541
|
workingDirectory: this.workingDirectory,
|
|
10399
|
-
historyFilePath:
|
|
10542
|
+
historyFilePath: join18(CODEX_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
10400
10543
|
initialSessionId: persisted.providerSessionId,
|
|
10401
10544
|
onSaveSessionId: saveSession,
|
|
10402
10545
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -10535,7 +10678,7 @@ var ChatService = class {
|
|
|
10535
10678
|
});
|
|
10536
10679
|
uploadChatTranscript(
|
|
10537
10680
|
chatId,
|
|
10538
|
-
|
|
10681
|
+
join18(HISTORY_DIR_BY_PROVIDER[chat.persisted.provider], `${chatId}.jsonl`),
|
|
10539
10682
|
this.toSummary(chat)
|
|
10540
10683
|
).catch((err) => {
|
|
10541
10684
|
console.error("[ChatService] Failed to upload chat transcript:", { chatId, err });
|
|
@@ -10651,7 +10794,7 @@ var ChatService = class {
|
|
|
10651
10794
|
// src/services/repo-file-service.ts
|
|
10652
10795
|
import { execFile as execFile2 } from "child_process";
|
|
10653
10796
|
import { readFile as readFile14, realpath, stat as stat4 } from "fs/promises";
|
|
10654
|
-
import { join as
|
|
10797
|
+
import { join as join19, resolve as resolve2, extname } from "path";
|
|
10655
10798
|
var CACHE_TTL_MS = 3e4;
|
|
10656
10799
|
var SEARCH_TIMEOUT_MS = 15e3;
|
|
10657
10800
|
var MAX_CONTENT_BYTES = 256 * 1024;
|
|
@@ -10811,7 +10954,7 @@ var RepoFileService = class {
|
|
|
10811
10954
|
const repo = repos.find((r) => r.name === repoName);
|
|
10812
10955
|
if (!repo) return null;
|
|
10813
10956
|
try {
|
|
10814
|
-
const fullPath = await realpath(resolve2(
|
|
10957
|
+
const fullPath = await realpath(resolve2(join19(repo.path, filePath)));
|
|
10815
10958
|
const repoRoot = await realpath(repo.path);
|
|
10816
10959
|
const repoPrefix = repoRoot.endsWith("/") ? repoRoot : repoRoot + "/";
|
|
10817
10960
|
if (!fullPath.startsWith(repoPrefix) && fullPath !== repoRoot) return null;
|
|
@@ -10919,20 +11062,20 @@ var RepoFileService = class {
|
|
|
10919
11062
|
import { Hono } from "hono";
|
|
10920
11063
|
import { z as z2 } from "zod";
|
|
10921
11064
|
import { readdir as readdir7, stat as stat5, readFile as readFile17 } from "fs/promises";
|
|
10922
|
-
import { join as
|
|
11065
|
+
import { join as join22, resolve as resolve3 } from "path";
|
|
10923
11066
|
|
|
10924
11067
|
// src/services/warm-hooks-service.ts
|
|
10925
11068
|
import { spawn as spawn4 } from "child_process";
|
|
10926
11069
|
import { readFile as readFile16 } from "fs/promises";
|
|
10927
11070
|
import { existsSync as existsSync8 } from "fs";
|
|
10928
|
-
import { join as
|
|
11071
|
+
import { join as join21 } from "path";
|
|
10929
11072
|
|
|
10930
11073
|
// src/services/warm-hook-logs-service.ts
|
|
10931
|
-
import { mkdir as
|
|
11074
|
+
import { mkdir as mkdir13, readFile as readFile15, writeFile as writeFile6, readdir as readdir6, appendFile as appendFile6, unlink as unlink3 } from "fs/promises";
|
|
10932
11075
|
import { homedir as homedir15 } from "os";
|
|
10933
|
-
import { join as
|
|
10934
|
-
var LOGS_DIR2 =
|
|
10935
|
-
var CURRENT_RUN_LOG =
|
|
11076
|
+
import { join as join20 } from "path";
|
|
11077
|
+
var LOGS_DIR2 = join20(homedir15(), ".replicas", "warm-hook-logs");
|
|
11078
|
+
var CURRENT_RUN_LOG = join20(LOGS_DIR2, "current-run.log");
|
|
10936
11079
|
var GLOBAL_FILENAME = "global.json";
|
|
10937
11080
|
function withPreview2(stored) {
|
|
10938
11081
|
const preview = buildHookOutputPreview(stored.output);
|
|
@@ -10940,7 +11083,7 @@ function withPreview2(stored) {
|
|
|
10940
11083
|
}
|
|
10941
11084
|
var WarmHookLogsService = class {
|
|
10942
11085
|
async ensureDir() {
|
|
10943
|
-
await
|
|
11086
|
+
await mkdir13(LOGS_DIR2, { recursive: true });
|
|
10944
11087
|
}
|
|
10945
11088
|
async saveGlobalHookLog(entry) {
|
|
10946
11089
|
await this.ensureDir();
|
|
@@ -10949,7 +11092,7 @@ var WarmHookLogsService = class {
|
|
|
10949
11092
|
hookName: "organization",
|
|
10950
11093
|
...entry
|
|
10951
11094
|
};
|
|
10952
|
-
await writeFile6(
|
|
11095
|
+
await writeFile6(join20(LOGS_DIR2, GLOBAL_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
10953
11096
|
`, "utf-8");
|
|
10954
11097
|
}
|
|
10955
11098
|
async saveEnvironmentHookLog(entry) {
|
|
@@ -10959,7 +11102,7 @@ var WarmHookLogsService = class {
|
|
|
10959
11102
|
hookName: "environment",
|
|
10960
11103
|
...entry
|
|
10961
11104
|
};
|
|
10962
|
-
await writeFile6(
|
|
11105
|
+
await writeFile6(join20(LOGS_DIR2, ENVIRONMENT_HOOK_LOG_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
10963
11106
|
`, "utf-8");
|
|
10964
11107
|
}
|
|
10965
11108
|
async saveRepoHookLog(repoName, entry) {
|
|
@@ -10969,7 +11112,7 @@ var WarmHookLogsService = class {
|
|
|
10969
11112
|
hookName: repoName,
|
|
10970
11113
|
...entry
|
|
10971
11114
|
};
|
|
10972
|
-
await writeFile6(
|
|
11115
|
+
await writeFile6(join20(LOGS_DIR2, repoHookLogFilename(repoName)), `${JSON.stringify(log, null, 2)}
|
|
10973
11116
|
`, "utf-8");
|
|
10974
11117
|
}
|
|
10975
11118
|
async getAllLogs() {
|
|
@@ -10988,7 +11131,7 @@ var WarmHookLogsService = class {
|
|
|
10988
11131
|
continue;
|
|
10989
11132
|
}
|
|
10990
11133
|
try {
|
|
10991
|
-
const raw = await readFile15(
|
|
11134
|
+
const raw = await readFile15(join20(LOGS_DIR2, file), "utf-8");
|
|
10992
11135
|
const stored = JSON.parse(raw);
|
|
10993
11136
|
logs.push(withPreview2(stored));
|
|
10994
11137
|
} catch {
|
|
@@ -11013,7 +11156,7 @@ var WarmHookLogsService = class {
|
|
|
11013
11156
|
}
|
|
11014
11157
|
async appendCurrentRunLog(chunk) {
|
|
11015
11158
|
if (!chunk) return;
|
|
11016
|
-
await
|
|
11159
|
+
await appendFile6(CURRENT_RUN_LOG, chunk, "utf-8");
|
|
11017
11160
|
}
|
|
11018
11161
|
async getCurrentRunLog() {
|
|
11019
11162
|
try {
|
|
@@ -11026,7 +11169,7 @@ var WarmHookLogsService = class {
|
|
|
11026
11169
|
async getFullOutput(hookType, hookName) {
|
|
11027
11170
|
const filename = hookType === "global" ? GLOBAL_FILENAME : hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
11028
11171
|
try {
|
|
11029
|
-
const raw = await readFile15(
|
|
11172
|
+
const raw = await readFile15(join20(LOGS_DIR2, filename), "utf-8");
|
|
11030
11173
|
const stored = JSON.parse(raw);
|
|
11031
11174
|
if (stored.hookType !== hookType || stored.hookName !== hookName) {
|
|
11032
11175
|
return null;
|
|
@@ -11045,7 +11188,7 @@ var warmHookLogsService = new WarmHookLogsService();
|
|
|
11045
11188
|
// src/services/warm-hooks-service.ts
|
|
11046
11189
|
async function readRepoWarmHook(repoPath) {
|
|
11047
11190
|
for (const filename of REPLICAS_CONFIG_FILENAMES) {
|
|
11048
|
-
const configPath =
|
|
11191
|
+
const configPath = join21(repoPath, filename);
|
|
11049
11192
|
if (!existsSync8(configPath)) {
|
|
11050
11193
|
continue;
|
|
11051
11194
|
}
|
|
@@ -11310,7 +11453,7 @@ var setWorkspaceNameSchema = z2.object({
|
|
|
11310
11453
|
name: z2.string().min(1).max(48)
|
|
11311
11454
|
});
|
|
11312
11455
|
var createChatSchema = z2.object({
|
|
11313
|
-
provider: z2.enum(["claude", "codex", "relay"]),
|
|
11456
|
+
provider: z2.enum(["claude", "codex", "cursor", "relay"]),
|
|
11314
11457
|
title: z2.string().min(1).optional(),
|
|
11315
11458
|
parentChatId: z2.string().uuid().optional()
|
|
11316
11459
|
});
|
|
@@ -12000,7 +12143,7 @@ function createV1Routes(deps) {
|
|
|
12000
12143
|
const logFiles = files.filter((f) => f.endsWith(".log"));
|
|
12001
12144
|
const sessions = await Promise.all(
|
|
12002
12145
|
logFiles.map(async (filename) => {
|
|
12003
|
-
const filePath =
|
|
12146
|
+
const filePath = join22(LOG_DIR, filename);
|
|
12004
12147
|
const fileStat = await stat5(filePath);
|
|
12005
12148
|
const sessionId = filename.replace(/\.log$/, "");
|
|
12006
12149
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "replicas-engine",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.329",
|
|
4
4
|
"description": "Lightweight API server for Replicas workspaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@anthropic-ai/claude-agent-sdk": "0.3.168",
|
|
34
|
+
"@cursor/sdk": "1.0.19",
|
|
34
35
|
"@hono/node-server": "^1.19.5",
|
|
35
36
|
"hono": "^4.10.3",
|
|
36
37
|
"smol-toml": "^1.6.0",
|