replicas-engine 0.1.729 → 0.1.731

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
@@ -8,11 +8,12 @@ import {
8
8
  monolithService,
9
9
  reportCommandProtectionBlock,
10
10
  setAgentCredentialSnapshot
11
- } from "./chunk-SI3OKIHR.js";
11
+ } from "./chunk-FOMGATAT.js";
12
12
  import {
13
13
  ACCOUNT_RATE_LIMITS_UPDATED_METHOD,
14
14
  AGENT_MESSAGE_DELTA_METHOD,
15
15
  AppServerProcess,
16
+ AspClient,
16
17
  COMMAND_EXECUTION_OUTPUT_DELTA_METHOD,
17
18
  FILE_CHANGE_OUTPUT_DELTA_METHOD,
18
19
  ITEM_COMPLETED_METHOD,
@@ -35,7 +36,7 @@ import {
35
36
  execFileAsync,
36
37
  putPresignedFile,
37
38
  recoverCompletedTurn
38
- } from "./chunk-NPXUYMVM.js";
39
+ } from "./chunk-RUIFVQCV.js";
39
40
  import {
40
41
  isRecord as isRecord2
41
42
  } from "./chunk-2RB7SIP3.js";
@@ -73,6 +74,7 @@ import {
73
74
  CODEX_QUOTA_STATUS_EVENT_TYPE,
74
75
  COMPACTION_STATUS_EVENT_TYPE,
75
76
  CONTEXT_USAGE_EVENT_TYPE,
77
+ CREDENTIAL_METHOD,
76
78
  CURSOR_CONNECTION_STATUS_EVENT_TYPE,
77
79
  DEFAULT_ASTER_MODEL,
78
80
  DEFAULT_CHAT_TITLES,
@@ -83,6 +85,7 @@ import {
83
85
  DEFAULT_FX_MODEL,
84
86
  DEFAULT_HOOK_OUTPUT_PREVIEW_CHARS,
85
87
  DEFAULT_KIMI_MODEL,
88
+ DEFAULT_MUSE_MODEL,
86
89
  DEFAULT_OPENCODE_MODEL,
87
90
  DEFAULT_PI_MODEL,
88
91
  DEFAULT_START_HOOK_TIMEOUT_MS,
@@ -213,10 +216,11 @@ import {
213
216
  sanitizeCanvasFilename,
214
217
  sendChatMessageRequestSchema,
215
218
  serializeCanvasContentResponse,
219
+ serializeMuseAuthFile,
216
220
  shellQuotePosix,
217
221
  stripAgentDiagnosticErrors,
218
222
  withTimeout
219
- } from "./chunk-2UL5LXFV.js";
223
+ } from "./chunk-6P3FBKKS.js";
220
224
 
221
225
  // src/index.ts
222
226
  import { serve } from "@hono/node-server";
@@ -1720,6 +1724,7 @@ import { join as join6 } from "path";
1720
1724
  var OPENCODE_AUTH_PATH = join6(homedir3(), ".local", "share", "opencode", "auth.json");
1721
1725
  var PI_AUTH_PATH = join6(homedir3(), ".pi", "agent", "auth.json");
1722
1726
  var DEEPSEEK_AUTH_PATH = join6(homedir3(), ".replicas", "deepseek-auth.json");
1727
+ var MUSE_AUTH_PATH = join6(homedir3(), ".config", "muse", "auth.json");
1723
1728
 
1724
1729
  // src/managers/deepseek-auth.ts
1725
1730
  import { readFileSync as readFileSync2 } from "fs";
@@ -1835,6 +1840,7 @@ function createDefaultDetails() {
1835
1840
  deepseekAuthMethod: "none",
1836
1841
  fxAuthMethod: "none",
1837
1842
  kimiAuthMethod: "none",
1843
+ museAuthMethod: "none",
1838
1844
  opencodeAuthMethod: "none",
1839
1845
  piAuthMethod: "none",
1840
1846
  lastUpdatedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -1877,6 +1883,7 @@ var EnvironmentDetailsService = class {
1877
1883
  details.deepseekAuthMethod = detectDeepseekAuthMethod();
1878
1884
  details.fxAuthMethod = detectFxAuthMethod();
1879
1885
  details.kimiAuthMethod = detectFxAuthMethod();
1886
+ details.museAuthMethod = existsSync2(MUSE_AUTH_PATH) ? "oauth" : "none";
1880
1887
  details.opencodeAuthMethod = detectOpencodeAuthMethod();
1881
1888
  details.piAuthMethod = detectPiAuthMethod();
1882
1889
  details.credentialFallbacks = listCredentialFallbacks();
@@ -2632,7 +2639,7 @@ async function registerDesktopPreview() {
2632
2639
 
2633
2640
  // src/services/chat/chat-service.ts
2634
2641
  import { existsSync as existsSync11 } from "fs";
2635
- import { appendFile as appendFile4, copyFile as copyFile2, mkdir as mkdir18, readFile as readFile20, rename as rename3, rm as rm3 } from "fs/promises";
2642
+ import { appendFile as appendFile4, copyFile as copyFile2, mkdir as mkdir19, readFile as readFile20, rename as rename3, rm as rm3 } from "fs/promises";
2636
2643
  import { join as join28 } from "path";
2637
2644
  import { randomUUID as randomUUID9 } from "crypto";
2638
2645
 
@@ -3313,10 +3320,51 @@ async function removeTempImageFiles(paths) {
3313
3320
  import { existsSync as existsSync5 } from "fs";
3314
3321
  import { join as join13 } from "path";
3315
3322
 
3323
+ // src/managers/muse-token-manager.ts
3324
+ var MuseTokenManager = class extends BaseRefreshManager {
3325
+ constructor() {
3326
+ super("MuseTokenManager");
3327
+ }
3328
+ doRefresh() {
3329
+ return Promise.resolve();
3330
+ }
3331
+ async fetchFreshCredentials(failureReason, failureKind = "exhausted", failedCredential = ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS.muse) {
3332
+ return this.swapCredentials({
3333
+ provider: "muse",
3334
+ failureKind,
3335
+ refresh: async (exclusions) => {
3336
+ const request = {
3337
+ failedMethod: CREDENTIAL_METHOD.MUSE_OAUTH,
3338
+ ...failedCredential ? { failedCredential } : {},
3339
+ failureReason,
3340
+ failureKind,
3341
+ ...exclusions
3342
+ };
3343
+ const response = await monolithRequest("/v1/engine/muse/refresh-credentials", { body: request });
3344
+ if (!response.ok) {
3345
+ throw new Error(`Credentials refresh failed: ${response.status} ${await response.text()}`);
3346
+ }
3347
+ const data = await response.json();
3348
+ await writeSecureCredentialFile(MUSE_AUTH_PATH, serializeMuseAuthFile(data), { ensureParentDir: true });
3349
+ if (data.scope) {
3350
+ setAgentCredentialSnapshot("muse", {
3351
+ method: data.type,
3352
+ scope: data.scope,
3353
+ ...data.revision ? { revision: data.revision } : {}
3354
+ });
3355
+ }
3356
+ },
3357
+ isOauthNow: () => false
3358
+ });
3359
+ }
3360
+ };
3361
+ var museTokenManager = new MuseTokenManager();
3362
+
3316
3363
  // src/managers/auth-fallback.ts
3317
3364
  var SWAPPABLE_AGENTS = {
3318
3365
  claude: claudeTokenManager,
3319
- codex: codexTokenManager
3366
+ codex: codexTokenManager,
3367
+ muse: museTokenManager
3320
3368
  };
3321
3369
  var AuthFallbackCoordinator = class {
3322
3370
  constructor(provider, record) {
@@ -6499,6 +6547,7 @@ var PI_HISTORY_DIR = join16(ENGINE_DIR2, "pi-histories");
6499
6547
  var DEEPSEEK_HISTORY_DIR = join16(ENGINE_DIR2, "deepseek-histories");
6500
6548
  var FX_HISTORY_DIR = join16(ENGINE_DIR2, "fx-histories");
6501
6549
  var KIMI_HISTORY_DIR = join16(ENGINE_DIR2, "kimi-histories");
6550
+ var MUSE_HISTORY_DIR = join16(ENGINE_DIR2, "muse-histories");
6502
6551
  var HISTORY_DIR_BY_PROVIDER = {
6503
6552
  claude: CLAUDE_HISTORY_DIR,
6504
6553
  relay: RELAY_HISTORY_DIR,
@@ -6507,6 +6556,7 @@ var HISTORY_DIR_BY_PROVIDER = {
6507
6556
  deepseek: DEEPSEEK_HISTORY_DIR,
6508
6557
  fx: FX_HISTORY_DIR,
6509
6558
  kimi: KIMI_HISTORY_DIR,
6559
+ muse: MUSE_HISTORY_DIR,
6510
6560
  opencode: OPENCODE_HISTORY_DIR,
6511
6561
  pi: PI_HISTORY_DIR
6512
6562
  };
@@ -9441,11 +9491,388 @@ var KimiManager = class extends AcpManager {
9441
9491
  }
9442
9492
  };
9443
9493
 
9494
+ // src/managers/muse-manager.ts
9495
+ import { spawn as spawn6 } from "child_process";
9496
+ import { randomBytes as randomBytes2 } from "crypto";
9497
+ import { mkdir as mkdir15 } from "fs/promises";
9498
+ import { dirname as dirname9 } from "path";
9499
+ var MuseQuotaError = class extends Error {
9500
+ };
9501
+ function uuidV7() {
9502
+ const bytes = randomBytes2(16);
9503
+ let timestamp = BigInt(Date.now());
9504
+ for (let index = 5; index >= 0; index -= 1) {
9505
+ bytes[index] = Number(timestamp & 0xffn);
9506
+ timestamp >>= 8n;
9507
+ }
9508
+ bytes[6] = bytes[6] & 15 | 112;
9509
+ bytes[8] = bytes[8] & 63 | 128;
9510
+ const hex = bytes.toString("hex");
9511
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
9512
+ }
9513
+ function isPendingQuestion(value) {
9514
+ return isRecord(value) && typeof value.id === "string";
9515
+ }
9516
+ var MuseManager = class extends CodingAgentManager {
9517
+ historyFile;
9518
+ historyFilePath;
9519
+ process = null;
9520
+ client = null;
9521
+ sessionId = null;
9522
+ activeTurnId = null;
9523
+ deliveredInstructions = null;
9524
+ turnComplete = null;
9525
+ turnError = null;
9526
+ compactionComplete = null;
9527
+ pendingInput = null;
9528
+ slashCommands = null;
9529
+ constructor(options) {
9530
+ super({ ...options, provider: "muse" });
9531
+ this.historyFilePath = options.historyFilePath;
9532
+ this.historyFile = new CodexHistoryFile(options.historyFilePath);
9533
+ this.sessionId = options.initialSessionId;
9534
+ this.initializeManager(this.processMessageInternal.bind(this));
9535
+ }
9536
+ async initialize() {
9537
+ await mkdir15(dirname9(this.historyFilePath), { recursive: true });
9538
+ }
9539
+ getHistorySink() {
9540
+ return this.historyFile;
9541
+ }
9542
+ async start(model) {
9543
+ if (this.process) return;
9544
+ const child = spawn6("muse", ["serve", "--disable-sandbox", "--trust-workspace"], {
9545
+ cwd: this.workingDirectory,
9546
+ env: { ...process.env, MUSE_NO_AUTO_UPDATE: "1", NO_COLOR: "1" },
9547
+ stdio: ["pipe", "pipe", "pipe"]
9548
+ });
9549
+ this.process = child;
9550
+ const client2 = new AspClient({ stdin: child.stdin, stdout: child.stdout, jsonRpcVersion: "2.0" });
9551
+ this.client = client2;
9552
+ client2.on("notification", (notification) => this.handleNotification(notification));
9553
+ child.stderr.on("data", (chunk) => console.error("[muse MSP]", chunk.toString().trimEnd()));
9554
+ child.on("error", (error) => this.handleProcessExit(child, error));
9555
+ child.on("exit", (code, signal) => this.handleProcessExit(
9556
+ child,
9557
+ new Error(`Muse MSP exited with code ${code ?? signal}`)
9558
+ ));
9559
+ await this.request("initialize", { clientInfo: { name: "replicas", version: "1" } });
9560
+ this.notify("initialized");
9561
+ if (this.sessionId) {
9562
+ try {
9563
+ await this.request("session/resume", {
9564
+ commandId: uuidV7(),
9565
+ sessionId: this.sessionId,
9566
+ excludeItems: true
9567
+ });
9568
+ } catch {
9569
+ this.sessionId = null;
9570
+ }
9571
+ }
9572
+ if (!this.sessionId) {
9573
+ const result = await this.request("session/start", {
9574
+ commandId: uuidV7(),
9575
+ approvalMode: "allowAll",
9576
+ modelId: model,
9577
+ providerId: "meta",
9578
+ workspaceRoot: this.workingDirectory
9579
+ });
9580
+ const sessionId = isRecord(result) && isRecord(result.session) && typeof result.session.sessionId === "string" ? result.session.sessionId : void 0;
9581
+ if (!sessionId) throw new Error("Muse did not return a session id.");
9582
+ this.sessionId = sessionId;
9583
+ await this.onSaveSessionId(sessionId);
9584
+ }
9585
+ }
9586
+ request(method, params) {
9587
+ if (!this.client) return Promise.reject(new Error("Muse MSP is not running."));
9588
+ return this.client.request(method, params, { timeoutMs: 0 });
9589
+ }
9590
+ notify(method, params) {
9591
+ this.client?.notify(method, params);
9592
+ }
9593
+ handleProcessExit(child, error) {
9594
+ if (this.process !== child) return;
9595
+ const hadPendingRequest = (this.client?.pendingRequestCount ?? 0) > 0;
9596
+ this.process = null;
9597
+ this.client?.dispose(error);
9598
+ this.client = null;
9599
+ if (this.turnComplete && !hadPendingRequest) {
9600
+ this.recordHistoryEvent("muse-error", { message: error.message }, this.historyFile);
9601
+ }
9602
+ this.turnComplete?.resolve();
9603
+ this.turnComplete = null;
9604
+ this.compactionComplete?.resolve();
9605
+ this.compactionComplete = null;
9606
+ }
9607
+ stopProcess() {
9608
+ const process2 = this.process;
9609
+ this.process = null;
9610
+ this.client?.dispose();
9611
+ this.client = null;
9612
+ process2?.kill("SIGTERM");
9613
+ }
9614
+ createTurnInput(text, images) {
9615
+ const input = [{ type: "text", text }];
9616
+ for (const image of images ?? []) {
9617
+ if (image.source.type !== "base64") throw new Error("Muse requires images to be base64 encoded.");
9618
+ input.push({ type: "image", mediaType: image.source.media_type, base64Data: image.source.data });
9619
+ }
9620
+ return input;
9621
+ }
9622
+ handleNotification(frame) {
9623
+ if (!isRecord(frame) || typeof frame.method !== "string" || !isRecord(frame.params)) return;
9624
+ this.recordHistoryEvent(`muse-${frame.method.replaceAll("/", "-")}`, frame.params, this.historyFile);
9625
+ if (frame.method === "turn/completed") {
9626
+ this.turnError = isRecord(frame.params.error) && typeof frame.params.error.message === "string" ? frame.params.error.message : null;
9627
+ this.activeTurnId = null;
9628
+ this.turnComplete?.resolve();
9629
+ this.turnComplete = null;
9630
+ } else if (frame.method === "item/completed" && isRecord(frame.params.item) && frame.params.item.kind === "compaction") {
9631
+ this.compactionComplete?.resolve();
9632
+ this.compactionComplete = null;
9633
+ } else if (frame.method === "session/tokenUsage") {
9634
+ this.onUsageUpdate(frame.params, (/* @__PURE__ */ new Date()).toISOString());
9635
+ } else if (frame.method === "session/contextUsage") {
9636
+ const used = typeof frame.params.usedTokens === "number" ? frame.params.usedTokens : 0;
9637
+ const size = typeof frame.params.windowTokens === "number" ? frame.params.windowTokens : 0;
9638
+ this.historyFile.append(this.emitContextUsage({
9639
+ provider: "muse",
9640
+ source: "provider_usage",
9641
+ model: DEFAULT_MUSE_MODEL,
9642
+ totalTokens: used,
9643
+ maxTokens: size,
9644
+ percentage: size > 0 ? used / size * 100 : 0,
9645
+ categories: [],
9646
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
9647
+ }));
9648
+ } else if (frame.method === "userInput/requested" && typeof frame.params.userInputId === "string") {
9649
+ const questions = Array.isArray(frame.params.questions) ? frame.params.questions.filter(isPendingQuestion) : [];
9650
+ this.pendingInput = {
9651
+ userInputId: frame.params.userInputId,
9652
+ toolCallId: typeof frame.params.toolCallId === "string" ? frame.params.toolCallId : frame.params.userInputId,
9653
+ questions
9654
+ };
9655
+ this.recordHistoryEvent("replicas-tool-input-request", {
9656
+ requestId: frame.params.userInputId,
9657
+ toolUseId: this.pendingInput.toolCallId,
9658
+ toolName: typeof frame.params.toolName === "string" ? frame.params.toolName : "request_user_input",
9659
+ questions: questions.map((question) => ({
9660
+ id: question.id,
9661
+ prompt: question.question ?? question.id,
9662
+ multiSelect: question.selection?.mode === "multiple",
9663
+ options: (question.options ?? []).flatMap((option) => typeof option.label === "string" ? [{
9664
+ id: option.label,
9665
+ label: option.label,
9666
+ ...option.description ? { description: option.description } : {},
9667
+ ...option.preview?.content ? { preview: option.preview.content } : {}
9668
+ }] : [])
9669
+ })),
9670
+ parent_tool_use_id: null
9671
+ }, this.historyFile);
9672
+ }
9673
+ }
9674
+ async processMessageInternal(request) {
9675
+ let userMessageRecorded = false;
9676
+ const dispatch = async () => {
9677
+ const model = request.model ?? DEFAULT_MUSE_MODEL;
9678
+ await this.start(model);
9679
+ if (!this.sessionId) throw new Error("Muse MSP failed to initialize.");
9680
+ if (!userMessageRecorded) {
9681
+ this.recordUserMessageHistoryEvent(
9682
+ request,
9683
+ this.historyFile,
9684
+ /^\/compact$/i.test(request.message.trim()) ? { command: "compact" } : {}
9685
+ );
9686
+ userMessageRecorded = true;
9687
+ }
9688
+ if (/^\/compact$/i.test(request.message.trim())) {
9689
+ const completed2 = new Promise((resolve5) => {
9690
+ this.compactionComplete = { resolve: resolve5 };
9691
+ });
9692
+ const result2 = await this.request("session/compact", {
9693
+ commandId: uuidV7(),
9694
+ sessionId: this.sessionId
9695
+ });
9696
+ if (isRecord(result2) && result2.status === "accepted") {
9697
+ this.setCompacting(true);
9698
+ await completed2;
9699
+ } else {
9700
+ this.compactionComplete = null;
9701
+ }
9702
+ return;
9703
+ }
9704
+ await this.request("session/setApprovalMode", {
9705
+ commandId: uuidV7(),
9706
+ sessionId: this.sessionId,
9707
+ mode: request.planMode ? "denyUnmatched" : "allowAll"
9708
+ });
9709
+ await this.request("session/setModel", {
9710
+ commandId: uuidV7(),
9711
+ sessionId: this.sessionId,
9712
+ model: { providerId: "meta", modelId: model }
9713
+ });
9714
+ const instructions = this.buildCombinedInstructions(request.customInstructions);
9715
+ const pending = instructions && instructions !== this.deliveredInstructions ? instructions : null;
9716
+ const text = `${pending ? `<workspace-instructions>
9717
+ ${pending}
9718
+ </workspace-instructions>
9719
+
9720
+ ` : ""}${request.planMode ? "Plan the requested work without modifying files or running mutating commands.\n\n" : ""}${request.message}`;
9721
+ this.turnError = null;
9722
+ const completed = new Promise((resolve5) => {
9723
+ this.turnComplete = { resolve: resolve5 };
9724
+ });
9725
+ const result = await this.request("turn/start", {
9726
+ commandId: uuidV7(),
9727
+ sessionId: this.sessionId,
9728
+ input: this.createTurnInput(text, request.images),
9729
+ displayText: request.message,
9730
+ reasoningEffort: codexReasoningEffortForThinkingLevel(request.thinkingLevel)
9731
+ });
9732
+ if (!isRecord(result) || typeof result.turnId !== "string") throw new Error("Muse did not start a turn.");
9733
+ this.activeTurnId = result.turnId;
9734
+ if (pending) this.deliveredInstructions = pending;
9735
+ await completed;
9736
+ if (this.turnError && detectAgentQuotaLimit(this.turnError)) throw new MuseQuotaError(this.turnError);
9737
+ };
9738
+ try {
9739
+ await dispatch();
9740
+ } catch (error) {
9741
+ if (error instanceof MuseQuotaError) {
9742
+ const quotaKind = detectAgentQuotaLimit(error.message);
9743
+ const outcome = await this.fallBackCredential(quotaKind ?? "rate_limit", error.message);
9744
+ if (outcome === "switched") {
9745
+ this.stopProcess();
9746
+ try {
9747
+ await dispatch();
9748
+ } catch (retryError) {
9749
+ if (retryError instanceof MuseQuotaError) return;
9750
+ this.recordHistoryEvent("muse-error", {
9751
+ message: retryError instanceof Error ? retryError.message : String(retryError)
9752
+ }, this.historyFile);
9753
+ throw retryError;
9754
+ }
9755
+ }
9756
+ return;
9757
+ }
9758
+ this.recordHistoryEvent("muse-error", { message: error instanceof Error ? error.message : String(error) }, this.historyFile);
9759
+ throw error;
9760
+ } finally {
9761
+ this.turnComplete?.resolve();
9762
+ this.turnComplete = null;
9763
+ this.activeTurnId = null;
9764
+ this.turnError = null;
9765
+ this.pendingInput = null;
9766
+ this.compactionComplete?.resolve();
9767
+ this.compactionComplete = null;
9768
+ try {
9769
+ await this.historyFile.flush();
9770
+ } finally {
9771
+ await this.onTurnComplete();
9772
+ }
9773
+ }
9774
+ }
9775
+ async interruptActiveTurn() {
9776
+ if (!this.sessionId || !this.activeTurnId) return;
9777
+ await this.request("turn/interrupt", {
9778
+ commandId: uuidV7(),
9779
+ sessionId: this.sessionId,
9780
+ turnId: this.activeTurnId
9781
+ });
9782
+ }
9783
+ async steerRequest(request) {
9784
+ if (!this.sessionId || !this.activeTurnId) return false;
9785
+ await this.request("turn/steer", {
9786
+ commandId: uuidV7(),
9787
+ sessionId: this.sessionId,
9788
+ expectedTurnId: this.activeTurnId,
9789
+ input: this.createTurnInput(request.message, request.images),
9790
+ reasoningEffort: codexReasoningEffortForThinkingLevel(request.thinkingLevel)
9791
+ });
9792
+ return true;
9793
+ }
9794
+ async respondToToolInput(requestId, selectionId) {
9795
+ if (!this.pendingInput || this.pendingInput.userInputId !== requestId || !this.sessionId) return false;
9796
+ const pending = this.pendingInput;
9797
+ if (selectionId === "declined") {
9798
+ await this.request("userInput/cancel", {
9799
+ commandId: uuidV7(),
9800
+ sessionId: this.sessionId,
9801
+ userInputId: pending.userInputId
9802
+ });
9803
+ } else {
9804
+ const parsedSelections = JSON.parse(selectionId);
9805
+ const selections = isRecord(parsedSelections) ? parsedSelections : {};
9806
+ const answers = pending.questions.map((question) => {
9807
+ const selection = selections[question.id];
9808
+ const custom = isRecord(selection) && typeof selection.custom === "string" ? selection.custom.trim() : "";
9809
+ if (custom) return { questionId: question.id, freeText: custom };
9810
+ const options = isRecord(selection) && Array.isArray(selection.options) ? selection.options.filter((option) => typeof option === "string") : [];
9811
+ const labels = options.flatMap((id) => question.options?.some((option) => option.label === id) ? [id] : []);
9812
+ return question.selection?.mode === "multiple" ? { questionId: question.id, selectedLabels: labels } : { questionId: question.id, selectedLabel: labels[0] };
9813
+ });
9814
+ await this.request("userInput/answer", {
9815
+ commandId: uuidV7(),
9816
+ sessionId: this.sessionId,
9817
+ userInputId: pending.userInputId,
9818
+ answers
9819
+ });
9820
+ }
9821
+ this.pendingInput = null;
9822
+ this.recordHistoryEvent("replicas-tool-input-resolved", {
9823
+ requestId,
9824
+ toolUseId: pending.toolCallId,
9825
+ toolName: "request_user_input",
9826
+ selectionId: selectionId === "declined" ? "aborted" : selectionId,
9827
+ parent_tool_use_id: null
9828
+ }, this.historyFile);
9829
+ return true;
9830
+ }
9831
+ isAwaitingInput() {
9832
+ return this.pendingInput !== null;
9833
+ }
9834
+ async getHistory(page = {}) {
9835
+ await this.historyFile.flush();
9836
+ return { thread_id: this.sessionId, ...await this.historyFile.loadEventsPage(page), goal: null };
9837
+ }
9838
+ async listSlashCommands() {
9839
+ if (this.slashCommands) return this.slashCommands;
9840
+ try {
9841
+ const { stdout } = await execFileAsync("muse", [
9842
+ "skills",
9843
+ "list",
9844
+ "--enabled-only",
9845
+ "--workspace",
9846
+ this.workingDirectory,
9847
+ "--trust-workspace",
9848
+ "--json"
9849
+ ], { maxBuffer: SUBPROCESS_MAX_BUFFER });
9850
+ const parsed = JSON.parse(stdout);
9851
+ this.slashCommands = isRecord(parsed) && Array.isArray(parsed.skills) ? parsed.skills.flatMap((skill) => {
9852
+ if (!isRecord(skill) || typeof skill.name !== "string") return [];
9853
+ const command = createProviderSlashCommand(
9854
+ "muse",
9855
+ skill.name,
9856
+ typeof skill.description === "string" ? skill.description : void 0
9857
+ );
9858
+ return command ? [command] : [];
9859
+ }) : [];
9860
+ } catch (error) {
9861
+ console.warn("[MuseManager] Failed to load slash commands:", error);
9862
+ this.slashCommands = [];
9863
+ }
9864
+ return this.slashCommands;
9865
+ }
9866
+ dispose() {
9867
+ this.stopProcess();
9868
+ }
9869
+ };
9870
+
9444
9871
  // src/managers/opencode-manager.ts
9445
9872
  import { existsSync as existsSync9 } from "fs";
9446
- import { copyFile, mkdir as mkdir15, readFile as readFile15, rm as rm2 } from "fs/promises";
9447
- import { delimiter, dirname as dirname9, join as join21 } from "path";
9448
- import { randomBytes as randomBytes2 } from "crypto";
9873
+ import { copyFile, mkdir as mkdir16, readFile as readFile15, rm as rm2 } from "fs/promises";
9874
+ import { delimiter, dirname as dirname10, join as join21 } from "path";
9875
+ import { randomBytes as randomBytes3 } from "crypto";
9449
9876
  import { fileURLToPath as fileURLToPath3 } from "url";
9450
9877
  import { Agent } from "undici";
9451
9878
  import { z as z3 } from "zod";
@@ -9503,7 +9930,7 @@ async function getAllowedOpenRouterModels() {
9503
9930
  }
9504
9931
 
9505
9932
  // src/managers/opencode-manager.ts
9506
- var OPENCODE_SHIM_DIR = dirname9(fileURLToPath3(new URL("../../scripts/opencode", import.meta.url)));
9933
+ var OPENCODE_SHIM_DIR = dirname10(fileURLToPath3(new URL("../../scripts/opencode", import.meta.url)));
9507
9934
  var OPENCODE_COMMAND_PROTECTION_PLUGIN_SOURCE = join21(OPENCODE_SHIM_DIR, "opencode-command-protection-plugin.ts");
9508
9935
  var OPENCODE_COMMAND_PROTECTION_PLUGIN_PATH = join21(ENGINE_ENV.HOME_DIR, ".config", "opencode", "plugins", "replicas-command-protection.ts");
9509
9936
  var OPENCODE_LEGACY_COMMAND_PROTECTION_PLUGIN_PATH = join21(ENGINE_ENV.HOME_DIR, ".config", "opencode", "plugins", "replicas-command-protection.mjs");
@@ -9724,7 +10151,7 @@ var OpencodeManager = class extends CodingAgentManager {
9724
10151
  this.initializeManager(this.processMessageInternal.bind(this));
9725
10152
  }
9726
10153
  async initialize() {
9727
- await mkdir15(dirname9(this.historyFilePath), { recursive: true });
10154
+ await mkdir16(dirname10(this.historyFilePath), { recursive: true });
9728
10155
  }
9729
10156
  getHistorySink() {
9730
10157
  return this.historyFile;
@@ -9824,7 +10251,7 @@ var OpencodeManager = class extends CodingAgentManager {
9824
10251
  if (!existsSync9(OPENCODE_COMMAND_PROTECTION_PLUGIN_SOURCE)) {
9825
10252
  throw new Error("Opencode command protection plugin is missing from the engine package.");
9826
10253
  }
9827
- await mkdir15(dirname9(OPENCODE_COMMAND_PROTECTION_PLUGIN_PATH), { recursive: true });
10254
+ await mkdir16(dirname10(OPENCODE_COMMAND_PROTECTION_PLUGIN_PATH), { recursive: true });
9828
10255
  await copyFile(OPENCODE_COMMAND_PROTECTION_PLUGIN_SOURCE, OPENCODE_COMMAND_PROTECTION_PLUGIN_PATH);
9829
10256
  await rm2(OPENCODE_LEGACY_COMMAND_PROTECTION_PLUGIN_PATH, { force: true });
9830
10257
  process.env.REPLICAS_COMMAND_PROTECTION_HOOK_PATH = getCommandProtectionHookPath();
@@ -9836,7 +10263,7 @@ var OpencodeManager = class extends CodingAgentManager {
9836
10263
  if (!pathEntries.includes(OPENCODE_SHIM_DIR)) {
9837
10264
  process.env.PATH = [OPENCODE_SHIM_DIR, ...pathEntries].join(delimiter);
9838
10265
  }
9839
- const password = process.env.OPENCODE_SERVER_PASSWORD || randomBytes2(24).toString("base64url");
10266
+ const password = process.env.OPENCODE_SERVER_PASSWORD || randomBytes3(24).toString("base64url");
9840
10267
  process.env.OPENCODE_SERVER_PASSWORD = password;
9841
10268
  const config = opencodeConfig(providerId, configuredModel, providerModels);
9842
10269
  const mcp = await readProvisionedOpencodeMcpConfig();
@@ -10119,8 +10546,8 @@ var OpencodeManager = class extends CodingAgentManager {
10119
10546
  };
10120
10547
 
10121
10548
  // src/managers/pi-manager.ts
10122
- import { mkdir as mkdir16 } from "fs/promises";
10123
- import { dirname as dirname10, join as join22 } from "path";
10549
+ import { mkdir as mkdir17 } from "fs/promises";
10550
+ import { dirname as dirname11, join as join22 } from "path";
10124
10551
  import {
10125
10552
  AuthStorage,
10126
10553
  createAgentSession,
@@ -10239,7 +10666,7 @@ var PiManager = class extends CodingAgentManager {
10239
10666
  this.initializeManager(this.processMessageInternal.bind(this));
10240
10667
  }
10241
10668
  async initialize() {
10242
- await mkdir16(dirname10(this.historyFilePath), { recursive: true });
10669
+ await mkdir17(dirname11(this.historyFilePath), { recursive: true });
10243
10670
  }
10244
10671
  getHistorySink() {
10245
10672
  return this.historyFile;
@@ -10418,6 +10845,7 @@ function getAvailableRelayProviders(availability) {
10418
10845
  const deepseekAvailable = availability.deepseekAvailable ?? false;
10419
10846
  const fxAvailable = availability.fxAvailable ?? false;
10420
10847
  const kimiAvailable = availability.kimiAvailable ?? false;
10848
+ const museAvailable = availability.museAvailable ?? false;
10421
10849
  const opencodeAvailable = availability.opencodeAvailable ?? false;
10422
10850
  const piAvailable = availability.piAvailable ?? false;
10423
10851
  const providers = ["claude"];
@@ -10426,6 +10854,7 @@ function getAvailableRelayProviders(availability) {
10426
10854
  if (deepseekAvailable) providers.push("deepseek");
10427
10855
  if (fxAvailable) providers.push("fx");
10428
10856
  if (kimiAvailable) providers.push("kimi");
10857
+ if (museAvailable) providers.push("muse");
10429
10858
  if (opencodeAvailable) providers.push("opencode");
10430
10859
  if (piAvailable) providers.push("pi");
10431
10860
  providers.push("relay");
@@ -10519,6 +10948,10 @@ function extractFinalResponse(history) {
10519
10948
  const text = getFxTextChunk(payload.update, "agent_message_chunk");
10520
10949
  if (text) return text;
10521
10950
  }
10951
+ if (event.type === "muse-item-completed") {
10952
+ const item = isRecord(payload.item) ? payload.item : void 0;
10953
+ if (item?.kind === "agentMessage" && typeof item.text === "string" && item.text) return item.text;
10954
+ }
10522
10955
  }
10523
10956
  return null;
10524
10957
  }
@@ -10559,11 +10992,12 @@ You will also receive the chatId so you can send follow-up messages or clean up
10559
10992
  `DeepSeek Harness: ${AGENT_MODELS.deepseek.join(", ")}.`,
10560
10993
  `fx: ${AGENT_MODELS.fx.join(", ")}.`,
10561
10994
  `Kimi Code: ${AGENT_MODELS.kimi.join(", ")}.`,
10995
+ `Muse Code: ${AGENT_MODELS.muse.join(", ")}.`,
10562
10996
  `Opencode: ${AGENT_MODELS.opencode.join(", ")}.`,
10563
10997
  `Pi: ${AGENT_MODELS.pi.join(", ")}.`
10564
10998
  ].join(" ")),
10565
10999
  thinking_level: z4.enum(VALID_THINKING_LEVELS).optional().describe(
10566
- "Controls how much thinking/reasoning the subagent applies. low = light thinking, medium = moderate, high = deep reasoning, xhigh = extended effort, max = maximum effort, ultra = Codex ultra, ultracode = Claude Code dynamic workflows. Defaults: Claude = high; Codex, Cursor, DeepSeek Harness, fx, Kimi Code, Opencode, and Pi = medium."
11000
+ "Controls how much thinking/reasoning the subagent applies. low = light thinking, medium = moderate, high = deep reasoning, xhigh = extended effort, max = maximum effort, ultra = Codex and Muse ultra, ultracode = Claude Code dynamic workflows. Defaults: Claude and Muse Code = high; Codex, Cursor, DeepSeek Harness, fx, Kimi Code, Opencode, and Pi = medium."
10567
11001
  ),
10568
11002
  title: z4.string().optional().describe("Optional title for the subagent chat (for identification)."),
10569
11003
  timeout_minutes: z4.number().positive().optional().describe("Timeout in minutes for the subagent to complete (default: 10). Set higher for large tasks to avoid losing work.")
@@ -10815,8 +11249,8 @@ function getUsingToolsSection() {
10815
11249
  ];
10816
11250
  return [`# Using your tools`, ...prependBullets(items)].join("\n");
10817
11251
  }
10818
- function getDelegationSection(codexAvailable, cursorAvailable, deepseekAvailable, fxAvailable, kimiAvailable, opencodeAvailable, piAvailable) {
10819
- const providerList = getAvailableRelayProviders({ codexAvailable, cursorAvailable, deepseekAvailable, fxAvailable, kimiAvailable, opencodeAvailable, piAvailable }).join(", ");
11252
+ function getDelegationSection(codexAvailable, cursorAvailable, deepseekAvailable, fxAvailable, kimiAvailable, museAvailable, opencodeAvailable, piAvailable) {
11253
+ const providerList = getAvailableRelayProviders({ codexAvailable, cursorAvailable, deepseekAvailable, fxAvailable, kimiAvailable, museAvailable, opencodeAvailable, piAvailable }).join(", ");
10820
11254
  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).`;
10821
11255
  const claudeModelList = AGENT_MODELS.claude.join(", ");
10822
11256
  const extraAgentLines = [
@@ -10824,6 +11258,7 @@ function getDelegationSection(codexAvailable, cursorAvailable, deepseekAvailable
10824
11258
  deepseekAvailable ? `Use provider 'deepseek' for tasks that benefit from the DeepSeek Harness tool loop. Suggested models: ${AGENT_MODELS.deepseek.join(", ")}.` : null,
10825
11259
  fxAvailable ? `Use provider 'fx' for tasks that benefit from fx's minimal native coding loop. Suggested models: ${AGENT_MODELS.fx.join(", ")}.` : null,
10826
11260
  kimiAvailable ? `Use provider 'kimi' for tasks that benefit from Kimi Code's ACP coding loop. Suggested models: ${AGENT_MODELS.kimi.join(", ")}.` : null,
11261
+ museAvailable ? `Use provider 'muse' for tasks that benefit from Muse Code's native coding loop. Suggested models: ${AGENT_MODELS.muse.join(", ")}.` : null,
10827
11262
  opencodeAvailable ? `Use provider 'opencode' for cheaper routine implementation tasks through OpenRouter-backed open source models. Suggested models: ${AGENT_MODELS.opencode.join(", ")}.` : null,
10828
11263
  piAvailable ? `Use provider 'pi' for coding tasks through Pi's OpenRouter-backed coding agent. Suggested models: ${AGENT_MODELS.pi.join(", ")}.` : null,
10829
11264
  cursorAvailable ? `Use provider 'cursor' for fast iteration on code changes. Suggested models: ${AGENT_MODELS.cursor.join(", ")}.` : null
@@ -10948,14 +11383,14 @@ function getEnvironmentSection() {
10948
11383
  ].join("\n");
10949
11384
  }
10950
11385
  function buildRelaySystemPrompt(options) {
10951
- const { customInstructions, codexAvailable, cursorAvailable, deepseekAvailable, fxAvailable, kimiAvailable, opencodeAvailable, piAvailable } = options ?? {};
11386
+ const { customInstructions, codexAvailable, cursorAvailable, deepseekAvailable, fxAvailable, kimiAvailable, museAvailable, opencodeAvailable, piAvailable } = options ?? {};
10952
11387
  const sections = [
10953
11388
  getIntroSection(),
10954
11389
  getSystemSection(),
10955
11390
  getDoingTasksSection(),
10956
11391
  getActionsSection(),
10957
11392
  getUsingToolsSection(),
10958
- getDelegationSection(codexAvailable ?? false, cursorAvailable ?? false, deepseekAvailable ?? false, fxAvailable ?? false, kimiAvailable ?? false, opencodeAvailable ?? false, piAvailable ?? false),
11393
+ getDelegationSection(codexAvailable ?? false, cursorAvailable ?? false, deepseekAvailable ?? false, fxAvailable ?? false, kimiAvailable ?? false, museAvailable ?? false, opencodeAvailable ?? false, piAvailable ?? false),
10959
11394
  getToneAndStyleSection(),
10960
11395
  getOutputEfficiencySection(),
10961
11396
  getEnvironmentSection(),
@@ -10990,9 +11425,10 @@ var RelayManager = class {
10990
11425
  const deepseekAvailable = options.deepseekAvailable ?? false;
10991
11426
  const fxAvailable = options.fxAvailable ?? false;
10992
11427
  const kimiAvailable = options.kimiAvailable ?? false;
11428
+ const museAvailable = options.museAvailable ?? false;
10993
11429
  const opencodeAvailable = options.opencodeAvailable ?? false;
10994
11430
  const piAvailable = options.piAvailable ?? false;
10995
- const availability = { codexAvailable, cursorAvailable, deepseekAvailable, fxAvailable, kimiAvailable, opencodeAvailable, piAvailable };
11431
+ const availability = { codexAvailable, cursorAvailable, deepseekAvailable, fxAvailable, kimiAvailable, museAvailable, opencodeAvailable, piAvailable };
10996
11432
  const getProviderAvailability = options.getProviderAvailability ?? (() => availability);
10997
11433
  this.inner = new ClaudeManager({
10998
11434
  ...options,
@@ -11070,7 +11506,7 @@ async function uploadAnalytics(endpoint, body) {
11070
11506
  // src/analytics/analytics-record-buffer.ts
11071
11507
  import {
11072
11508
  appendFile as appendFile3,
11073
- mkdir as mkdir17,
11509
+ mkdir as mkdir18,
11074
11510
  readFile as readFile16,
11075
11511
  readdir as readdir6,
11076
11512
  rename as rename2,
@@ -11112,7 +11548,7 @@ var AnalyticsRecordBuffer = class {
11112
11548
  if (this.recordIds.has(recordId)) return;
11113
11549
  this.recordIds.add(recordId);
11114
11550
  }
11115
- const pending = mkdir17(ENGINE_DIR2, { recursive: true }).then(() => appendFile3(this.liveFile, `${JSON.stringify(record)}
11551
+ const pending = mkdir18(ENGINE_DIR2, { recursive: true }).then(() => appendFile3(this.liveFile, `${JSON.stringify(record)}
11116
11552
  `, "utf-8")).catch((error) => {
11117
11553
  console.error(
11118
11554
  `[${this.options.storageName}] Append failed, will retry on flush:`,
@@ -11227,7 +11663,7 @@ var AnalyticsRecordBuffer = class {
11227
11663
  };
11228
11664
 
11229
11665
  // src/analytics/agent/activity/skill-mcp-call-extractor.ts
11230
- var NON_MCP_SERVERS = /* @__PURE__ */ new Set(["claude", "cursor", "deepseek", "fx", "kimi", "opencode", "pi", "custom", "dynamic"]);
11666
+ var NON_MCP_SERVERS = /* @__PURE__ */ new Set(["claude", "cursor", "deepseek", "fx", "kimi", "muse", "opencode", "pi", "custom", "dynamic"]);
11231
11667
  function mcpNameFromToolCall(message) {
11232
11668
  const parsedName = parseMcpToolName(message.tool);
11233
11669
  if (parsedName) return parsedName.server;
@@ -11774,6 +12210,28 @@ var DeepseekTokenUsageService = class {
11774
12210
  }
11775
12211
  };
11776
12212
 
12213
+ // src/analytics/token-usage/muse/index.ts
12214
+ var MuseTokenUsageService = class {
12215
+ record(event) {
12216
+ if (event.type !== "usage-updated" || !isRecord(event.payload) || !isRecord(event.payload.usage)) return void 0;
12217
+ const usage = {
12218
+ inputTokens: event.payload.promptTokens,
12219
+ outputTokens: event.payload.usage.outputTokens,
12220
+ cacheReadInputTokens: 0,
12221
+ cacheWriteInputTokens: 0
12222
+ };
12223
+ if (!isTokenUsageCounts(usage)) return void 0;
12224
+ const record = {
12225
+ ...event.context,
12226
+ harness: AGENT.MUSE,
12227
+ model: typeof event.payload.modelId === "string" ? event.payload.modelId : event.context.model,
12228
+ ...usage,
12229
+ occurredAt: event.occurredAt
12230
+ };
12231
+ return { records: [record] };
12232
+ }
12233
+ };
12234
+
11777
12235
  // src/analytics/token-usage/opencode/index.ts
11778
12236
  function parseOpencodeTokenUsage(payload) {
11779
12237
  if (!isRecord(payload) || payload.type !== "step-finish" || !isRecord(payload.tokens) || !isRecord(payload.tokens.cache)) return void 0;
@@ -11840,6 +12298,8 @@ function createAgentTokenUsageService(harness) {
11840
12298
  return new CursorTokenUsageService();
11841
12299
  case AGENT.DEEPSEEK:
11842
12300
  return new DeepseekTokenUsageService();
12301
+ case AGENT.MUSE:
12302
+ return new MuseTokenUsageService();
11843
12303
  case AGENT.OPENCODE:
11844
12304
  return new OpencodeTokenUsageService();
11845
12305
  case AGENT.PI:
@@ -12549,6 +13009,9 @@ function isFxAvailable() {
12549
13009
  function isKimiAvailable() {
12550
13010
  return Boolean(ENGINE_ENV.AI_GATEWAY_API_KEY);
12551
13011
  }
13012
+ function isMuseAvailable() {
13013
+ return existsSync11(MUSE_AUTH_PATH);
13014
+ }
12552
13015
  function isPiAvailable() {
12553
13016
  return existsSync11(PI_AUTH_PATH);
12554
13017
  }
@@ -12689,13 +13152,13 @@ var ChatService = class {
12689
13152
  persistPromise = null;
12690
13153
  persistQueued = false;
12691
13154
  async initialize() {
12692
- await mkdir18(ENGINE_DIR2, { recursive: true });
12693
- await mkdir18(CLAUDE_HISTORY_DIR, { recursive: true });
12694
- await mkdir18(RELAY_HISTORY_DIR, { recursive: true });
12695
- await mkdir18(CODEX_HISTORY_DIR, { recursive: true });
12696
- await mkdir18(CURSOR_HISTORY_DIR, { recursive: true });
12697
- await mkdir18(OPENCODE_HISTORY_DIR, { recursive: true });
12698
- await mkdir18(CHAT_SENDERS_DIR, { recursive: true });
13155
+ await mkdir19(ENGINE_DIR2, { recursive: true });
13156
+ await mkdir19(CLAUDE_HISTORY_DIR, { recursive: true });
13157
+ await mkdir19(RELAY_HISTORY_DIR, { recursive: true });
13158
+ await mkdir19(CODEX_HISTORY_DIR, { recursive: true });
13159
+ await mkdir19(CURSOR_HISTORY_DIR, { recursive: true });
13160
+ await mkdir19(OPENCODE_HISTORY_DIR, { recursive: true });
13161
+ await mkdir19(CHAT_SENDERS_DIR, { recursive: true });
12699
13162
  const persisted = await this.loadChats();
12700
13163
  for (const chat of persisted) {
12701
13164
  const runtime = this.createRuntimeChat(chat);
@@ -13281,7 +13744,8 @@ var ChatService = class {
13281
13744
  cursorAvailable: isCursorAvailable(),
13282
13745
  deepseekAvailable: isDeepseekAvailable(),
13283
13746
  fxAvailable: isFxAvailable(),
13284
- kimiAvailable: isKimiAvailable()
13747
+ kimiAvailable: isKimiAvailable(),
13748
+ museAvailable: isMuseAvailable()
13285
13749
  });
13286
13750
  provider = new RelayManager({
13287
13751
  workingDirectory: this.workingDirectory,
@@ -13342,6 +13806,18 @@ var ChatService = class {
13342
13806
  onProcessingChanged,
13343
13807
  onMessageStarted
13344
13808
  });
13809
+ } else if (persisted.provider === "muse") {
13810
+ provider = new MuseManager({
13811
+ workingDirectory: this.workingDirectory,
13812
+ historyFilePath: join28(MUSE_HISTORY_DIR, `${persisted.id}.jsonl`),
13813
+ initialSessionId: persisted.providerSessionId,
13814
+ onSaveSessionId: saveSession,
13815
+ onTurnComplete: onProviderTurnComplete,
13816
+ onEvent: onProviderEvent,
13817
+ onProcessingChanged,
13818
+ onMessageStarted,
13819
+ onUsageUpdate: onProviderUsage
13820
+ });
13345
13821
  } else if (persisted.provider === "opencode") {
13346
13822
  provider = new OpencodeManager({
13347
13823
  workingDirectory: this.workingDirectory,
@@ -14005,13 +14481,13 @@ import { readdir as readdir11, stat as stat7, readFile as readFile24 } from "fs/
14005
14481
  import { join as join32, resolve as resolve3 } from "path";
14006
14482
 
14007
14483
  // src/services/warm-hooks-service.ts
14008
- import { spawn as spawn6 } from "child_process";
14484
+ import { spawn as spawn7 } from "child_process";
14009
14485
  import { readFile as readFile23 } from "fs/promises";
14010
14486
  import { existsSync as existsSync12 } from "fs";
14011
14487
  import { join as join31 } from "path";
14012
14488
 
14013
14489
  // src/services/warm-hook-logs-service.ts
14014
- import { mkdir as mkdir19, readFile as readFile22, writeFile as writeFile9, readdir as readdir10, appendFile as appendFile5, unlink as unlink4 } from "fs/promises";
14490
+ import { mkdir as mkdir20, readFile as readFile22, writeFile as writeFile9, readdir as readdir10, appendFile as appendFile5, unlink as unlink4 } from "fs/promises";
14015
14491
  import { homedir as homedir13 } from "os";
14016
14492
  import { join as join30 } from "path";
14017
14493
  var LOGS_DIR2 = join30(homedir13(), ".replicas", "warm-hook-logs");
@@ -14023,7 +14499,7 @@ function withPreview2(stored) {
14023
14499
  }
14024
14500
  var WarmHookLogsService = class {
14025
14501
  async ensureDir() {
14026
- await mkdir19(LOGS_DIR2, { recursive: true });
14502
+ await mkdir20(LOGS_DIR2, { recursive: true });
14027
14503
  }
14028
14504
  async saveGlobalHookLog(entry) {
14029
14505
  await this.ensureDir();
@@ -14180,7 +14656,7 @@ async function executeHookScriptStreaming(params) {
14180
14656
  params.onChunk(`$ ${params.label}
14181
14657
  `);
14182
14658
  return new Promise((resolve5) => {
14183
- const proc = spawn6("bash", ["-lc", params.content], {
14659
+ const proc = spawn7("bash", ["-lc", params.content], {
14184
14660
  cwd: params.cwd,
14185
14661
  env: process.env,
14186
14662
  stdio: ["pipe", "pipe", "pipe"]
@@ -14391,7 +14867,7 @@ ${combinedScript}` : combinedScript;
14391
14867
  // src/services/terminal-service.ts
14392
14868
  import { randomUUID as randomUUID10 } from "crypto";
14393
14869
  import { existsSync as existsSync13 } from "fs";
14394
- import { spawn as spawn7 } from "node-pty";
14870
+ import { spawn as spawn8 } from "node-pty";
14395
14871
  var MAX_REPLAY_CHARS = 1024 * 1024;
14396
14872
  var MAX_TERMINAL_SESSIONS = 8;
14397
14873
  var MAX_PENDING_INPUT = 64;
@@ -14410,7 +14886,7 @@ var TerminalService = class {
14410
14886
  }
14411
14887
  const id = randomUUID10();
14412
14888
  const shell = process.env.SHELL && existsSync13(process.env.SHELL) ? process.env.SHELL : "/bin/bash";
14413
- const pty = spawn7(shell, ["-l"], {
14889
+ const pty = spawn8(shell, ["-l"], {
14414
14890
  name: "xterm-256color",
14415
14891
  cols,
14416
14892
  rows,
@@ -15474,17 +15950,17 @@ var HeartbeatService = class _HeartbeatService {
15474
15950
  var heartbeatService = new HeartbeatService();
15475
15951
 
15476
15952
  // src/services/workspace-sdk-service.ts
15477
- import { cp, mkdir as mkdir20 } from "fs/promises";
15478
- import { dirname as dirname11, resolve as resolve4 } from "path";
15953
+ import { cp, mkdir as mkdir21 } from "fs/promises";
15954
+ import { dirname as dirname12, resolve as resolve4 } from "path";
15479
15955
  import { fileURLToPath as fileURLToPath4 } from "url";
15480
15956
  async function installWorkspaceSdk() {
15481
- const source = resolve4(dirname11(fileURLToPath4(import.meta.url)), "../../workspace-sdk");
15957
+ const source = resolve4(dirname12(fileURLToPath4(import.meta.url)), "../../workspace-sdk");
15482
15958
  const targets = [
15483
15959
  resolve4(ENGINE_ENV.HOME_DIR, "node_modules/@replicas/sdk"),
15484
15960
  "/tmp/node_modules/@replicas/sdk"
15485
15961
  ];
15486
15962
  await Promise.all(targets.map(async (target) => {
15487
- await mkdir20(target, { recursive: true });
15963
+ await mkdir21(target, { recursive: true });
15488
15964
  await cp(source, target, { recursive: true, force: true });
15489
15965
  }));
15490
15966
  }