replicas-engine 0.1.451 → 0.1.452
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 +260 -68
- package/package.json +3 -1
package/dist/src/index.js
CHANGED
|
@@ -43,10 +43,13 @@ function createErrorResult(error) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// ../shared/src/agent.ts
|
|
46
|
-
var VALID_AGENT_PROVIDERS = ["claude", "codex", "cursor", "opencode", "relay"];
|
|
46
|
+
var VALID_AGENT_PROVIDERS = ["claude", "codex", "cursor", "opencode", "pi", "relay"];
|
|
47
47
|
var VALID_CODING_AGENT_PROVIDERS = VALID_AGENT_PROVIDERS.filter(
|
|
48
48
|
(provider) => provider !== "relay"
|
|
49
49
|
);
|
|
50
|
+
function isValidAgentProvider(value) {
|
|
51
|
+
return VALID_AGENT_PROVIDERS.some((p) => p === value);
|
|
52
|
+
}
|
|
50
53
|
var VALID_THINKING_LEVELS = ["low", "medium", "high", "xhigh", "max"];
|
|
51
54
|
var CODEX_REASONING_EFFORT_BY_THINKING_LEVEL = {
|
|
52
55
|
low: "low",
|
|
@@ -166,6 +169,7 @@ var DEFAULT_CHAT_TITLES = {
|
|
|
166
169
|
codex: "Codex",
|
|
167
170
|
cursor: "Cursor",
|
|
168
171
|
opencode: "Opencode",
|
|
172
|
+
pi: "Pi",
|
|
169
173
|
relay: "Relay"
|
|
170
174
|
};
|
|
171
175
|
function isDefaultChat(chat) {
|
|
@@ -188,6 +192,13 @@ var GPT_5_6_LUNA_MODEL = "gpt-5.6-luna";
|
|
|
188
192
|
var DEFAULT_CODEX_MODEL = GPT_5_6_SOL_MODEL;
|
|
189
193
|
var DEFAULT_CURSOR_MODEL = "composer-2.5";
|
|
190
194
|
var DEFAULT_OPENCODE_MODEL = "z-ai/glm-5.2";
|
|
195
|
+
var DEFAULT_PI_MODEL = DEFAULT_OPENCODE_MODEL;
|
|
196
|
+
var OPENROUTER_MODELS = [
|
|
197
|
+
DEFAULT_OPENCODE_MODEL,
|
|
198
|
+
"minimax/minimax-m3",
|
|
199
|
+
"xiaomi/mimo-v2.5-pro",
|
|
200
|
+
"moonshotai/kimi-k2.6"
|
|
201
|
+
];
|
|
191
202
|
function normalizeClaudeModel(model) {
|
|
192
203
|
if (model === "opus" || model === CLAUDE_OPUS_1M_MODEL || model === LEGACY_CLAUDE_OPUS_1M_MODEL) {
|
|
193
204
|
return DEFAULT_CLAUDE_MODEL;
|
|
@@ -256,7 +267,8 @@ var AGENT_MODELS = {
|
|
|
256
267
|
CLAUDE_HAIKU_4_5_MODEL,
|
|
257
268
|
"kimi-k2.5"
|
|
258
269
|
],
|
|
259
|
-
opencode:
|
|
270
|
+
opencode: OPENROUTER_MODELS,
|
|
271
|
+
pi: OPENROUTER_MODELS,
|
|
260
272
|
relay: [CLAUDE_FABLE_5_MODEL, DEFAULT_CLAUDE_MODEL, CLAUDE_SONNET_5_MODEL]
|
|
261
273
|
};
|
|
262
274
|
var MODEL_LABELS = {
|
|
@@ -516,7 +528,7 @@ var WORKSPACE_SIZES = ["small", "large"];
|
|
|
516
528
|
var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
|
|
517
529
|
|
|
518
530
|
// ../shared/src/e2b.ts
|
|
519
|
-
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-19-
|
|
531
|
+
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-19-v4";
|
|
520
532
|
|
|
521
533
|
// ../shared/src/runtime-env.ts
|
|
522
534
|
function shellQuotePosix(value) {
|
|
@@ -672,7 +684,7 @@ var SLASH_COMMANDS = [
|
|
|
672
684
|
command: "/plan",
|
|
673
685
|
description: "Switch to plan mode and optionally send a prompt.",
|
|
674
686
|
argumentHint: "[prompt]",
|
|
675
|
-
providers: ["claude", "codex", "cursor", "opencode", "relay"]
|
|
687
|
+
providers: ["claude", "codex", "cursor", "opencode", "pi", "relay"]
|
|
676
688
|
},
|
|
677
689
|
{
|
|
678
690
|
command: "/fast",
|
|
@@ -5012,6 +5024,9 @@ function detectCursorAuthMethod() {
|
|
|
5012
5024
|
function detectOpencodeAuthMethod() {
|
|
5013
5025
|
return existsSync3(OPENCODE_AUTH_PATH) || ENGINE_ENV.OPENROUTER_API_KEY ? "api_key" : "none";
|
|
5014
5026
|
}
|
|
5027
|
+
function detectPiAuthMethod() {
|
|
5028
|
+
return ENGINE_ENV.OPENROUTER_API_KEY ? "api_key" : "none";
|
|
5029
|
+
}
|
|
5015
5030
|
async function detectGitIdentityConfigured() {
|
|
5016
5031
|
try {
|
|
5017
5032
|
const { stdout } = await execFileAsync("git", ["config", "--global", "user.name"]);
|
|
@@ -5069,6 +5084,7 @@ function createDefaultDetails() {
|
|
|
5069
5084
|
codexAuthMethod: "none",
|
|
5070
5085
|
cursorAuthMethod: "none",
|
|
5071
5086
|
opencodeAuthMethod: "none",
|
|
5087
|
+
piAuthMethod: "none",
|
|
5072
5088
|
lastUpdatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5073
5089
|
};
|
|
5074
5090
|
}
|
|
@@ -5104,6 +5120,7 @@ var EnvironmentDetailsService = class {
|
|
|
5104
5120
|
details.codexAuthMethod = detectCodexAuthMethod();
|
|
5105
5121
|
details.cursorAuthMethod = detectCursorAuthMethod();
|
|
5106
5122
|
details.opencodeAuthMethod = detectOpencodeAuthMethod();
|
|
5123
|
+
details.piAuthMethod = detectPiAuthMethod();
|
|
5107
5124
|
details.gitIdentityConfigured = gitIdentityConfigured;
|
|
5108
5125
|
const ghConfigured = existsSync3(GH_HOSTS_PATH);
|
|
5109
5126
|
details.githubAccessConfigured = ghConfigured;
|
|
@@ -5854,9 +5871,9 @@ async function registerDesktopPreview() {
|
|
|
5854
5871
|
|
|
5855
5872
|
// src/services/chat/chat-service.ts
|
|
5856
5873
|
import { existsSync as existsSync7 } from "fs";
|
|
5857
|
-
import { appendFile as appendFile3, copyFile, mkdir as
|
|
5874
|
+
import { appendFile as appendFile3, copyFile, mkdir as mkdir14, readFile as readFile14, rename as rename2, rm as rm2 } from "fs/promises";
|
|
5858
5875
|
import { homedir as homedir15 } from "os";
|
|
5859
|
-
import { join as
|
|
5876
|
+
import { join as join22 } from "path";
|
|
5860
5877
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
5861
5878
|
|
|
5862
5879
|
// src/managers/claude-manager.ts
|
|
@@ -6576,16 +6593,16 @@ var CodingAgentManager = class {
|
|
|
6576
6593
|
});
|
|
6577
6594
|
}
|
|
6578
6595
|
recordHistoryEvent(type, payload, historyFile) {
|
|
6579
|
-
const
|
|
6596
|
+
const eventPayload2 = {};
|
|
6580
6597
|
if (payload && typeof payload === "object") {
|
|
6581
|
-
Object.assign(
|
|
6598
|
+
Object.assign(eventPayload2, payload);
|
|
6582
6599
|
} else {
|
|
6583
|
-
|
|
6600
|
+
eventPayload2.value = payload;
|
|
6584
6601
|
}
|
|
6585
6602
|
const event = {
|
|
6586
6603
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6587
6604
|
type,
|
|
6588
|
-
payload:
|
|
6605
|
+
payload: eventPayload2
|
|
6589
6606
|
};
|
|
6590
6607
|
this.onEvent(event);
|
|
6591
6608
|
historyFile.append(event);
|
|
@@ -8569,7 +8586,7 @@ var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
|
8569
8586
|
var MIN_CODEX_CLI_VERSION = "0.144.0";
|
|
8570
8587
|
var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
|
|
8571
8588
|
var codexCliVersionEnsured = null;
|
|
8572
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
8589
|
+
var ENGINE_PACKAGE_VERSION = "0.1.452";
|
|
8573
8590
|
var INITIALIZE_METHOD = "initialize";
|
|
8574
8591
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
8575
8592
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -9447,12 +9464,14 @@ var RELAY_HISTORY_DIR = join15(ENGINE_DIR2, "relay-histories");
|
|
|
9447
9464
|
var CODEX_HISTORY_DIR = join15(ENGINE_DIR2, "codex-histories");
|
|
9448
9465
|
var CURSOR_HISTORY_DIR = join15(ENGINE_DIR2, "cursor-histories");
|
|
9449
9466
|
var OPENCODE_HISTORY_DIR = join15(ENGINE_DIR2, "opencode-histories");
|
|
9467
|
+
var PI_HISTORY_DIR = join15(ENGINE_DIR2, "pi-histories");
|
|
9450
9468
|
var HISTORY_DIR_BY_PROVIDER = {
|
|
9451
9469
|
claude: CLAUDE_HISTORY_DIR,
|
|
9452
9470
|
relay: RELAY_HISTORY_DIR,
|
|
9453
9471
|
codex: CODEX_HISTORY_DIR,
|
|
9454
9472
|
cursor: CURSOR_HISTORY_DIR,
|
|
9455
|
-
opencode: OPENCODE_HISTORY_DIR
|
|
9473
|
+
opencode: OPENCODE_HISTORY_DIR,
|
|
9474
|
+
pi: PI_HISTORY_DIR
|
|
9456
9475
|
};
|
|
9457
9476
|
|
|
9458
9477
|
// src/services/chat/errors.ts
|
|
@@ -11744,6 +11763,162 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
11744
11763
|
}
|
|
11745
11764
|
};
|
|
11746
11765
|
|
|
11766
|
+
// src/managers/pi-manager.ts
|
|
11767
|
+
import { mkdir as mkdir13 } from "fs/promises";
|
|
11768
|
+
import { dirname as dirname7, join as join19 } from "path";
|
|
11769
|
+
import {
|
|
11770
|
+
AuthStorage,
|
|
11771
|
+
createAgentSession,
|
|
11772
|
+
ModelRegistry,
|
|
11773
|
+
SessionManager,
|
|
11774
|
+
DefaultResourceLoader
|
|
11775
|
+
} from "@mariozechner/pi-coding-agent";
|
|
11776
|
+
function eventPayload(event) {
|
|
11777
|
+
return isRecord4(event) ? { ...event } : { value: event };
|
|
11778
|
+
}
|
|
11779
|
+
function registerCommandProtection(cwd) {
|
|
11780
|
+
return (pi) => {
|
|
11781
|
+
pi.on("tool_call", async (event) => {
|
|
11782
|
+
const command = extractToolCommand(event.input);
|
|
11783
|
+
const result = await evaluateCommandProtection({
|
|
11784
|
+
provider: "pi",
|
|
11785
|
+
source: "pi_tool_call",
|
|
11786
|
+
toolName: event.toolName,
|
|
11787
|
+
toolInput: event.input,
|
|
11788
|
+
command,
|
|
11789
|
+
cwd,
|
|
11790
|
+
toolUseId: event.toolCallId
|
|
11791
|
+
});
|
|
11792
|
+
if (!result.allowed) {
|
|
11793
|
+
reportCommandProtectionBlock({ provider: "pi", toolName: event.toolName, command, reason: result.reason });
|
|
11794
|
+
return { block: true, reason: result.reason ?? "Command blocked by Replicas protection." };
|
|
11795
|
+
}
|
|
11796
|
+
return void 0;
|
|
11797
|
+
});
|
|
11798
|
+
};
|
|
11799
|
+
}
|
|
11800
|
+
var PiManager = class extends CodingAgentManager {
|
|
11801
|
+
session = null;
|
|
11802
|
+
unsubscribe = null;
|
|
11803
|
+
activeSessionFile = null;
|
|
11804
|
+
historyFilePath;
|
|
11805
|
+
historyFile;
|
|
11806
|
+
constructor(options) {
|
|
11807
|
+
super(options);
|
|
11808
|
+
this.historyFilePath = options.historyFilePath ?? join19(PI_HISTORY_DIR, `${Date.now()}.jsonl`);
|
|
11809
|
+
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
11810
|
+
this.initializeManager(this.processMessageInternal.bind(this));
|
|
11811
|
+
}
|
|
11812
|
+
async initialize() {
|
|
11813
|
+
await mkdir13(dirname7(this.historyFilePath), { recursive: true });
|
|
11814
|
+
}
|
|
11815
|
+
async interruptActiveTurn() {
|
|
11816
|
+
await this.session?.abort();
|
|
11817
|
+
}
|
|
11818
|
+
async steerRequest(request) {
|
|
11819
|
+
if (!this.session?.isStreaming) return false;
|
|
11820
|
+
await this.session.steer(request.message);
|
|
11821
|
+
return true;
|
|
11822
|
+
}
|
|
11823
|
+
async getHistory() {
|
|
11824
|
+
await this.historyFile.flush();
|
|
11825
|
+
const history = await this.historyFile.load();
|
|
11826
|
+
return { thread_id: this.activeSessionFile ?? this.initialSessionId, events: history.events, goal: null };
|
|
11827
|
+
}
|
|
11828
|
+
async listSlashCommands() {
|
|
11829
|
+
await this.initialized;
|
|
11830
|
+
return mergeSlashCommands(...(this.session?.promptTemplates ?? []).map((template) => createProviderSlashCommand("pi", template.name, template.description)).filter((command) => Boolean(command)));
|
|
11831
|
+
}
|
|
11832
|
+
dispose() {
|
|
11833
|
+
this.unsubscribe?.();
|
|
11834
|
+
this.unsubscribe = null;
|
|
11835
|
+
this.session?.dispose();
|
|
11836
|
+
this.session = null;
|
|
11837
|
+
}
|
|
11838
|
+
async ensureSession(request) {
|
|
11839
|
+
if (this.session) {
|
|
11840
|
+
if (request.model && request.model !== this.session.model?.id) {
|
|
11841
|
+
const model2 = this.session.modelRegistry.find("openrouter", request.model);
|
|
11842
|
+
if (model2) await this.session.setModel(model2);
|
|
11843
|
+
}
|
|
11844
|
+
if (request.thinkingLevel) this.session.setThinkingLevel(request.thinkingLevel);
|
|
11845
|
+
return this.session;
|
|
11846
|
+
}
|
|
11847
|
+
const apiKey = ENGINE_ENV.OPENROUTER_API_KEY;
|
|
11848
|
+
if (!apiKey) throw new Error("OpenRouter API key is not configured for Pi.");
|
|
11849
|
+
const authStorage = AuthStorage.inMemory({ openrouter: { type: "api_key", key: apiKey } });
|
|
11850
|
+
const modelRegistry = ModelRegistry.create(authStorage);
|
|
11851
|
+
const openRouterModels = modelRegistry.getAll().filter((candidate) => candidate.provider === "openrouter");
|
|
11852
|
+
const modelTemplate = openRouterModels[0];
|
|
11853
|
+
if (!modelTemplate) throw new Error("Pi OpenRouter model catalog is empty.");
|
|
11854
|
+
modelRegistry.registerProvider("openrouter", {
|
|
11855
|
+
api: modelTemplate.api,
|
|
11856
|
+
apiKey,
|
|
11857
|
+
baseUrl: modelTemplate.baseUrl,
|
|
11858
|
+
models: [
|
|
11859
|
+
...openRouterModels,
|
|
11860
|
+
...OPENROUTER_MODELS.filter((id) => !openRouterModels.some((candidate) => candidate.id === id)).map((id) => ({
|
|
11861
|
+
id,
|
|
11862
|
+
name: id,
|
|
11863
|
+
api: modelTemplate.api,
|
|
11864
|
+
baseUrl: modelTemplate.baseUrl,
|
|
11865
|
+
reasoning: modelTemplate.reasoning,
|
|
11866
|
+
input: modelTemplate.input,
|
|
11867
|
+
cost: modelTemplate.cost,
|
|
11868
|
+
contextWindow: modelTemplate.contextWindow,
|
|
11869
|
+
maxTokens: modelTemplate.maxTokens
|
|
11870
|
+
}))
|
|
11871
|
+
]
|
|
11872
|
+
});
|
|
11873
|
+
const modelId = request.model ?? DEFAULT_PI_MODEL;
|
|
11874
|
+
const model = modelRegistry.find("openrouter", modelId) ?? modelRegistry.find("openrouter", DEFAULT_PI_MODEL);
|
|
11875
|
+
if (!model) throw new Error(`Pi model is not available through OpenRouter: ${modelId}`);
|
|
11876
|
+
const sessionManager = this.initialSessionId ? SessionManager.open(this.initialSessionId, PI_HISTORY_DIR, this.workingDirectory) : SessionManager.create(this.workingDirectory, PI_HISTORY_DIR);
|
|
11877
|
+
const resourceLoader = new DefaultResourceLoader({
|
|
11878
|
+
cwd: this.workingDirectory,
|
|
11879
|
+
agentDir: join19(ENGINE_ENV.HOME_DIR, ".pi", "agent"),
|
|
11880
|
+
extensionFactories: [registerCommandProtection(this.workingDirectory)],
|
|
11881
|
+
appendSystemPrompt: [this.buildCombinedInstructions() ?? ""]
|
|
11882
|
+
});
|
|
11883
|
+
await resourceLoader.reload();
|
|
11884
|
+
const result = await createAgentSession({
|
|
11885
|
+
cwd: this.workingDirectory,
|
|
11886
|
+
authStorage,
|
|
11887
|
+
modelRegistry,
|
|
11888
|
+
model,
|
|
11889
|
+
sessionManager,
|
|
11890
|
+
resourceLoader
|
|
11891
|
+
});
|
|
11892
|
+
this.session = result.session;
|
|
11893
|
+
if (request.thinkingLevel) this.session.setThinkingLevel(request.thinkingLevel);
|
|
11894
|
+
this.activeSessionFile = sessionManager.getSessionFile() ?? null;
|
|
11895
|
+
await this.onSaveSessionId(this.activeSessionFile);
|
|
11896
|
+
this.unsubscribe = this.session.subscribe((event) => this.handleEvent(event));
|
|
11897
|
+
return this.session;
|
|
11898
|
+
}
|
|
11899
|
+
handleEvent(event) {
|
|
11900
|
+
const payload = eventPayload(event);
|
|
11901
|
+
this.recordHistoryEvent(`pi-${event.type}`, payload, this.historyFile);
|
|
11902
|
+
}
|
|
11903
|
+
async processMessageInternal(request) {
|
|
11904
|
+
const session = await this.ensureSession(request);
|
|
11905
|
+
this.recordHistoryEvent("event_msg", { type: "user_message", message: request.message }, this.historyFile);
|
|
11906
|
+
try {
|
|
11907
|
+
const images = request.images && request.images.length > 0 ? (await normalizeImages(request.images)).map((image) => ({
|
|
11908
|
+
type: "image",
|
|
11909
|
+
data: image.source.data,
|
|
11910
|
+
mimeType: image.source.media_type
|
|
11911
|
+
})) : void 0;
|
|
11912
|
+
await session.prompt(request.message, images ? { images } : void 0);
|
|
11913
|
+
} catch (error) {
|
|
11914
|
+
this.recordHistoryEvent("pi-error", { message: error instanceof Error ? error.message : String(error) }, this.historyFile);
|
|
11915
|
+
throw error;
|
|
11916
|
+
} finally {
|
|
11917
|
+
await this.onTurnComplete();
|
|
11918
|
+
}
|
|
11919
|
+
}
|
|
11920
|
+
};
|
|
11921
|
+
|
|
11747
11922
|
// src/managers/relay-tools.ts
|
|
11748
11923
|
import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
11749
11924
|
import { z } from "zod";
|
|
@@ -11753,15 +11928,17 @@ function getAvailableRelayProviders(availability) {
|
|
|
11753
11928
|
const codexAvailable = availability.codexAvailable ?? false;
|
|
11754
11929
|
const cursorAvailable = availability.cursorAvailable ?? false;
|
|
11755
11930
|
const opencodeAvailable = availability.opencodeAvailable ?? false;
|
|
11931
|
+
const piAvailable = availability.piAvailable ?? false;
|
|
11756
11932
|
const providers = ["claude"];
|
|
11757
11933
|
if (codexAvailable) providers.push("codex");
|
|
11758
11934
|
if (cursorAvailable) providers.push("cursor");
|
|
11759
11935
|
if (opencodeAvailable) providers.push("opencode");
|
|
11936
|
+
if (piAvailable) providers.push("pi");
|
|
11760
11937
|
providers.push("relay");
|
|
11761
11938
|
return providers;
|
|
11762
11939
|
}
|
|
11763
11940
|
function getAvailableCodeProviders(availability) {
|
|
11764
|
-
return getAvailableRelayProviders(availability).filter((provider) => provider === "codex" || provider === "cursor" || provider === "opencode");
|
|
11941
|
+
return getAvailableRelayProviders(availability).filter((provider) => provider === "codex" || provider === "cursor" || provider === "opencode" || provider === "pi");
|
|
11765
11942
|
}
|
|
11766
11943
|
|
|
11767
11944
|
// src/managers/relay-tools.ts
|
|
@@ -12115,13 +12292,14 @@ function getUsingToolsSection() {
|
|
|
12115
12292
|
];
|
|
12116
12293
|
return [`# Using your tools`, ...prependBullets(items)].join("\n");
|
|
12117
12294
|
}
|
|
12118
|
-
function getDelegationSection(codexAvailable, cursorAvailable, opencodeAvailable) {
|
|
12119
|
-
const providerList = getAvailableRelayProviders({ codexAvailable, cursorAvailable, opencodeAvailable }).join(", ");
|
|
12295
|
+
function getDelegationSection(codexAvailable, cursorAvailable, opencodeAvailable, piAvailable) {
|
|
12296
|
+
const providerList = getAvailableRelayProviders({ codexAvailable, cursorAvailable, opencodeAvailable, piAvailable }).join(", ");
|
|
12120
12297
|
const spawnDesc = `Create a new subagent with a specific provider (${providerList}), send it a prompt, and wait for its response. Returns the chatId and the agent's final response. You can set a custom timeout via the timeout_minutes parameter (default: 10 minutes).`;
|
|
12121
12298
|
const claudeModelList = AGENT_MODELS.claude.join(", ");
|
|
12122
12299
|
const extraAgentLines = [
|
|
12123
12300
|
codexAvailable ? `Use provider 'codex' for heavy code writing, implementation, and large refactors. Suggested models: ${AGENT_MODELS.codex.join(", ")} (${AGENT_MODELS.codex[0]} is the default).` : null,
|
|
12124
12301
|
opencodeAvailable ? `Use provider 'opencode' for cheaper routine implementation tasks through OpenRouter-backed open source models. Suggested models: ${AGENT_MODELS.opencode.join(", ")}.` : null,
|
|
12302
|
+
piAvailable ? `Use provider 'pi' for coding tasks through Pi's OpenRouter-backed coding agent. Suggested models: ${AGENT_MODELS.pi.join(", ")}.` : null,
|
|
12125
12303
|
cursorAvailable ? `Use provider 'cursor' for fast iteration on code changes. Suggested models: ${AGENT_MODELS.cursor.join(", ")}.` : null
|
|
12126
12304
|
].filter(Boolean);
|
|
12127
12305
|
const agentSelectionLines = extraAgentLines.length > 0 ? `${extraAgentLines.join("\n\n")}
|
|
@@ -12244,14 +12422,14 @@ function getEnvironmentSection() {
|
|
|
12244
12422
|
].join("\n");
|
|
12245
12423
|
}
|
|
12246
12424
|
function buildRelaySystemPrompt(options) {
|
|
12247
|
-
const { customInstructions, codexAvailable, cursorAvailable, opencodeAvailable } = options ?? {};
|
|
12425
|
+
const { customInstructions, codexAvailable, cursorAvailable, opencodeAvailable, piAvailable } = options ?? {};
|
|
12248
12426
|
const sections = [
|
|
12249
12427
|
getIntroSection(),
|
|
12250
12428
|
getSystemSection(),
|
|
12251
12429
|
getDoingTasksSection(),
|
|
12252
12430
|
getActionsSection(),
|
|
12253
12431
|
getUsingToolsSection(),
|
|
12254
|
-
getDelegationSection(codexAvailable ?? false, cursorAvailable ?? false, opencodeAvailable ?? false),
|
|
12432
|
+
getDelegationSection(codexAvailable ?? false, cursorAvailable ?? false, opencodeAvailable ?? false, piAvailable ?? false),
|
|
12255
12433
|
getToneAndStyleSection(),
|
|
12256
12434
|
getOutputEfficiencySection(),
|
|
12257
12435
|
getEnvironmentSection(),
|
|
@@ -12284,12 +12462,13 @@ var RelayManager = class {
|
|
|
12284
12462
|
const codexAvailable = options.codexAvailable ?? false;
|
|
12285
12463
|
const cursorAvailable = options.cursorAvailable ?? false;
|
|
12286
12464
|
const opencodeAvailable = options.opencodeAvailable ?? false;
|
|
12465
|
+
const piAvailable = options.piAvailable ?? false;
|
|
12287
12466
|
this.inner = new ClaudeManager({
|
|
12288
12467
|
...options,
|
|
12289
|
-
systemPromptOverride: (customInstructions) => buildRelaySystemPrompt({ customInstructions, codexAvailable, cursorAvailable, opencodeAvailable }),
|
|
12468
|
+
systemPromptOverride: (customInstructions) => buildRelaySystemPrompt({ customInstructions, codexAvailable, cursorAvailable, opencodeAvailable, piAvailable }),
|
|
12290
12469
|
tools: RELAY_TOOLS,
|
|
12291
12470
|
mcpServers: {
|
|
12292
|
-
"relay-subagent-tools": createRelayMcpServer(options.chatId, { codexAvailable, cursorAvailable, opencodeAvailable })
|
|
12471
|
+
"relay-subagent-tools": createRelayMcpServer(options.chatId, { codexAvailable, cursorAvailable, opencodeAvailable, piAvailable })
|
|
12293
12472
|
},
|
|
12294
12473
|
envOverrides: {
|
|
12295
12474
|
CLAUDE_CODE_STREAM_CLOSE_TIMEOUT: "900000"
|
|
@@ -12381,17 +12560,17 @@ var keepAliveService = new KeepAliveService();
|
|
|
12381
12560
|
// src/services/canvas-service.ts
|
|
12382
12561
|
import { readdir as readdir6, readFile as readFile12, stat as stat3 } from "fs/promises";
|
|
12383
12562
|
import { homedir as homedir13 } from "os";
|
|
12384
|
-
import { join as
|
|
12563
|
+
import { join as join20 } from "path";
|
|
12385
12564
|
var GLOBAL_CANVAS_DIRECTORIES = [
|
|
12386
|
-
|
|
12387
|
-
|
|
12388
|
-
|
|
12565
|
+
join20(homedir13(), ".claude", "plans"),
|
|
12566
|
+
join20(process.env.XDG_DATA_HOME ?? join20(homedir13(), ".local", "share"), "opencode", "plans"),
|
|
12567
|
+
join20(homedir13(), ".replicas", "canvas")
|
|
12389
12568
|
];
|
|
12390
12569
|
async function canvasDirectories() {
|
|
12391
12570
|
const repositories = await gitService.listRepositories().catch(() => []);
|
|
12392
12571
|
return [
|
|
12393
12572
|
...GLOBAL_CANVAS_DIRECTORIES,
|
|
12394
|
-
...repositories.map((repository) =>
|
|
12573
|
+
...repositories.map((repository) => join20(repository.path, ".opencode", "plans"))
|
|
12395
12574
|
];
|
|
12396
12575
|
}
|
|
12397
12576
|
var CanvasService = class {
|
|
@@ -12411,7 +12590,7 @@ var CanvasService = class {
|
|
|
12411
12590
|
const { kind } = classifyCanvasFilename(entry.name);
|
|
12412
12591
|
let sizeBytes = 0;
|
|
12413
12592
|
try {
|
|
12414
|
-
const s = await stat3(
|
|
12593
|
+
const s = await stat3(join20(directory, entry.name));
|
|
12415
12594
|
sizeBytes = s.size;
|
|
12416
12595
|
} catch {
|
|
12417
12596
|
continue;
|
|
@@ -12426,7 +12605,7 @@ var CanvasService = class {
|
|
|
12426
12605
|
if (!safe) return null;
|
|
12427
12606
|
const { kind, mimeType } = classifyCanvasFilename(safe);
|
|
12428
12607
|
for (const directory of await canvasDirectories()) {
|
|
12429
|
-
const filePath =
|
|
12608
|
+
const filePath = join20(directory, safe);
|
|
12430
12609
|
let sizeBytes = 0;
|
|
12431
12610
|
let updatedAt = "";
|
|
12432
12611
|
try {
|
|
@@ -12563,13 +12742,13 @@ async function reconcileCanvasItems(filenames) {
|
|
|
12563
12742
|
|
|
12564
12743
|
// src/services/upload-chat-transcripts.ts
|
|
12565
12744
|
import { readdir as readdir7, readFile as readFile13 } from "fs/promises";
|
|
12566
|
-
import { basename as basename2, join as
|
|
12745
|
+
import { basename as basename2, join as join21 } from "path";
|
|
12567
12746
|
import { homedir as homedir14 } from "os";
|
|
12568
|
-
var ENGINE_DIR3 =
|
|
12747
|
+
var ENGINE_DIR3 = join21(homedir14(), ".replicas", "engine");
|
|
12569
12748
|
var HISTORY_DIRS = [
|
|
12570
|
-
|
|
12571
|
-
|
|
12572
|
-
|
|
12749
|
+
join21(ENGINE_DIR3, "claude-histories"),
|
|
12750
|
+
join21(ENGINE_DIR3, "relay-histories"),
|
|
12751
|
+
join21(ENGINE_DIR3, "codex-histories")
|
|
12573
12752
|
];
|
|
12574
12753
|
async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
|
|
12575
12754
|
let flushed = 0;
|
|
@@ -12586,7 +12765,7 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
|
|
|
12586
12765
|
if (!entry.endsWith(".jsonl")) continue;
|
|
12587
12766
|
const chatId = basename2(entry, ".jsonl");
|
|
12588
12767
|
tasks.push(
|
|
12589
|
-
uploadChatTranscript(chatId,
|
|
12768
|
+
uploadChatTranscript(chatId, join21(dir, entry), chatsById.get(chatId)).then(() => {
|
|
12590
12769
|
flushed++;
|
|
12591
12770
|
}).catch((err) => {
|
|
12592
12771
|
failed++;
|
|
@@ -12665,9 +12844,9 @@ async function flushRepoState() {
|
|
|
12665
12844
|
}
|
|
12666
12845
|
|
|
12667
12846
|
// src/services/chat/chat-service.ts
|
|
12668
|
-
var CHAT_SENDERS_DIR =
|
|
12669
|
-
var CODEX_AUTH_PATH2 =
|
|
12670
|
-
var OPENCODE_AUTH_PATH2 =
|
|
12847
|
+
var CHAT_SENDERS_DIR = join22(ENGINE_DIR2, "chat-senders");
|
|
12848
|
+
var CODEX_AUTH_PATH2 = join22(homedir15(), ".codex", "auth.json");
|
|
12849
|
+
var OPENCODE_AUTH_PATH2 = join22(homedir15(), ".local", "share", "opencode", "auth.json");
|
|
12671
12850
|
var CHATS_BACKUP_FILE = `${CHATS_FILE}.bak`;
|
|
12672
12851
|
function isChatMessageSender(value) {
|
|
12673
12852
|
if (!isRecord4(value)) return false;
|
|
@@ -12679,6 +12858,9 @@ function isCodexAvailable() {
|
|
|
12679
12858
|
function isOpencodeAvailable() {
|
|
12680
12859
|
return existsSync7(OPENCODE_AUTH_PATH2) || Boolean(ENGINE_ENV.OPENROUTER_API_KEY);
|
|
12681
12860
|
}
|
|
12861
|
+
function isPiAvailable() {
|
|
12862
|
+
return Boolean(ENGINE_ENV.OPENROUTER_API_KEY);
|
|
12863
|
+
}
|
|
12682
12864
|
function isCursorAvailable() {
|
|
12683
12865
|
return Boolean(ENGINE_ENV.CURSOR_API_KEY);
|
|
12684
12866
|
}
|
|
@@ -12727,7 +12909,7 @@ function isPersistedChat(value) {
|
|
|
12727
12909
|
return false;
|
|
12728
12910
|
}
|
|
12729
12911
|
const candidate = value;
|
|
12730
|
-
return typeof candidate.id === "string" &&
|
|
12912
|
+
return typeof candidate.id === "string" && typeof candidate.provider === "string" && isValidAgentProvider(candidate.provider) && 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") && (candidate.deletedAt === void 0 || candidate.deletedAt === null || typeof candidate.deletedAt === "string");
|
|
12731
12913
|
}
|
|
12732
12914
|
function normalizePersistedChat(chat) {
|
|
12733
12915
|
const isLegacyCodexSdkChat = chat.provider === "codex" && (chat.codexBackend === "sdk" || chat.codexBackend === void 0 && chat.providerSessionId !== null);
|
|
@@ -12779,13 +12961,13 @@ var ChatService = class {
|
|
|
12779
12961
|
persistInFlight = false;
|
|
12780
12962
|
persistQueued = false;
|
|
12781
12963
|
async initialize() {
|
|
12782
|
-
await
|
|
12783
|
-
await
|
|
12784
|
-
await
|
|
12785
|
-
await
|
|
12786
|
-
await
|
|
12787
|
-
await
|
|
12788
|
-
await
|
|
12964
|
+
await mkdir14(ENGINE_DIR2, { recursive: true });
|
|
12965
|
+
await mkdir14(CLAUDE_HISTORY_DIR, { recursive: true });
|
|
12966
|
+
await mkdir14(RELAY_HISTORY_DIR, { recursive: true });
|
|
12967
|
+
await mkdir14(CODEX_HISTORY_DIR, { recursive: true });
|
|
12968
|
+
await mkdir14(CURSOR_HISTORY_DIR, { recursive: true });
|
|
12969
|
+
await mkdir14(OPENCODE_HISTORY_DIR, { recursive: true });
|
|
12970
|
+
await mkdir14(CHAT_SENDERS_DIR, { recursive: true });
|
|
12789
12971
|
const persisted = await this.loadChats();
|
|
12790
12972
|
for (const chat of persisted) {
|
|
12791
12973
|
const runtime = this.createRuntimeChat(chat);
|
|
@@ -12909,7 +13091,7 @@ var ChatService = class {
|
|
|
12909
13091
|
};
|
|
12910
13092
|
}
|
|
12911
13093
|
senderFilePath(chatId) {
|
|
12912
|
-
return
|
|
13094
|
+
return join22(CHAT_SENDERS_DIR, `${chatId}.jsonl`);
|
|
12913
13095
|
}
|
|
12914
13096
|
async appendSender(chatId, sender) {
|
|
12915
13097
|
try {
|
|
@@ -13103,7 +13285,7 @@ var ChatService = class {
|
|
|
13103
13285
|
return descendants;
|
|
13104
13286
|
}
|
|
13105
13287
|
async deleteHistoryFile(persisted) {
|
|
13106
|
-
await rm2(
|
|
13288
|
+
await rm2(join22(HISTORY_DIR_BY_PROVIDER[persisted.provider], `${persisted.id}.jsonl`), { force: true });
|
|
13107
13289
|
await rm2(this.senderFilePath(persisted.id), { force: true });
|
|
13108
13290
|
}
|
|
13109
13291
|
async getChatHistory(chatId, page = {}) {
|
|
@@ -13177,7 +13359,7 @@ var ChatService = class {
|
|
|
13177
13359
|
if (persisted.provider === "claude") {
|
|
13178
13360
|
provider = new ClaudeManager({
|
|
13179
13361
|
workingDirectory: this.workingDirectory,
|
|
13180
|
-
historyFilePath:
|
|
13362
|
+
historyFilePath: join22(CLAUDE_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
13181
13363
|
initialSessionId: persisted.providerSessionId,
|
|
13182
13364
|
onSaveSessionId: saveSession,
|
|
13183
13365
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -13186,7 +13368,7 @@ var ChatService = class {
|
|
|
13186
13368
|
} else if (persisted.provider === "relay") {
|
|
13187
13369
|
provider = new RelayManager({
|
|
13188
13370
|
workingDirectory: this.workingDirectory,
|
|
13189
|
-
historyFilePath:
|
|
13371
|
+
historyFilePath: join22(RELAY_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
13190
13372
|
initialSessionId: persisted.providerSessionId,
|
|
13191
13373
|
onSaveSessionId: saveSession,
|
|
13192
13374
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -13194,12 +13376,13 @@ var ChatService = class {
|
|
|
13194
13376
|
chatId: persisted.id,
|
|
13195
13377
|
codexAvailable: isCodexAvailable(),
|
|
13196
13378
|
opencodeAvailable: isOpencodeAvailable(),
|
|
13379
|
+
piAvailable: isPiAvailable(),
|
|
13197
13380
|
cursorAvailable: isCursorAvailable()
|
|
13198
13381
|
});
|
|
13199
13382
|
} else if (persisted.provider === "cursor") {
|
|
13200
13383
|
provider = new CursorManager({
|
|
13201
13384
|
workingDirectory: this.workingDirectory,
|
|
13202
|
-
historyFilePath:
|
|
13385
|
+
historyFilePath: join22(CURSOR_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
13203
13386
|
initialSessionId: persisted.providerSessionId,
|
|
13204
13387
|
onSaveSessionId: saveSession,
|
|
13205
13388
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -13208,7 +13391,16 @@ var ChatService = class {
|
|
|
13208
13391
|
} else if (persisted.provider === "opencode") {
|
|
13209
13392
|
provider = new OpencodeManager({
|
|
13210
13393
|
workingDirectory: this.workingDirectory,
|
|
13211
|
-
historyFilePath:
|
|
13394
|
+
historyFilePath: join22(OPENCODE_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
13395
|
+
initialSessionId: persisted.providerSessionId,
|
|
13396
|
+
onSaveSessionId: saveSession,
|
|
13397
|
+
onTurnComplete: onProviderTurnComplete,
|
|
13398
|
+
onEvent: onProviderEvent
|
|
13399
|
+
});
|
|
13400
|
+
} else if (persisted.provider === "pi") {
|
|
13401
|
+
provider = new PiManager({
|
|
13402
|
+
workingDirectory: this.workingDirectory,
|
|
13403
|
+
historyFilePath: join22(PI_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
13212
13404
|
initialSessionId: persisted.providerSessionId,
|
|
13213
13405
|
onSaveSessionId: saveSession,
|
|
13214
13406
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -13217,7 +13409,7 @@ var ChatService = class {
|
|
|
13217
13409
|
} else {
|
|
13218
13410
|
provider = new CodexAspManager({
|
|
13219
13411
|
workingDirectory: this.workingDirectory,
|
|
13220
|
-
historyFilePath:
|
|
13412
|
+
historyFilePath: join22(CODEX_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
13221
13413
|
initialSessionId: persisted.providerSessionId,
|
|
13222
13414
|
onSaveSessionId: saveSession,
|
|
13223
13415
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -13357,7 +13549,7 @@ var ChatService = class {
|
|
|
13357
13549
|
});
|
|
13358
13550
|
uploadChatTranscript(
|
|
13359
13551
|
chatId,
|
|
13360
|
-
|
|
13552
|
+
join22(HISTORY_DIR_BY_PROVIDER[chat.persisted.provider], `${chatId}.jsonl`),
|
|
13361
13553
|
this.toSummary(chat)
|
|
13362
13554
|
).catch((err) => {
|
|
13363
13555
|
console.error("[ChatService] Failed to upload chat transcript:", { chatId, err });
|
|
@@ -13484,7 +13676,7 @@ var ChatService = class {
|
|
|
13484
13676
|
// src/services/repo-file-service.ts
|
|
13485
13677
|
import { execFile as execFile2 } from "child_process";
|
|
13486
13678
|
import { readFile as readFile15, realpath, stat as stat4 } from "fs/promises";
|
|
13487
|
-
import { join as
|
|
13679
|
+
import { join as join23, resolve as resolve2, extname as extname2 } from "path";
|
|
13488
13680
|
var CACHE_TTL_MS = 3e4;
|
|
13489
13681
|
var SEARCH_TIMEOUT_MS = 15e3;
|
|
13490
13682
|
var MAX_CONTENT_BYTES = 256 * 1024;
|
|
@@ -13644,7 +13836,7 @@ var RepoFileService = class {
|
|
|
13644
13836
|
const repo = repos.find((r) => r.name === repoName);
|
|
13645
13837
|
if (!repo) return null;
|
|
13646
13838
|
try {
|
|
13647
|
-
const fullPath = await realpath(resolve2(
|
|
13839
|
+
const fullPath = await realpath(resolve2(join23(repo.path, filePath)));
|
|
13648
13840
|
const repoRoot = await realpath(repo.path);
|
|
13649
13841
|
const repoPrefix = repoRoot.endsWith("/") ? repoRoot : repoRoot + "/";
|
|
13650
13842
|
if (!fullPath.startsWith(repoPrefix) && fullPath !== repoRoot) return null;
|
|
@@ -13752,20 +13944,20 @@ var RepoFileService = class {
|
|
|
13752
13944
|
import { Hono } from "hono";
|
|
13753
13945
|
import { z as z2 } from "zod";
|
|
13754
13946
|
import { readdir as readdir9, stat as stat5, readFile as readFile18 } from "fs/promises";
|
|
13755
|
-
import { join as
|
|
13947
|
+
import { join as join26, resolve as resolve3 } from "path";
|
|
13756
13948
|
|
|
13757
13949
|
// src/services/warm-hooks-service.ts
|
|
13758
13950
|
import { spawn as spawn4 } from "child_process";
|
|
13759
13951
|
import { readFile as readFile17 } from "fs/promises";
|
|
13760
13952
|
import { existsSync as existsSync8 } from "fs";
|
|
13761
|
-
import { join as
|
|
13953
|
+
import { join as join25 } from "path";
|
|
13762
13954
|
|
|
13763
13955
|
// src/services/warm-hook-logs-service.ts
|
|
13764
|
-
import { mkdir as
|
|
13956
|
+
import { mkdir as mkdir15, readFile as readFile16, writeFile as writeFile6, readdir as readdir8, appendFile as appendFile4, unlink as unlink3 } from "fs/promises";
|
|
13765
13957
|
import { homedir as homedir16 } from "os";
|
|
13766
|
-
import { join as
|
|
13767
|
-
var LOGS_DIR2 =
|
|
13768
|
-
var CURRENT_RUN_LOG =
|
|
13958
|
+
import { join as join24 } from "path";
|
|
13959
|
+
var LOGS_DIR2 = join24(homedir16(), ".replicas", "warm-hook-logs");
|
|
13960
|
+
var CURRENT_RUN_LOG = join24(LOGS_DIR2, "current-run.log");
|
|
13769
13961
|
var GLOBAL_FILENAME = "global.json";
|
|
13770
13962
|
function withPreview2(stored) {
|
|
13771
13963
|
const preview = buildHookOutputPreview(stored.output);
|
|
@@ -13773,7 +13965,7 @@ function withPreview2(stored) {
|
|
|
13773
13965
|
}
|
|
13774
13966
|
var WarmHookLogsService = class {
|
|
13775
13967
|
async ensureDir() {
|
|
13776
|
-
await
|
|
13968
|
+
await mkdir15(LOGS_DIR2, { recursive: true });
|
|
13777
13969
|
}
|
|
13778
13970
|
async saveGlobalHookLog(entry) {
|
|
13779
13971
|
await this.ensureDir();
|
|
@@ -13782,7 +13974,7 @@ var WarmHookLogsService = class {
|
|
|
13782
13974
|
hookName: "organization",
|
|
13783
13975
|
...entry
|
|
13784
13976
|
};
|
|
13785
|
-
await writeFile6(
|
|
13977
|
+
await writeFile6(join24(LOGS_DIR2, GLOBAL_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
13786
13978
|
`, "utf-8");
|
|
13787
13979
|
}
|
|
13788
13980
|
async saveEnvironmentHookLog(entry) {
|
|
@@ -13792,7 +13984,7 @@ var WarmHookLogsService = class {
|
|
|
13792
13984
|
hookName: "environment",
|
|
13793
13985
|
...entry
|
|
13794
13986
|
};
|
|
13795
|
-
await writeFile6(
|
|
13987
|
+
await writeFile6(join24(LOGS_DIR2, ENVIRONMENT_HOOK_LOG_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
13796
13988
|
`, "utf-8");
|
|
13797
13989
|
}
|
|
13798
13990
|
async saveRepoHookLog(repoName, entry) {
|
|
@@ -13802,7 +13994,7 @@ var WarmHookLogsService = class {
|
|
|
13802
13994
|
hookName: repoName,
|
|
13803
13995
|
...entry
|
|
13804
13996
|
};
|
|
13805
|
-
await writeFile6(
|
|
13997
|
+
await writeFile6(join24(LOGS_DIR2, repoHookLogFilename(repoName)), `${JSON.stringify(log, null, 2)}
|
|
13806
13998
|
`, "utf-8");
|
|
13807
13999
|
}
|
|
13808
14000
|
async getAllLogs() {
|
|
@@ -13821,7 +14013,7 @@ var WarmHookLogsService = class {
|
|
|
13821
14013
|
continue;
|
|
13822
14014
|
}
|
|
13823
14015
|
try {
|
|
13824
|
-
const raw = await readFile16(
|
|
14016
|
+
const raw = await readFile16(join24(LOGS_DIR2, file), "utf-8");
|
|
13825
14017
|
const stored = JSON.parse(raw);
|
|
13826
14018
|
logs.push(withPreview2(stored));
|
|
13827
14019
|
} catch {
|
|
@@ -13859,7 +14051,7 @@ var WarmHookLogsService = class {
|
|
|
13859
14051
|
async getFullOutput(hookType, hookName) {
|
|
13860
14052
|
const filename = hookType === "global" ? GLOBAL_FILENAME : hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
13861
14053
|
try {
|
|
13862
|
-
const raw = await readFile16(
|
|
14054
|
+
const raw = await readFile16(join24(LOGS_DIR2, filename), "utf-8");
|
|
13863
14055
|
const stored = JSON.parse(raw);
|
|
13864
14056
|
if (stored.hookType !== hookType || stored.hookName !== hookName) {
|
|
13865
14057
|
return null;
|
|
@@ -13878,7 +14070,7 @@ var warmHookLogsService = new WarmHookLogsService();
|
|
|
13878
14070
|
// src/services/warm-hooks-service.ts
|
|
13879
14071
|
async function readRepoWarmHook(repoPath) {
|
|
13880
14072
|
for (const filename of REPLICAS_CONFIG_FILENAMES) {
|
|
13881
|
-
const configPath =
|
|
14073
|
+
const configPath = join25(repoPath, filename);
|
|
13882
14074
|
if (!existsSync8(configPath)) {
|
|
13883
14075
|
continue;
|
|
13884
14076
|
}
|
|
@@ -14262,7 +14454,7 @@ var setWorkspaceNameSchema = z2.object({
|
|
|
14262
14454
|
name: z2.string().min(1).max(48)
|
|
14263
14455
|
});
|
|
14264
14456
|
var createChatSchema = z2.object({
|
|
14265
|
-
provider: z2.enum(["claude", "codex", "cursor", "opencode", "relay"]),
|
|
14457
|
+
provider: z2.enum(["claude", "codex", "cursor", "opencode", "pi", "relay"]),
|
|
14266
14458
|
title: z2.string().min(1).optional(),
|
|
14267
14459
|
parentChatId: z2.string().uuid().optional(),
|
|
14268
14460
|
clientRequestId: z2.string().min(1).max(128).optional()
|
|
@@ -15100,7 +15292,7 @@ data: ${JSON.stringify("Terminal session not found")}
|
|
|
15100
15292
|
const logFiles = files.filter((f) => f.endsWith(".log"));
|
|
15101
15293
|
const sessions = await Promise.all(
|
|
15102
15294
|
logFiles.map(async (filename) => {
|
|
15103
|
-
const filePath =
|
|
15295
|
+
const filePath = join26(LOG_DIR, filename);
|
|
15104
15296
|
const fileStat = await stat5(filePath);
|
|
15105
15297
|
const sessionId = filename.replace(/\.log$/, "");
|
|
15106
15298
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "replicas-engine",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.452",
|
|
4
4
|
"description": "Lightweight API server for Replicas workspaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
"@connectrpc/connect-node": "1.7.0",
|
|
36
36
|
"@cursor/sdk": "1.0.19",
|
|
37
37
|
"@hono/node-server": "^1.19.5",
|
|
38
|
+
"@mariozechner/pi-ai": "0.73.1",
|
|
39
|
+
"@mariozechner/pi-coding-agent": "0.73.1",
|
|
38
40
|
"@opencode-ai/sdk": "1.17.9",
|
|
39
41
|
"hono": "^4.10.3",
|
|
40
42
|
"opencode-ai": "1.17.9",
|