replicas-engine 0.1.235 → 0.1.237
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 +383 -137
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -1779,11 +1779,11 @@ function parseReplicasConfigString(content, filename) {
|
|
|
1779
1779
|
// ../shared/src/claude-auth.ts
|
|
1780
1780
|
function isClaudeAuthErrorText(text) {
|
|
1781
1781
|
const lower = text.toLowerCase();
|
|
1782
|
-
return lower.includes("failed to authenticate") || lower.includes("authentication_error") || lower.includes("authentication_failed") || lower.includes("authentication failed") || lower.includes("invalid authentication credentials") || lower.includes("not logged in") || lower.includes("please run /login") || lower.includes("401") && lower.includes("authentic");
|
|
1782
|
+
return lower.includes("failed to authenticate") || lower.includes("authentication_error") || lower.includes("authentication_failed") || lower.includes("authentication failed") || lower.includes("invalid authentication credentials") || lower.includes("not logged in") || lower.includes("please run /login") || lower.includes("credit balance is too low") || lower.includes("401") && lower.includes("authentic");
|
|
1783
1783
|
}
|
|
1784
1784
|
|
|
1785
1785
|
// ../shared/src/engine/environment.ts
|
|
1786
|
-
var DAYTONA_SNAPSHOT_ID = "29-05-2026-royal-york-
|
|
1786
|
+
var DAYTONA_SNAPSHOT_ID = "29-05-2026-royal-york-v8";
|
|
1787
1787
|
var DESKTOP_NOVNC_PORT = 6080;
|
|
1788
1788
|
|
|
1789
1789
|
// ../shared/src/engine/types.ts
|
|
@@ -1905,6 +1905,53 @@ var AUDIT_LOG_ACTION = {
|
|
|
1905
1905
|
};
|
|
1906
1906
|
var AUDIT_LOG_ACTIONS = Object.values(AUDIT_LOG_ACTION);
|
|
1907
1907
|
|
|
1908
|
+
// ../shared/src/display-message/types.ts
|
|
1909
|
+
var BACKGROUND_TASK_SUBTYPES = /* @__PURE__ */ new Set([
|
|
1910
|
+
"task_started",
|
|
1911
|
+
"task_progress",
|
|
1912
|
+
"task_updated",
|
|
1913
|
+
"task_notification"
|
|
1914
|
+
]);
|
|
1915
|
+
function isBackgroundTaskSubtype(subtype) {
|
|
1916
|
+
return typeof subtype === "string" && BACKGROUND_TASK_SUBTYPES.has(subtype);
|
|
1917
|
+
}
|
|
1918
|
+
function optionalString(value) {
|
|
1919
|
+
return typeof value === "string" ? value : void 0;
|
|
1920
|
+
}
|
|
1921
|
+
function coerceBackgroundTaskPayload(payload) {
|
|
1922
|
+
if (!isRecord(payload)) return null;
|
|
1923
|
+
const subtype = payload.subtype;
|
|
1924
|
+
if (!isBackgroundTaskSubtype(subtype)) return null;
|
|
1925
|
+
const taskId = payload.task_id;
|
|
1926
|
+
if (typeof taskId !== "string" || !taskId) return null;
|
|
1927
|
+
const patch = isRecord(payload.patch) ? {
|
|
1928
|
+
status: optionalString(payload.patch.status),
|
|
1929
|
+
description: optionalString(payload.patch.description),
|
|
1930
|
+
error: optionalString(payload.patch.error)
|
|
1931
|
+
} : void 0;
|
|
1932
|
+
return {
|
|
1933
|
+
subtype,
|
|
1934
|
+
taskId,
|
|
1935
|
+
description: optionalString(payload.description),
|
|
1936
|
+
summary: optionalString(payload.summary),
|
|
1937
|
+
outputFile: optionalString(payload.output_file),
|
|
1938
|
+
status: optionalString(payload.status),
|
|
1939
|
+
patch
|
|
1940
|
+
};
|
|
1941
|
+
}
|
|
1942
|
+
function normalizeBackgroundTaskStatus(status) {
|
|
1943
|
+
if (status === "completed" || status === "failed" || status === "stopped") {
|
|
1944
|
+
return status;
|
|
1945
|
+
}
|
|
1946
|
+
if (status === "killed") {
|
|
1947
|
+
return "stopped";
|
|
1948
|
+
}
|
|
1949
|
+
return "in_progress";
|
|
1950
|
+
}
|
|
1951
|
+
function isTerminalBackgroundTaskStatus(status) {
|
|
1952
|
+
return normalizeBackgroundTaskStatus(status) !== "in_progress";
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1908
1955
|
// ../shared/src/agent-event-utils.ts
|
|
1909
1956
|
function getUserMessage(event) {
|
|
1910
1957
|
return event.type === "event_msg" && event.payload.type === "user_message" && typeof event.payload.message === "string" ? event.payload.message : null;
|
|
@@ -3260,33 +3307,67 @@ var EnvironmentDetailsService = class {
|
|
|
3260
3307
|
var environmentDetailsService = new EnvironmentDetailsService();
|
|
3261
3308
|
|
|
3262
3309
|
// src/services/start-hook-logs-service.ts
|
|
3263
|
-
import { createHash } from "crypto";
|
|
3264
3310
|
import { mkdir as mkdir4, readFile as readFile3, writeFile as writeFile3, readdir as readdir2 } from "fs/promises";
|
|
3265
3311
|
import { homedir as homedir6 } from "os";
|
|
3266
3312
|
import { join as join8 } from "path";
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
return `repo-${
|
|
3313
|
+
|
|
3314
|
+
// src/services/hook-log-files.ts
|
|
3315
|
+
import { createHash } from "crypto";
|
|
3316
|
+
var ENVIRONMENT_HOOK_LOG_FILENAME = "environment.json";
|
|
3317
|
+
function repoHookLogFilename(repoName) {
|
|
3318
|
+
const safe = repoName.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
3319
|
+
const hash = createHash("sha256").update(repoName).digest("hex").slice(0, 8);
|
|
3320
|
+
return `repo-${safe}-${hash}.json`;
|
|
3275
3321
|
}
|
|
3322
|
+
|
|
3323
|
+
// src/services/start-hook-logs-service.ts
|
|
3324
|
+
var LOGS_DIR = join8(homedir6(), ".replicas", "start-hook-logs");
|
|
3276
3325
|
function withPreview(stored) {
|
|
3277
3326
|
const preview = buildHookOutputPreview(stored.output);
|
|
3278
3327
|
return { ...stored, ...preview };
|
|
3279
3328
|
}
|
|
3329
|
+
function isObject(value) {
|
|
3330
|
+
return typeof value === "object" && value !== null;
|
|
3331
|
+
}
|
|
3332
|
+
function optionalString2(value) {
|
|
3333
|
+
return typeof value === "string" ? value : void 0;
|
|
3334
|
+
}
|
|
3335
|
+
function normalizeStored(raw) {
|
|
3336
|
+
if (!isObject(raw)) return null;
|
|
3337
|
+
if (typeof raw.output !== "string" || typeof raw.exitCode !== "number") return null;
|
|
3338
|
+
const hookType = raw.hookType === "environment" ? "environment" : "repository";
|
|
3339
|
+
const repoNameField = optionalString2(raw.repoName);
|
|
3340
|
+
const hookName = optionalString2(raw.hookName) ?? repoNameField ?? "";
|
|
3341
|
+
const repoName = repoNameField ?? hookName;
|
|
3342
|
+
const hookCommands = Array.isArray(raw.hookCommands) ? raw.hookCommands.filter((c) => typeof c === "string") : [];
|
|
3343
|
+
return {
|
|
3344
|
+
hookType,
|
|
3345
|
+
hookName,
|
|
3346
|
+
repoName,
|
|
3347
|
+
hookCommands,
|
|
3348
|
+
output: raw.output,
|
|
3349
|
+
exitCode: raw.exitCode,
|
|
3350
|
+
timedOut: typeof raw.timedOut === "boolean" ? raw.timedOut : false,
|
|
3351
|
+
executedAt: optionalString2(raw.executedAt) ?? ""
|
|
3352
|
+
};
|
|
3353
|
+
}
|
|
3280
3354
|
var StartHookLogsService = class {
|
|
3281
3355
|
async ensureDir() {
|
|
3282
3356
|
await mkdir4(LOGS_DIR, { recursive: true });
|
|
3283
3357
|
}
|
|
3284
|
-
async
|
|
3358
|
+
async saveLog(hookType, hookName, entry) {
|
|
3285
3359
|
await this.ensureDir();
|
|
3286
|
-
const log = { repoName, ...entry };
|
|
3287
|
-
|
|
3360
|
+
const log = { hookType, hookName, repoName: hookName, ...entry };
|
|
3361
|
+
const filename = hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
3362
|
+
await writeFile3(join8(LOGS_DIR, filename), `${JSON.stringify(log, null, 2)}
|
|
3288
3363
|
`, "utf-8");
|
|
3289
3364
|
}
|
|
3365
|
+
async saveEnvironmentLog(entry) {
|
|
3366
|
+
await this.saveLog("environment", "environment", entry);
|
|
3367
|
+
}
|
|
3368
|
+
async saveRepoLog(repoName, entry) {
|
|
3369
|
+
await this.saveLog("repository", repoName, entry);
|
|
3370
|
+
}
|
|
3290
3371
|
async getAllLogs() {
|
|
3291
3372
|
let files;
|
|
3292
3373
|
try {
|
|
@@ -3304,19 +3385,27 @@ var StartHookLogsService = class {
|
|
|
3304
3385
|
}
|
|
3305
3386
|
try {
|
|
3306
3387
|
const raw = await readFile3(join8(LOGS_DIR, file), "utf-8");
|
|
3307
|
-
const stored = JSON.parse(raw);
|
|
3308
|
-
|
|
3388
|
+
const stored = normalizeStored(JSON.parse(raw));
|
|
3389
|
+
if (stored) {
|
|
3390
|
+
logs.push(withPreview(stored));
|
|
3391
|
+
}
|
|
3309
3392
|
} catch {
|
|
3310
3393
|
}
|
|
3311
3394
|
}
|
|
3312
|
-
logs.sort((a, b) =>
|
|
3395
|
+
logs.sort((a, b) => {
|
|
3396
|
+
if (a.hookType !== b.hookType) {
|
|
3397
|
+
return a.hookType === "environment" ? -1 : 1;
|
|
3398
|
+
}
|
|
3399
|
+
return a.hookName.localeCompare(b.hookName);
|
|
3400
|
+
});
|
|
3313
3401
|
return logs;
|
|
3314
3402
|
}
|
|
3315
|
-
async getFullOutput(
|
|
3403
|
+
async getFullOutput(hookType, hookName) {
|
|
3404
|
+
const filename = hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
3316
3405
|
try {
|
|
3317
|
-
const raw = await readFile3(join8(LOGS_DIR,
|
|
3318
|
-
const stored = JSON.parse(raw);
|
|
3319
|
-
if (stored.
|
|
3406
|
+
const raw = await readFile3(join8(LOGS_DIR, filename), "utf-8");
|
|
3407
|
+
const stored = normalizeStored(JSON.parse(raw));
|
|
3408
|
+
if (!stored || stored.hookType !== hookType || stored.hookName !== hookName) {
|
|
3320
3409
|
return null;
|
|
3321
3410
|
}
|
|
3322
3411
|
return stored.output;
|
|
@@ -3565,6 +3654,13 @@ Repositories: ${hookEntries.length}
|
|
|
3565
3654
|
onOutputChunk: (chunk) => onEvent({ type: "output", data: chunk, label: "environment" })
|
|
3566
3655
|
});
|
|
3567
3656
|
recordResult(envResult);
|
|
3657
|
+
await startHookLogsService.saveEnvironmentLog({
|
|
3658
|
+
hookCommands: [envHookContent],
|
|
3659
|
+
output: envResult.output.join(""),
|
|
3660
|
+
exitCode: envResult.exitCode,
|
|
3661
|
+
timedOut: envResult.timedOut,
|
|
3662
|
+
executedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3663
|
+
});
|
|
3568
3664
|
} else {
|
|
3569
3665
|
await environmentDetailsService.setEnvironmentStartHook("n/a");
|
|
3570
3666
|
}
|
|
@@ -5095,7 +5191,14 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5095
5191
|
sessionId = null;
|
|
5096
5192
|
activeQuery = null;
|
|
5097
5193
|
activePromptStream = null;
|
|
5194
|
+
activeSessionSignature = null;
|
|
5195
|
+
activeSessionModel = null;
|
|
5196
|
+
activeSessionPermissionMode = null;
|
|
5197
|
+
sessionLoop = null;
|
|
5198
|
+
sessionLinearForwarder = null;
|
|
5199
|
+
pendingTurn = null;
|
|
5098
5200
|
pendingInterrupt = false;
|
|
5201
|
+
activeBackgroundTasks = /* @__PURE__ */ new Set();
|
|
5099
5202
|
systemPromptOverride;
|
|
5100
5203
|
toolsOverride;
|
|
5101
5204
|
mcpServersConfig;
|
|
@@ -5116,7 +5219,6 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5116
5219
|
}
|
|
5117
5220
|
async interruptActiveTurn() {
|
|
5118
5221
|
this.pendingInterrupt = true;
|
|
5119
|
-
this.activePromptStream?.close();
|
|
5120
5222
|
if (this.activeQuery) {
|
|
5121
5223
|
await this.activeQuery.interrupt();
|
|
5122
5224
|
}
|
|
@@ -5298,117 +5400,271 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5298
5400
|
thinkingLevel,
|
|
5299
5401
|
enableInteractiveTools
|
|
5300
5402
|
} = request;
|
|
5301
|
-
const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
|
|
5302
5403
|
if (!message || !message.trim()) {
|
|
5303
5404
|
throw new Error("Message cannot be empty");
|
|
5304
5405
|
}
|
|
5305
5406
|
await this.initialized;
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5407
|
+
this.pendingInterrupt = false;
|
|
5408
|
+
const content = [
|
|
5409
|
+
{
|
|
5410
|
+
type: "text",
|
|
5411
|
+
text: message
|
|
5412
|
+
}
|
|
5413
|
+
];
|
|
5414
|
+
if (images && images.length > 0) {
|
|
5415
|
+
const normalizedImages = await normalizeImages(images);
|
|
5416
|
+
for (const image of normalizedImages) {
|
|
5417
|
+
content.push({
|
|
5418
|
+
type: "image",
|
|
5419
|
+
source: {
|
|
5420
|
+
type: "base64",
|
|
5421
|
+
media_type: image.source.media_type,
|
|
5422
|
+
data: image.source.data
|
|
5423
|
+
}
|
|
5424
|
+
});
|
|
5425
|
+
}
|
|
5426
|
+
}
|
|
5427
|
+
const userMessage = {
|
|
5428
|
+
type: "user",
|
|
5429
|
+
message: {
|
|
5430
|
+
role: "user",
|
|
5431
|
+
content
|
|
5432
|
+
},
|
|
5433
|
+
parent_tool_use_id: null,
|
|
5434
|
+
session_id: this.sessionId ?? ""
|
|
5435
|
+
};
|
|
5436
|
+
if (!options.skipUserMessageRecord) {
|
|
5437
|
+
await this.recordEvent(userMessage);
|
|
5438
|
+
}
|
|
5439
|
+
const combinedInstructions = this.buildCombinedInstructions(customInstructions);
|
|
5440
|
+
const resolvedModel = normalizeClaudeModel(model) || CLAUDE_OPUS_1M_MODEL;
|
|
5441
|
+
const resolvedPermissionMode = permissionMode === "read" ? "plan" : "bypassPermissions";
|
|
5442
|
+
const signature = {
|
|
5443
|
+
combinedInstructions,
|
|
5444
|
+
thinkingLevel,
|
|
5445
|
+
// enableInteractiveTools only matters when permissionMode is 'read'; the
|
|
5446
|
+
// session signature tracks the effective flag so a permissionMode change
|
|
5447
|
+
// can hot-swap via setPermissionMode without restarting.
|
|
5448
|
+
enableInteractiveTools: Boolean(enableInteractiveTools)
|
|
5449
|
+
};
|
|
5450
|
+
await this.ensureSession({
|
|
5451
|
+
signature,
|
|
5452
|
+
combinedInstructions,
|
|
5453
|
+
resolvedModel,
|
|
5454
|
+
resolvedPermissionMode,
|
|
5455
|
+
enableInteractiveTools: signature.enableInteractiveTools,
|
|
5456
|
+
thinkingLevel
|
|
5457
|
+
});
|
|
5458
|
+
const promptStream = this.activePromptStream;
|
|
5459
|
+
const activeQuery = this.activeQuery;
|
|
5460
|
+
if (!promptStream || !activeQuery) {
|
|
5461
|
+
throw new Error("Claude session unavailable after ensureSession");
|
|
5462
|
+
}
|
|
5463
|
+
if (this.pendingInterrupt) {
|
|
5464
|
+
this.pendingInterrupt = false;
|
|
5465
|
+
return;
|
|
5466
|
+
}
|
|
5467
|
+
await new Promise((resolve3, reject) => {
|
|
5468
|
+
this.pendingTurn = { resolve: resolve3, reject };
|
|
5469
|
+
promptStream.push(userMessage);
|
|
5470
|
+
});
|
|
5471
|
+
}
|
|
5472
|
+
async ensureSession(args) {
|
|
5473
|
+
const {
|
|
5474
|
+
signature,
|
|
5475
|
+
combinedInstructions,
|
|
5476
|
+
resolvedModel,
|
|
5477
|
+
resolvedPermissionMode,
|
|
5478
|
+
enableInteractiveTools,
|
|
5479
|
+
thinkingLevel
|
|
5480
|
+
} = args;
|
|
5481
|
+
if (this.activeQuery && this.activeSessionSignature && this.sessionSignaturesMatch(this.activeSessionSignature, signature)) {
|
|
5482
|
+
if (this.activeSessionModel !== resolvedModel) {
|
|
5483
|
+
try {
|
|
5484
|
+
await this.activeQuery.setModel(resolvedModel);
|
|
5485
|
+
this.activeSessionModel = resolvedModel;
|
|
5486
|
+
} catch (err) {
|
|
5487
|
+
console.warn("[ClaudeManager] setModel failed; recreating session:", err);
|
|
5488
|
+
await this.tearDownSession();
|
|
5311
5489
|
}
|
|
5312
|
-
|
|
5313
|
-
if (
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
media_type: image.source.media_type,
|
|
5321
|
-
data: image.source.data
|
|
5322
|
-
}
|
|
5323
|
-
});
|
|
5490
|
+
}
|
|
5491
|
+
if (this.activeQuery && this.activeSessionPermissionMode !== resolvedPermissionMode) {
|
|
5492
|
+
try {
|
|
5493
|
+
await this.activeQuery.setPermissionMode(resolvedPermissionMode);
|
|
5494
|
+
this.activeSessionPermissionMode = resolvedPermissionMode;
|
|
5495
|
+
} catch (err) {
|
|
5496
|
+
console.warn("[ClaudeManager] setPermissionMode failed; recreating session:", err);
|
|
5497
|
+
await this.tearDownSession();
|
|
5324
5498
|
}
|
|
5325
5499
|
}
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5500
|
+
if (this.activeQuery) return;
|
|
5501
|
+
} else if (this.activeQuery) {
|
|
5502
|
+
await this.tearDownSession();
|
|
5503
|
+
}
|
|
5504
|
+
await this.startSession({
|
|
5505
|
+
combinedInstructions,
|
|
5506
|
+
resolvedModel,
|
|
5507
|
+
resolvedPermissionMode,
|
|
5508
|
+
enableInteractiveTools,
|
|
5509
|
+
thinkingLevel,
|
|
5510
|
+
signature
|
|
5511
|
+
});
|
|
5512
|
+
}
|
|
5513
|
+
sessionSignaturesMatch(a, b) {
|
|
5514
|
+
return a.combinedInstructions === b.combinedInstructions && a.thinkingLevel === b.thinkingLevel && a.enableInteractiveTools === b.enableInteractiveTools;
|
|
5515
|
+
}
|
|
5516
|
+
async startSession(args) {
|
|
5517
|
+
const {
|
|
5518
|
+
combinedInstructions,
|
|
5519
|
+
resolvedModel,
|
|
5520
|
+
resolvedPermissionMode,
|
|
5521
|
+
enableInteractiveTools,
|
|
5522
|
+
thinkingLevel,
|
|
5523
|
+
signature
|
|
5524
|
+
} = args;
|
|
5525
|
+
const systemPrompt = this.systemPromptOverride ? this.systemPromptOverride(combinedInstructions) : {
|
|
5526
|
+
type: "preset",
|
|
5527
|
+
preset: "claude_code",
|
|
5528
|
+
append: combinedInstructions
|
|
5529
|
+
};
|
|
5530
|
+
const queryEnv = buildClaudeAgentEnv(this.envOverrides);
|
|
5531
|
+
const additionalDirectories = await getAgentAdditionalDirectories();
|
|
5532
|
+
const interactiveAllowed = enableInteractiveTools && resolvedPermissionMode === "plan";
|
|
5533
|
+
const useDefaultToolPolicy = !this.toolsOverride;
|
|
5534
|
+
const allowedTools = useDefaultToolPolicy ? [
|
|
5535
|
+
...ALWAYS_ALLOWED_TOOLS,
|
|
5536
|
+
...interactiveAllowed ? INTERACTIVE_TOOL_NAMES : []
|
|
5537
|
+
] : void 0;
|
|
5538
|
+
const disallowedTools = [
|
|
5539
|
+
...this.disallowedToolsOverride ?? [],
|
|
5540
|
+
...useDefaultToolPolicy ? ALWAYS_DISALLOWED_TOOLS : [],
|
|
5541
|
+
...interactiveAllowed ? [] : INTERACTIVE_TOOL_NAMES
|
|
5542
|
+
];
|
|
5543
|
+
const promptStream = new PromptStream();
|
|
5544
|
+
const response = query({
|
|
5545
|
+
prompt: promptStream,
|
|
5546
|
+
options: {
|
|
5547
|
+
resume: this.sessionId || void 0,
|
|
5548
|
+
cwd: this.workingDirectory,
|
|
5549
|
+
additionalDirectories,
|
|
5550
|
+
permissionMode: resolvedPermissionMode,
|
|
5551
|
+
allowDangerouslySkipPermissions: resolvedPermissionMode === "bypassPermissions",
|
|
5552
|
+
...this.toolsOverride ? { tools: this.toolsOverride } : {},
|
|
5553
|
+
...allowedTools ? { allowedTools } : {},
|
|
5554
|
+
...disallowedTools.length > 0 ? { disallowedTools } : {},
|
|
5555
|
+
settingSources: ["user", "project", "local"],
|
|
5556
|
+
systemPrompt,
|
|
5557
|
+
...this.mcpServersConfig ? { mcpServers: this.mcpServersConfig } : {},
|
|
5558
|
+
env: queryEnv,
|
|
5559
|
+
model: resolvedModel,
|
|
5560
|
+
...thinkingLevel ? { effort: thinkingLevel } : {},
|
|
5561
|
+
canUseTool: this.buildCanUseTool()
|
|
5337
5562
|
}
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
...useDefaultToolPolicy ? ALWAYS_DISALLOWED_TOOLS : [],
|
|
5359
|
-
...interactiveAllowed ? [] : INTERACTIVE_TOOL_NAMES
|
|
5360
|
-
];
|
|
5361
|
-
const response = query({
|
|
5362
|
-
prompt: promptStream,
|
|
5363
|
-
options: {
|
|
5364
|
-
resume: this.sessionId || void 0,
|
|
5365
|
-
cwd: this.workingDirectory,
|
|
5366
|
-
additionalDirectories,
|
|
5367
|
-
permissionMode: permissionMode === "read" ? "plan" : "bypassPermissions",
|
|
5368
|
-
allowDangerouslySkipPermissions: permissionMode !== "read",
|
|
5369
|
-
...this.toolsOverride ? { tools: this.toolsOverride } : {},
|
|
5370
|
-
...allowedTools ? { allowedTools } : {},
|
|
5371
|
-
...disallowedTools.length > 0 ? { disallowedTools } : {},
|
|
5372
|
-
settingSources: ["user", "project", "local"],
|
|
5373
|
-
systemPrompt,
|
|
5374
|
-
...this.mcpServersConfig ? { mcpServers: this.mcpServersConfig } : {},
|
|
5375
|
-
env: queryEnv,
|
|
5376
|
-
model: resolvedModel,
|
|
5377
|
-
...thinkingLevel ? { effort: thinkingLevel } : {},
|
|
5378
|
-
canUseTool: this.buildCanUseTool()
|
|
5379
|
-
}
|
|
5380
|
-
});
|
|
5381
|
-
this.activeQuery = response;
|
|
5382
|
-
if (this.pendingInterrupt) {
|
|
5383
|
-
this.pendingInterrupt = false;
|
|
5384
|
-
this.activePromptStream?.close();
|
|
5385
|
-
await this.activeQuery.interrupt();
|
|
5386
|
-
}
|
|
5387
|
-
const linearForwarder = new LinearEventForwarder(linearSessionId);
|
|
5388
|
-
for await (const msg of response) {
|
|
5563
|
+
});
|
|
5564
|
+
this.activeQuery = response;
|
|
5565
|
+
this.activePromptStream = promptStream;
|
|
5566
|
+
this.activeSessionSignature = signature;
|
|
5567
|
+
this.activeSessionModel = resolvedModel;
|
|
5568
|
+
this.activeSessionPermissionMode = resolvedPermissionMode;
|
|
5569
|
+
this.sessionLinearForwarder = new LinearEventForwarder(ENGINE_ENV.LINEAR_SESSION_ID);
|
|
5570
|
+
this.activeBackgroundTasks.clear();
|
|
5571
|
+
this.sessionLoop = this.runSessionLoop(response).catch((err) => {
|
|
5572
|
+
console.error("[ClaudeManager] Session loop crashed:", err);
|
|
5573
|
+
});
|
|
5574
|
+
}
|
|
5575
|
+
async runSessionLoop(response) {
|
|
5576
|
+
const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
|
|
5577
|
+
const iterator = response[Symbol.asyncIterator]();
|
|
5578
|
+
try {
|
|
5579
|
+
while (true) {
|
|
5580
|
+
const next = await iterator.next();
|
|
5581
|
+
if (next.done) break;
|
|
5582
|
+
const msg = next.value;
|
|
5389
5583
|
const authErrorMessage = _ClaudeManager.detectAuthErrorInMessage(msg);
|
|
5390
5584
|
if (authErrorMessage) {
|
|
5391
|
-
this.
|
|
5392
|
-
|
|
5585
|
+
this.failPendingTurn(new ClaudeAuthError(authErrorMessage));
|
|
5586
|
+
try {
|
|
5587
|
+
response.close();
|
|
5588
|
+
} catch (err) {
|
|
5589
|
+
console.warn("[ClaudeManager] query.close() during auth error failed:", err);
|
|
5590
|
+
}
|
|
5591
|
+
return;
|
|
5393
5592
|
}
|
|
5394
5593
|
this.setAuthRetrying(false);
|
|
5395
5594
|
await this.handleMessage(msg);
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5595
|
+
_ClaudeManager.updateBackgroundTaskState(msg, this.activeBackgroundTasks);
|
|
5596
|
+
if (linearSessionId && this.sessionLinearForwarder) {
|
|
5597
|
+
this.sessionLinearForwarder.sendPlan(extractPlanFromClaudeEvent(msg));
|
|
5598
|
+
this.sessionLinearForwarder.sendEvent(convertClaudeEvent(msg, linearSessionId));
|
|
5399
5599
|
}
|
|
5400
5600
|
if (msg.type === "result") {
|
|
5401
5601
|
await this.recordContextUsage(response);
|
|
5402
|
-
this.
|
|
5403
|
-
|
|
5602
|
+
this.sessionLinearForwarder?.flushThoughtAsResponse();
|
|
5603
|
+
this.resolvePendingTurn();
|
|
5404
5604
|
}
|
|
5405
5605
|
}
|
|
5406
|
-
linearForwarder.flushThoughtAsResponse();
|
|
5407
5606
|
} finally {
|
|
5408
|
-
this.
|
|
5409
|
-
this.
|
|
5410
|
-
this.
|
|
5411
|
-
|
|
5607
|
+
this.sessionLinearForwarder?.flushThoughtAsResponse();
|
|
5608
|
+
this.failPendingTurn(new Error("Claude session ended unexpectedly"));
|
|
5609
|
+
if (this.activeQuery === response) {
|
|
5610
|
+
this.clearSessionState();
|
|
5611
|
+
}
|
|
5612
|
+
}
|
|
5613
|
+
}
|
|
5614
|
+
clearSessionState() {
|
|
5615
|
+
this.activeQuery = null;
|
|
5616
|
+
this.activePromptStream = null;
|
|
5617
|
+
this.activeSessionSignature = null;
|
|
5618
|
+
this.activeSessionModel = null;
|
|
5619
|
+
this.activeSessionPermissionMode = null;
|
|
5620
|
+
this.sessionLinearForwarder = null;
|
|
5621
|
+
this.sessionLoop = null;
|
|
5622
|
+
this.activeBackgroundTasks.clear();
|
|
5623
|
+
}
|
|
5624
|
+
resolvePendingTurn() {
|
|
5625
|
+
const pending = this.pendingTurn;
|
|
5626
|
+
if (!pending) return;
|
|
5627
|
+
this.pendingTurn = null;
|
|
5628
|
+
this.pendingInterrupt = false;
|
|
5629
|
+
pending.resolve();
|
|
5630
|
+
}
|
|
5631
|
+
failPendingTurn(err) {
|
|
5632
|
+
const pending = this.pendingTurn;
|
|
5633
|
+
if (!pending) return;
|
|
5634
|
+
this.pendingTurn = null;
|
|
5635
|
+
this.pendingInterrupt = false;
|
|
5636
|
+
pending.reject(err);
|
|
5637
|
+
}
|
|
5638
|
+
async tearDownSession() {
|
|
5639
|
+
const query2 = this.activeQuery;
|
|
5640
|
+
const stream = this.activePromptStream;
|
|
5641
|
+
const loop = this.sessionLoop;
|
|
5642
|
+
this.failPendingTurn(new Error("Claude session torn down"));
|
|
5643
|
+
this.clearSessionState();
|
|
5644
|
+
if (query2) {
|
|
5645
|
+
try {
|
|
5646
|
+
query2.close();
|
|
5647
|
+
} catch (err) {
|
|
5648
|
+
console.warn("[ClaudeManager] query.close() failed:", err);
|
|
5649
|
+
}
|
|
5650
|
+
}
|
|
5651
|
+
stream?.close();
|
|
5652
|
+
if (loop) {
|
|
5653
|
+
try {
|
|
5654
|
+
await loop;
|
|
5655
|
+
} catch {
|
|
5656
|
+
}
|
|
5657
|
+
}
|
|
5658
|
+
}
|
|
5659
|
+
static updateBackgroundTaskState(message, activeTasks) {
|
|
5660
|
+
if (message.type !== "system") return;
|
|
5661
|
+
const payload = coerceBackgroundTaskPayload(message);
|
|
5662
|
+
if (!payload) return;
|
|
5663
|
+
const status = payload.subtype === "task_updated" ? payload.patch?.status : payload.status;
|
|
5664
|
+
if (isTerminalBackgroundTaskStatus(status)) {
|
|
5665
|
+
activeTasks.delete(payload.taskId);
|
|
5666
|
+
} else {
|
|
5667
|
+
activeTasks.add(payload.taskId);
|
|
5412
5668
|
}
|
|
5413
5669
|
}
|
|
5414
5670
|
getContextUsageProvider() {
|
|
@@ -5726,7 +5982,7 @@ var AspClient = class {
|
|
|
5726
5982
|
// src/managers/codex-asp/app-server-process.ts
|
|
5727
5983
|
var DEFAULT_CODEX_BINARY = "codex";
|
|
5728
5984
|
var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
5729
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
5985
|
+
var ENGINE_PACKAGE_VERSION = "0.1.237";
|
|
5730
5986
|
var INITIALIZE_METHOD = "initialize";
|
|
5731
5987
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
5732
5988
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -9224,26 +9480,12 @@ import { existsSync as existsSync8 } from "fs";
|
|
|
9224
9480
|
import { join as join19 } from "path";
|
|
9225
9481
|
|
|
9226
9482
|
// src/services/warm-hook-logs-service.ts
|
|
9227
|
-
import { createHash as createHash2 } from "crypto";
|
|
9228
9483
|
import { mkdir as mkdir12, readFile as readFile11, writeFile as writeFile7, readdir as readdir5, appendFile as appendFile6, unlink as unlink3 } from "fs/promises";
|
|
9229
9484
|
import { homedir as homedir15 } from "os";
|
|
9230
9485
|
import { join as join18 } from "path";
|
|
9231
9486
|
var LOGS_DIR2 = join18(homedir15(), ".replicas", "warm-hook-logs");
|
|
9232
9487
|
var CURRENT_RUN_LOG = join18(LOGS_DIR2, "current-run.log");
|
|
9233
|
-
|
|
9234
|
-
const safe = name.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
9235
|
-
const hash = createHash2("sha256").update(name).digest("hex").slice(0, 8);
|
|
9236
|
-
return `${safe}-${hash}`;
|
|
9237
|
-
}
|
|
9238
|
-
function globalFilename() {
|
|
9239
|
-
return "global.json";
|
|
9240
|
-
}
|
|
9241
|
-
function environmentFilename() {
|
|
9242
|
-
return "environment.json";
|
|
9243
|
-
}
|
|
9244
|
-
function repoFilename2(repoName) {
|
|
9245
|
-
return `repo-${sanitizeFilename2(repoName)}.json`;
|
|
9246
|
-
}
|
|
9488
|
+
var GLOBAL_FILENAME = "global.json";
|
|
9247
9489
|
function withPreview2(stored) {
|
|
9248
9490
|
const preview = buildHookOutputPreview(stored.output);
|
|
9249
9491
|
return { ...stored, ...preview };
|
|
@@ -9259,7 +9501,7 @@ var WarmHookLogsService = class {
|
|
|
9259
9501
|
hookName: "organization",
|
|
9260
9502
|
...entry
|
|
9261
9503
|
};
|
|
9262
|
-
await writeFile7(join18(LOGS_DIR2,
|
|
9504
|
+
await writeFile7(join18(LOGS_DIR2, GLOBAL_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
9263
9505
|
`, "utf-8");
|
|
9264
9506
|
}
|
|
9265
9507
|
async saveEnvironmentHookLog(entry) {
|
|
@@ -9269,7 +9511,7 @@ var WarmHookLogsService = class {
|
|
|
9269
9511
|
hookName: "environment",
|
|
9270
9512
|
...entry
|
|
9271
9513
|
};
|
|
9272
|
-
await writeFile7(join18(LOGS_DIR2,
|
|
9514
|
+
await writeFile7(join18(LOGS_DIR2, ENVIRONMENT_HOOK_LOG_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
9273
9515
|
`, "utf-8");
|
|
9274
9516
|
}
|
|
9275
9517
|
async saveRepoHookLog(repoName, entry) {
|
|
@@ -9279,7 +9521,7 @@ var WarmHookLogsService = class {
|
|
|
9279
9521
|
hookName: repoName,
|
|
9280
9522
|
...entry
|
|
9281
9523
|
};
|
|
9282
|
-
await writeFile7(join18(LOGS_DIR2,
|
|
9524
|
+
await writeFile7(join18(LOGS_DIR2, repoHookLogFilename(repoName)), `${JSON.stringify(log, null, 2)}
|
|
9283
9525
|
`, "utf-8");
|
|
9284
9526
|
}
|
|
9285
9527
|
async getAllLogs() {
|
|
@@ -9334,7 +9576,7 @@ var WarmHookLogsService = class {
|
|
|
9334
9576
|
}
|
|
9335
9577
|
}
|
|
9336
9578
|
async getFullOutput(hookType, hookName) {
|
|
9337
|
-
const filename = hookType === "global" ?
|
|
9579
|
+
const filename = hookType === "global" ? GLOBAL_FILENAME : hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
9338
9580
|
try {
|
|
9339
9581
|
const raw = await readFile11(join18(LOGS_DIR2, filename), "utf-8");
|
|
9340
9582
|
const stored = JSON.parse(raw);
|
|
@@ -10172,10 +10414,14 @@ function createV1Routes(deps) {
|
|
|
10172
10414
|
);
|
|
10173
10415
|
}
|
|
10174
10416
|
});
|
|
10175
|
-
app2.get("/start-hooks/logs/:
|
|
10417
|
+
app2.get("/start-hooks/logs/:hookType/:hookName/full", async (c) => {
|
|
10176
10418
|
try {
|
|
10177
|
-
const
|
|
10178
|
-
const
|
|
10419
|
+
const hookType = c.req.param("hookType");
|
|
10420
|
+
const hookName = c.req.param("hookName");
|
|
10421
|
+
if (hookType !== "environment" && hookType !== "repository") {
|
|
10422
|
+
return c.json(jsonError("Invalid hookType", 'Must be "environment" or "repository"'), 400);
|
|
10423
|
+
}
|
|
10424
|
+
const output = await startHookLogsService.getFullOutput(hookType, hookName);
|
|
10179
10425
|
if (output === null) {
|
|
10180
10426
|
return c.json(jsonError("Start hook log not found"), 404);
|
|
10181
10427
|
}
|