replicas-engine 0.1.236 → 0.1.238
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 +467 -149
- 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-v9";
|
|
1787
1787
|
var DESKTOP_NOVNC_PORT = 6080;
|
|
1788
1788
|
|
|
1789
1789
|
// ../shared/src/engine/types.ts
|
|
@@ -1802,9 +1802,9 @@ function normalizeClaudeModel(model) {
|
|
|
1802
1802
|
}
|
|
1803
1803
|
var MODEL_LABELS = {
|
|
1804
1804
|
sonnet: "Sonnet 4.5",
|
|
1805
|
-
opus: "Opus 4.
|
|
1806
|
-
[CLAUDE_OPUS_1M_MODEL]: "Opus 4.
|
|
1807
|
-
[LEGACY_CLAUDE_OPUS_1M_MODEL]: "Opus 4.
|
|
1805
|
+
opus: "Opus 4.8",
|
|
1806
|
+
[CLAUDE_OPUS_1M_MODEL]: "Opus 4.8 (1M)",
|
|
1807
|
+
[LEGACY_CLAUDE_OPUS_1M_MODEL]: "Opus 4.8 (1M)",
|
|
1808
1808
|
haiku: "Haiku 4.5",
|
|
1809
1809
|
"gpt-5.5": "GPT-5.5",
|
|
1810
1810
|
"gpt-5.4": "GPT-5.4",
|
|
@@ -1905,6 +1905,174 @@ 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
|
+
|
|
1955
|
+
// ../shared/src/display-message/task-accumulator.ts
|
|
1956
|
+
function mapTaskStatus(status) {
|
|
1957
|
+
if (status === "in_progress" || status === "completed") return status;
|
|
1958
|
+
return "pending";
|
|
1959
|
+
}
|
|
1960
|
+
function toAccumulatorInput(input) {
|
|
1961
|
+
if (typeof input === "string") {
|
|
1962
|
+
try {
|
|
1963
|
+
const parsed = JSON.parse(input);
|
|
1964
|
+
return isRecord(parsed) ? parsed : {};
|
|
1965
|
+
} catch {
|
|
1966
|
+
return {};
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
return isRecord(input) ? input : {};
|
|
1970
|
+
}
|
|
1971
|
+
function extractToolResultText(content, separator = "\n") {
|
|
1972
|
+
if (typeof content === "string") return content;
|
|
1973
|
+
if (!Array.isArray(content)) return "";
|
|
1974
|
+
const texts = [];
|
|
1975
|
+
for (const part of content) {
|
|
1976
|
+
if (isRecord(part) && part.type === "text" && typeof part.text === "string") {
|
|
1977
|
+
texts.push(part.text);
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
return texts.join(separator);
|
|
1981
|
+
}
|
|
1982
|
+
function parseStringField(value) {
|
|
1983
|
+
if (typeof value !== "string") return null;
|
|
1984
|
+
const trimmed = value.trim();
|
|
1985
|
+
return trimmed ? trimmed : null;
|
|
1986
|
+
}
|
|
1987
|
+
function parseCreateResultTaskId(resultText) {
|
|
1988
|
+
try {
|
|
1989
|
+
const parsed = JSON.parse(resultText);
|
|
1990
|
+
if (isRecord(parsed) && isRecord(parsed.task)) {
|
|
1991
|
+
return parseStringField(parsed.task.id);
|
|
1992
|
+
}
|
|
1993
|
+
} catch {
|
|
1994
|
+
}
|
|
1995
|
+
return resultText.match(/\bTask\s+#?([A-Za-z0-9_-]+)\s+created\b/i)?.[1] ?? null;
|
|
1996
|
+
}
|
|
1997
|
+
var TaskAccumulator = class {
|
|
1998
|
+
tasksByTaskId = /* @__PURE__ */ new Map();
|
|
1999
|
+
tasksByCreateToolUseId = /* @__PURE__ */ new Map();
|
|
2000
|
+
orderedKeys = [];
|
|
2001
|
+
processToolUse(toolName, toolUseId, input) {
|
|
2002
|
+
if (toolName === "TaskCreate") {
|
|
2003
|
+
const subject = parseStringField(input.subject);
|
|
2004
|
+
if (!subject) return false;
|
|
2005
|
+
this.tasksByCreateToolUseId.set(toolUseId, { subject, status: "pending" });
|
|
2006
|
+
this.orderedKeys.push(toolUseId);
|
|
2007
|
+
return true;
|
|
2008
|
+
}
|
|
2009
|
+
if (toolName === "TaskUpdate") {
|
|
2010
|
+
const taskId = parseStringField(input.taskId);
|
|
2011
|
+
if (!taskId) return false;
|
|
2012
|
+
if (input.status === "deleted") {
|
|
2013
|
+
if (!this.tasksByTaskId.delete(taskId)) return false;
|
|
2014
|
+
const idx = this.orderedKeys.indexOf(taskId);
|
|
2015
|
+
if (idx !== -1) this.orderedKeys.splice(idx, 1);
|
|
2016
|
+
return true;
|
|
2017
|
+
}
|
|
2018
|
+
const existing = this.tasksByTaskId.get(taskId);
|
|
2019
|
+
const subject = parseStringField(input.subject) ?? existing?.subject;
|
|
2020
|
+
if (!subject) return false;
|
|
2021
|
+
const status = input.status !== void 0 ? mapTaskStatus(input.status) : existing?.status ?? "pending";
|
|
2022
|
+
this.tasksByTaskId.set(taskId, { subject, status });
|
|
2023
|
+
if (!existing) this.orderedKeys.push(taskId);
|
|
2024
|
+
return true;
|
|
2025
|
+
}
|
|
2026
|
+
if (toolName === "TaskList") {
|
|
2027
|
+
if (!Array.isArray(input.tasks)) return false;
|
|
2028
|
+
let changed = false;
|
|
2029
|
+
for (const raw of input.tasks) {
|
|
2030
|
+
if (!isRecord(raw)) continue;
|
|
2031
|
+
const id = parseStringField(raw.id);
|
|
2032
|
+
const subject = parseStringField(raw.subject);
|
|
2033
|
+
if (!id || !subject) continue;
|
|
2034
|
+
const existing = this.tasksByTaskId.get(id);
|
|
2035
|
+
const next = { subject, status: mapTaskStatus(raw.status) };
|
|
2036
|
+
if (existing && existing.subject === next.subject && existing.status === next.status) continue;
|
|
2037
|
+
this.tasksByTaskId.set(id, next);
|
|
2038
|
+
if (!existing) this.orderedKeys.push(id);
|
|
2039
|
+
changed = true;
|
|
2040
|
+
}
|
|
2041
|
+
return changed;
|
|
2042
|
+
}
|
|
2043
|
+
return false;
|
|
2044
|
+
}
|
|
2045
|
+
processCreateResult(toolUseId, resultText) {
|
|
2046
|
+
const pending = this.tasksByCreateToolUseId.get(toolUseId);
|
|
2047
|
+
if (!pending) return false;
|
|
2048
|
+
const taskId = parseCreateResultTaskId(resultText);
|
|
2049
|
+
if (!taskId) return false;
|
|
2050
|
+
this.tasksByTaskId.set(taskId, pending);
|
|
2051
|
+
this.tasksByCreateToolUseId.delete(toolUseId);
|
|
2052
|
+
const idx = this.orderedKeys.indexOf(toolUseId);
|
|
2053
|
+
if (idx !== -1) this.orderedKeys.splice(idx, 1, taskId);
|
|
2054
|
+
return true;
|
|
2055
|
+
}
|
|
2056
|
+
getTasks() {
|
|
2057
|
+
const out = [];
|
|
2058
|
+
for (const key of this.orderedKeys) {
|
|
2059
|
+
const task = this.tasksByTaskId.get(key) ?? this.tasksByCreateToolUseId.get(key);
|
|
2060
|
+
if (task && task.subject) out.push(task);
|
|
2061
|
+
}
|
|
2062
|
+
return out;
|
|
2063
|
+
}
|
|
2064
|
+
processContentBlock(block) {
|
|
2065
|
+
if (!isRecord(block)) return false;
|
|
2066
|
+
if (block.type === "tool_use" && typeof block.name === "string" && typeof block.id === "string") {
|
|
2067
|
+
return this.processToolUse(block.name, block.id, toAccumulatorInput(block.input));
|
|
2068
|
+
}
|
|
2069
|
+
if (block.type === "tool_result" && typeof block.tool_use_id === "string") {
|
|
2070
|
+
return this.processCreateResult(block.tool_use_id, extractToolResultText(block.content, ""));
|
|
2071
|
+
}
|
|
2072
|
+
return false;
|
|
2073
|
+
}
|
|
2074
|
+
};
|
|
2075
|
+
|
|
1908
2076
|
// ../shared/src/agent-event-utils.ts
|
|
1909
2077
|
function getUserMessage(event) {
|
|
1910
2078
|
return event.type === "event_msg" && event.payload.type === "user_message" && typeof event.payload.message === "string" ? event.payload.message : null;
|
|
@@ -3282,15 +3450,15 @@ function withPreview(stored) {
|
|
|
3282
3450
|
function isObject(value) {
|
|
3283
3451
|
return typeof value === "object" && value !== null;
|
|
3284
3452
|
}
|
|
3285
|
-
function
|
|
3453
|
+
function optionalString2(value) {
|
|
3286
3454
|
return typeof value === "string" ? value : void 0;
|
|
3287
3455
|
}
|
|
3288
3456
|
function normalizeStored(raw) {
|
|
3289
3457
|
if (!isObject(raw)) return null;
|
|
3290
3458
|
if (typeof raw.output !== "string" || typeof raw.exitCode !== "number") return null;
|
|
3291
3459
|
const hookType = raw.hookType === "environment" ? "environment" : "repository";
|
|
3292
|
-
const repoNameField =
|
|
3293
|
-
const hookName =
|
|
3460
|
+
const repoNameField = optionalString2(raw.repoName);
|
|
3461
|
+
const hookName = optionalString2(raw.hookName) ?? repoNameField ?? "";
|
|
3294
3462
|
const repoName = repoNameField ?? hookName;
|
|
3295
3463
|
const hookCommands = Array.isArray(raw.hookCommands) ? raw.hookCommands.filter((c) => typeof c === "string") : [];
|
|
3296
3464
|
return {
|
|
@@ -3301,7 +3469,7 @@ function normalizeStored(raw) {
|
|
|
3301
3469
|
output: raw.output,
|
|
3302
3470
|
exitCode: raw.exitCode,
|
|
3303
3471
|
timedOut: typeof raw.timedOut === "boolean" ? raw.timedOut : false,
|
|
3304
|
-
executedAt:
|
|
3472
|
+
executedAt: optionalString2(raw.executedAt) ?? ""
|
|
3305
3473
|
};
|
|
3306
3474
|
}
|
|
3307
3475
|
var StartHookLogsService = class {
|
|
@@ -4004,14 +4172,8 @@ function summarizeInput(input) {
|
|
|
4004
4172
|
if (obj.pattern) return `pattern: ${String(obj.pattern)}`;
|
|
4005
4173
|
if (obj.query) return String(obj.query);
|
|
4006
4174
|
if (obj.url) return String(obj.url);
|
|
4007
|
-
if (obj.
|
|
4008
|
-
|
|
4009
|
-
const completed = todos.filter((t) => t.status === "completed").length;
|
|
4010
|
-
const total = todos.length;
|
|
4011
|
-
const currentTask = todos.find((t) => t.status === "in_progress");
|
|
4012
|
-
const summary = `${completed}/${total}`;
|
|
4013
|
-
return currentTask?.content ? `${summary}: ${currentTask.content}` : summary;
|
|
4014
|
-
}
|
|
4175
|
+
if (typeof obj.activeForm === "string" && obj.activeForm) return String(obj.activeForm);
|
|
4176
|
+
if (typeof obj.subject === "string" && obj.subject) return String(obj.subject);
|
|
4015
4177
|
const keys = Object.keys(obj);
|
|
4016
4178
|
if (keys.length > 0) {
|
|
4017
4179
|
const firstKey = keys[0];
|
|
@@ -4075,7 +4237,10 @@ function convertClaudeEvent(event, linearSessionId) {
|
|
|
4075
4237
|
case "Task":
|
|
4076
4238
|
action = "Spawning subagent";
|
|
4077
4239
|
break;
|
|
4078
|
-
case "
|
|
4240
|
+
case "TaskCreate":
|
|
4241
|
+
case "TaskUpdate":
|
|
4242
|
+
case "TaskList":
|
|
4243
|
+
case "TaskGet":
|
|
4079
4244
|
action = "Updating plan";
|
|
4080
4245
|
break;
|
|
4081
4246
|
}
|
|
@@ -4095,12 +4260,7 @@ function convertClaudeEvent(event, linearSessionId) {
|
|
|
4095
4260
|
const contentBlocks = message.message?.content || [];
|
|
4096
4261
|
for (const block of contentBlocks) {
|
|
4097
4262
|
if (block.type === "tool_result") {
|
|
4098
|
-
|
|
4099
|
-
if (typeof block.content === "string") {
|
|
4100
|
-
resultText = block.content;
|
|
4101
|
-
} else if (Array.isArray(block.content)) {
|
|
4102
|
-
resultText = block.content.filter((c) => c.type === "text").map((c) => c.text || "").join("\n");
|
|
4103
|
-
}
|
|
4263
|
+
const resultText = extractToolResultText(block.content);
|
|
4104
4264
|
const isError = block.is_error || false;
|
|
4105
4265
|
const result = isError ? `Error: ${resultText}` : resultText || "Done";
|
|
4106
4266
|
return {
|
|
@@ -4129,34 +4289,6 @@ function mapTodoStatus(status) {
|
|
|
4129
4289
|
}
|
|
4130
4290
|
return "pending";
|
|
4131
4291
|
}
|
|
4132
|
-
function extractPlanFromClaudeEvent(event) {
|
|
4133
|
-
if (event.type !== "assistant") {
|
|
4134
|
-
return null;
|
|
4135
|
-
}
|
|
4136
|
-
const message = event;
|
|
4137
|
-
const contentBlocks = message.message?.content || [];
|
|
4138
|
-
for (const block of contentBlocks) {
|
|
4139
|
-
if (block.type !== "tool_use" || block.name !== "TodoWrite") {
|
|
4140
|
-
continue;
|
|
4141
|
-
}
|
|
4142
|
-
const input = typeof block.input === "string" ? (() => {
|
|
4143
|
-
try {
|
|
4144
|
-
return JSON.parse(block.input);
|
|
4145
|
-
} catch {
|
|
4146
|
-
return null;
|
|
4147
|
-
}
|
|
4148
|
-
})() : typeof block.input === "object" && block.input !== null ? block.input : null;
|
|
4149
|
-
const todos = input?.todos;
|
|
4150
|
-
if (!todos || todos.length === 0) {
|
|
4151
|
-
return null;
|
|
4152
|
-
}
|
|
4153
|
-
return todos.filter((todo) => Boolean(todo.content && todo.content.trim().length > 0)).map((todo) => ({
|
|
4154
|
-
content: todo.content.trim(),
|
|
4155
|
-
status: mapTodoStatus(todo.status)
|
|
4156
|
-
}));
|
|
4157
|
-
}
|
|
4158
|
-
return null;
|
|
4159
|
-
}
|
|
4160
4292
|
function convertCodexEvent(event, linearSessionId) {
|
|
4161
4293
|
if (event.type === "turn.started") {
|
|
4162
4294
|
return {
|
|
@@ -4950,6 +5082,7 @@ function isLinearThoughtEvent(event) {
|
|
|
4950
5082
|
}
|
|
4951
5083
|
var LinearEventForwarder = class {
|
|
4952
5084
|
linearSessionId;
|
|
5085
|
+
taskAccumulator = new TaskAccumulator();
|
|
4953
5086
|
latestThoughtEvent = null;
|
|
4954
5087
|
constructor(linearSessionId) {
|
|
4955
5088
|
this.linearSessionId = linearSessionId;
|
|
@@ -4962,6 +5095,25 @@ var LinearEventForwarder = class {
|
|
|
4962
5095
|
}).catch(() => {
|
|
4963
5096
|
});
|
|
4964
5097
|
}
|
|
5098
|
+
processClaudeEventForPlan(event) {
|
|
5099
|
+
if (!this.linearSessionId) return;
|
|
5100
|
+
if (!this.routeEventToAccumulator(event)) return;
|
|
5101
|
+
const plan = this.taskAccumulator.getTasks().map((task) => ({
|
|
5102
|
+
content: task.subject,
|
|
5103
|
+
status: mapTodoStatus(task.status)
|
|
5104
|
+
}));
|
|
5105
|
+
this.sendPlan(plan);
|
|
5106
|
+
}
|
|
5107
|
+
routeEventToAccumulator(event) {
|
|
5108
|
+
if (event.type !== "assistant" && event.type !== "user") return false;
|
|
5109
|
+
const content = event.message.content;
|
|
5110
|
+
if (!Array.isArray(content)) return false;
|
|
5111
|
+
let changed = false;
|
|
5112
|
+
for (const block of content) {
|
|
5113
|
+
if (this.taskAccumulator.processContentBlock(block)) changed = true;
|
|
5114
|
+
}
|
|
5115
|
+
return changed;
|
|
5116
|
+
}
|
|
4965
5117
|
sendEvent(linearEvent) {
|
|
4966
5118
|
if (!this.linearSessionId || !linearEvent) return;
|
|
4967
5119
|
if (this.latestThoughtEvent) {
|
|
@@ -5032,7 +5184,10 @@ var ALWAYS_ALLOWED_TOOLS = [
|
|
|
5032
5184
|
"Grep",
|
|
5033
5185
|
"WebSearch",
|
|
5034
5186
|
"WebFetch",
|
|
5035
|
-
"
|
|
5187
|
+
"TaskCreate",
|
|
5188
|
+
"TaskUpdate",
|
|
5189
|
+
"TaskGet",
|
|
5190
|
+
"TaskList",
|
|
5036
5191
|
"Agent",
|
|
5037
5192
|
"ListMcpResourcesTool",
|
|
5038
5193
|
"ReadMcpResourceTool",
|
|
@@ -5144,7 +5299,14 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5144
5299
|
sessionId = null;
|
|
5145
5300
|
activeQuery = null;
|
|
5146
5301
|
activePromptStream = null;
|
|
5302
|
+
activeSessionSignature = null;
|
|
5303
|
+
activeSessionModel = null;
|
|
5304
|
+
activeSessionPermissionMode = null;
|
|
5305
|
+
sessionLoop = null;
|
|
5306
|
+
sessionLinearForwarder = null;
|
|
5307
|
+
pendingTurn = null;
|
|
5147
5308
|
pendingInterrupt = false;
|
|
5309
|
+
activeBackgroundTasks = /* @__PURE__ */ new Set();
|
|
5148
5310
|
systemPromptOverride;
|
|
5149
5311
|
toolsOverride;
|
|
5150
5312
|
mcpServersConfig;
|
|
@@ -5165,7 +5327,6 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5165
5327
|
}
|
|
5166
5328
|
async interruptActiveTurn() {
|
|
5167
5329
|
this.pendingInterrupt = true;
|
|
5168
|
-
this.activePromptStream?.close();
|
|
5169
5330
|
if (this.activeQuery) {
|
|
5170
5331
|
await this.activeQuery.interrupt();
|
|
5171
5332
|
}
|
|
@@ -5347,117 +5508,271 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5347
5508
|
thinkingLevel,
|
|
5348
5509
|
enableInteractiveTools
|
|
5349
5510
|
} = request;
|
|
5350
|
-
const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
|
|
5351
5511
|
if (!message || !message.trim()) {
|
|
5352
5512
|
throw new Error("Message cannot be empty");
|
|
5353
5513
|
}
|
|
5354
5514
|
await this.initialized;
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5515
|
+
this.pendingInterrupt = false;
|
|
5516
|
+
const content = [
|
|
5517
|
+
{
|
|
5518
|
+
type: "text",
|
|
5519
|
+
text: message
|
|
5520
|
+
}
|
|
5521
|
+
];
|
|
5522
|
+
if (images && images.length > 0) {
|
|
5523
|
+
const normalizedImages = await normalizeImages(images);
|
|
5524
|
+
for (const image of normalizedImages) {
|
|
5525
|
+
content.push({
|
|
5526
|
+
type: "image",
|
|
5527
|
+
source: {
|
|
5528
|
+
type: "base64",
|
|
5529
|
+
media_type: image.source.media_type,
|
|
5530
|
+
data: image.source.data
|
|
5531
|
+
}
|
|
5532
|
+
});
|
|
5533
|
+
}
|
|
5534
|
+
}
|
|
5535
|
+
const userMessage = {
|
|
5536
|
+
type: "user",
|
|
5537
|
+
message: {
|
|
5538
|
+
role: "user",
|
|
5539
|
+
content
|
|
5540
|
+
},
|
|
5541
|
+
parent_tool_use_id: null,
|
|
5542
|
+
session_id: this.sessionId ?? ""
|
|
5543
|
+
};
|
|
5544
|
+
if (!options.skipUserMessageRecord) {
|
|
5545
|
+
await this.recordEvent(userMessage);
|
|
5546
|
+
}
|
|
5547
|
+
const combinedInstructions = this.buildCombinedInstructions(customInstructions);
|
|
5548
|
+
const resolvedModel = normalizeClaudeModel(model) || CLAUDE_OPUS_1M_MODEL;
|
|
5549
|
+
const resolvedPermissionMode = permissionMode === "read" ? "plan" : "bypassPermissions";
|
|
5550
|
+
const signature = {
|
|
5551
|
+
combinedInstructions,
|
|
5552
|
+
thinkingLevel,
|
|
5553
|
+
// enableInteractiveTools only matters when permissionMode is 'read'; the
|
|
5554
|
+
// session signature tracks the effective flag so a permissionMode change
|
|
5555
|
+
// can hot-swap via setPermissionMode without restarting.
|
|
5556
|
+
enableInteractiveTools: Boolean(enableInteractiveTools)
|
|
5557
|
+
};
|
|
5558
|
+
await this.ensureSession({
|
|
5559
|
+
signature,
|
|
5560
|
+
combinedInstructions,
|
|
5561
|
+
resolvedModel,
|
|
5562
|
+
resolvedPermissionMode,
|
|
5563
|
+
enableInteractiveTools: signature.enableInteractiveTools,
|
|
5564
|
+
thinkingLevel
|
|
5565
|
+
});
|
|
5566
|
+
const promptStream = this.activePromptStream;
|
|
5567
|
+
const activeQuery = this.activeQuery;
|
|
5568
|
+
if (!promptStream || !activeQuery) {
|
|
5569
|
+
throw new Error("Claude session unavailable after ensureSession");
|
|
5570
|
+
}
|
|
5571
|
+
if (this.pendingInterrupt) {
|
|
5572
|
+
this.pendingInterrupt = false;
|
|
5573
|
+
return;
|
|
5574
|
+
}
|
|
5575
|
+
await new Promise((resolve3, reject) => {
|
|
5576
|
+
this.pendingTurn = { resolve: resolve3, reject };
|
|
5577
|
+
promptStream.push(userMessage);
|
|
5578
|
+
});
|
|
5579
|
+
}
|
|
5580
|
+
async ensureSession(args) {
|
|
5581
|
+
const {
|
|
5582
|
+
signature,
|
|
5583
|
+
combinedInstructions,
|
|
5584
|
+
resolvedModel,
|
|
5585
|
+
resolvedPermissionMode,
|
|
5586
|
+
enableInteractiveTools,
|
|
5587
|
+
thinkingLevel
|
|
5588
|
+
} = args;
|
|
5589
|
+
if (this.activeQuery && this.activeSessionSignature && this.sessionSignaturesMatch(this.activeSessionSignature, signature)) {
|
|
5590
|
+
if (this.activeSessionModel !== resolvedModel) {
|
|
5591
|
+
try {
|
|
5592
|
+
await this.activeQuery.setModel(resolvedModel);
|
|
5593
|
+
this.activeSessionModel = resolvedModel;
|
|
5594
|
+
} catch (err) {
|
|
5595
|
+
console.warn("[ClaudeManager] setModel failed; recreating session:", err);
|
|
5596
|
+
await this.tearDownSession();
|
|
5360
5597
|
}
|
|
5361
|
-
|
|
5362
|
-
if (
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
media_type: image.source.media_type,
|
|
5370
|
-
data: image.source.data
|
|
5371
|
-
}
|
|
5372
|
-
});
|
|
5598
|
+
}
|
|
5599
|
+
if (this.activeQuery && this.activeSessionPermissionMode !== resolvedPermissionMode) {
|
|
5600
|
+
try {
|
|
5601
|
+
await this.activeQuery.setPermissionMode(resolvedPermissionMode);
|
|
5602
|
+
this.activeSessionPermissionMode = resolvedPermissionMode;
|
|
5603
|
+
} catch (err) {
|
|
5604
|
+
console.warn("[ClaudeManager] setPermissionMode failed; recreating session:", err);
|
|
5605
|
+
await this.tearDownSession();
|
|
5373
5606
|
}
|
|
5374
5607
|
}
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5608
|
+
if (this.activeQuery) return;
|
|
5609
|
+
} else if (this.activeQuery) {
|
|
5610
|
+
await this.tearDownSession();
|
|
5611
|
+
}
|
|
5612
|
+
await this.startSession({
|
|
5613
|
+
combinedInstructions,
|
|
5614
|
+
resolvedModel,
|
|
5615
|
+
resolvedPermissionMode,
|
|
5616
|
+
enableInteractiveTools,
|
|
5617
|
+
thinkingLevel,
|
|
5618
|
+
signature
|
|
5619
|
+
});
|
|
5620
|
+
}
|
|
5621
|
+
sessionSignaturesMatch(a, b) {
|
|
5622
|
+
return a.combinedInstructions === b.combinedInstructions && a.thinkingLevel === b.thinkingLevel && a.enableInteractiveTools === b.enableInteractiveTools;
|
|
5623
|
+
}
|
|
5624
|
+
async startSession(args) {
|
|
5625
|
+
const {
|
|
5626
|
+
combinedInstructions,
|
|
5627
|
+
resolvedModel,
|
|
5628
|
+
resolvedPermissionMode,
|
|
5629
|
+
enableInteractiveTools,
|
|
5630
|
+
thinkingLevel,
|
|
5631
|
+
signature
|
|
5632
|
+
} = args;
|
|
5633
|
+
const systemPrompt = this.systemPromptOverride ? this.systemPromptOverride(combinedInstructions) : {
|
|
5634
|
+
type: "preset",
|
|
5635
|
+
preset: "claude_code",
|
|
5636
|
+
append: combinedInstructions
|
|
5637
|
+
};
|
|
5638
|
+
const queryEnv = buildClaudeAgentEnv(this.envOverrides);
|
|
5639
|
+
const additionalDirectories = await getAgentAdditionalDirectories();
|
|
5640
|
+
const interactiveAllowed = enableInteractiveTools && resolvedPermissionMode === "plan";
|
|
5641
|
+
const useDefaultToolPolicy = !this.toolsOverride;
|
|
5642
|
+
const allowedTools = useDefaultToolPolicy ? [
|
|
5643
|
+
...ALWAYS_ALLOWED_TOOLS,
|
|
5644
|
+
...interactiveAllowed ? INTERACTIVE_TOOL_NAMES : []
|
|
5645
|
+
] : void 0;
|
|
5646
|
+
const disallowedTools = [
|
|
5647
|
+
...this.disallowedToolsOverride ?? [],
|
|
5648
|
+
...useDefaultToolPolicy ? ALWAYS_DISALLOWED_TOOLS : [],
|
|
5649
|
+
...interactiveAllowed ? [] : INTERACTIVE_TOOL_NAMES
|
|
5650
|
+
];
|
|
5651
|
+
const promptStream = new PromptStream();
|
|
5652
|
+
const response = query({
|
|
5653
|
+
prompt: promptStream,
|
|
5654
|
+
options: {
|
|
5655
|
+
resume: this.sessionId || void 0,
|
|
5656
|
+
cwd: this.workingDirectory,
|
|
5657
|
+
additionalDirectories,
|
|
5658
|
+
permissionMode: resolvedPermissionMode,
|
|
5659
|
+
allowDangerouslySkipPermissions: resolvedPermissionMode === "bypassPermissions",
|
|
5660
|
+
...this.toolsOverride ? { tools: this.toolsOverride } : {},
|
|
5661
|
+
...allowedTools ? { allowedTools } : {},
|
|
5662
|
+
...disallowedTools.length > 0 ? { disallowedTools } : {},
|
|
5663
|
+
settingSources: ["user", "project", "local"],
|
|
5664
|
+
systemPrompt,
|
|
5665
|
+
...this.mcpServersConfig ? { mcpServers: this.mcpServersConfig } : {},
|
|
5666
|
+
env: queryEnv,
|
|
5667
|
+
model: resolvedModel,
|
|
5668
|
+
...thinkingLevel ? { effort: thinkingLevel } : {},
|
|
5669
|
+
canUseTool: this.buildCanUseTool()
|
|
5386
5670
|
}
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
...useDefaultToolPolicy ? ALWAYS_DISALLOWED_TOOLS : [],
|
|
5408
|
-
...interactiveAllowed ? [] : INTERACTIVE_TOOL_NAMES
|
|
5409
|
-
];
|
|
5410
|
-
const response = query({
|
|
5411
|
-
prompt: promptStream,
|
|
5412
|
-
options: {
|
|
5413
|
-
resume: this.sessionId || void 0,
|
|
5414
|
-
cwd: this.workingDirectory,
|
|
5415
|
-
additionalDirectories,
|
|
5416
|
-
permissionMode: permissionMode === "read" ? "plan" : "bypassPermissions",
|
|
5417
|
-
allowDangerouslySkipPermissions: permissionMode !== "read",
|
|
5418
|
-
...this.toolsOverride ? { tools: this.toolsOverride } : {},
|
|
5419
|
-
...allowedTools ? { allowedTools } : {},
|
|
5420
|
-
...disallowedTools.length > 0 ? { disallowedTools } : {},
|
|
5421
|
-
settingSources: ["user", "project", "local"],
|
|
5422
|
-
systemPrompt,
|
|
5423
|
-
...this.mcpServersConfig ? { mcpServers: this.mcpServersConfig } : {},
|
|
5424
|
-
env: queryEnv,
|
|
5425
|
-
model: resolvedModel,
|
|
5426
|
-
...thinkingLevel ? { effort: thinkingLevel } : {},
|
|
5427
|
-
canUseTool: this.buildCanUseTool()
|
|
5428
|
-
}
|
|
5429
|
-
});
|
|
5430
|
-
this.activeQuery = response;
|
|
5431
|
-
if (this.pendingInterrupt) {
|
|
5432
|
-
this.pendingInterrupt = false;
|
|
5433
|
-
this.activePromptStream?.close();
|
|
5434
|
-
await this.activeQuery.interrupt();
|
|
5435
|
-
}
|
|
5436
|
-
const linearForwarder = new LinearEventForwarder(linearSessionId);
|
|
5437
|
-
for await (const msg of response) {
|
|
5671
|
+
});
|
|
5672
|
+
this.activeQuery = response;
|
|
5673
|
+
this.activePromptStream = promptStream;
|
|
5674
|
+
this.activeSessionSignature = signature;
|
|
5675
|
+
this.activeSessionModel = resolvedModel;
|
|
5676
|
+
this.activeSessionPermissionMode = resolvedPermissionMode;
|
|
5677
|
+
this.sessionLinearForwarder = new LinearEventForwarder(ENGINE_ENV.LINEAR_SESSION_ID);
|
|
5678
|
+
this.activeBackgroundTasks.clear();
|
|
5679
|
+
this.sessionLoop = this.runSessionLoop(response).catch((err) => {
|
|
5680
|
+
console.error("[ClaudeManager] Session loop crashed:", err);
|
|
5681
|
+
});
|
|
5682
|
+
}
|
|
5683
|
+
async runSessionLoop(response) {
|
|
5684
|
+
const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
|
|
5685
|
+
const iterator = response[Symbol.asyncIterator]();
|
|
5686
|
+
try {
|
|
5687
|
+
while (true) {
|
|
5688
|
+
const next = await iterator.next();
|
|
5689
|
+
if (next.done) break;
|
|
5690
|
+
const msg = next.value;
|
|
5438
5691
|
const authErrorMessage = _ClaudeManager.detectAuthErrorInMessage(msg);
|
|
5439
5692
|
if (authErrorMessage) {
|
|
5440
|
-
this.
|
|
5441
|
-
|
|
5693
|
+
this.failPendingTurn(new ClaudeAuthError(authErrorMessage));
|
|
5694
|
+
try {
|
|
5695
|
+
response.close();
|
|
5696
|
+
} catch (err) {
|
|
5697
|
+
console.warn("[ClaudeManager] query.close() during auth error failed:", err);
|
|
5698
|
+
}
|
|
5699
|
+
return;
|
|
5442
5700
|
}
|
|
5443
5701
|
this.setAuthRetrying(false);
|
|
5444
5702
|
await this.handleMessage(msg);
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5703
|
+
_ClaudeManager.updateBackgroundTaskState(msg, this.activeBackgroundTasks);
|
|
5704
|
+
if (linearSessionId && this.sessionLinearForwarder) {
|
|
5705
|
+
this.sessionLinearForwarder.processClaudeEventForPlan(msg);
|
|
5706
|
+
this.sessionLinearForwarder.sendEvent(convertClaudeEvent(msg, linearSessionId));
|
|
5448
5707
|
}
|
|
5449
5708
|
if (msg.type === "result") {
|
|
5450
5709
|
await this.recordContextUsage(response);
|
|
5451
|
-
this.
|
|
5452
|
-
|
|
5710
|
+
this.sessionLinearForwarder?.flushThoughtAsResponse();
|
|
5711
|
+
this.resolvePendingTurn();
|
|
5453
5712
|
}
|
|
5454
5713
|
}
|
|
5455
|
-
linearForwarder.flushThoughtAsResponse();
|
|
5456
5714
|
} finally {
|
|
5457
|
-
this.
|
|
5458
|
-
this.
|
|
5459
|
-
this.
|
|
5460
|
-
|
|
5715
|
+
this.sessionLinearForwarder?.flushThoughtAsResponse();
|
|
5716
|
+
this.failPendingTurn(new Error("Claude session ended unexpectedly"));
|
|
5717
|
+
if (this.activeQuery === response) {
|
|
5718
|
+
this.clearSessionState();
|
|
5719
|
+
}
|
|
5720
|
+
}
|
|
5721
|
+
}
|
|
5722
|
+
clearSessionState() {
|
|
5723
|
+
this.activeQuery = null;
|
|
5724
|
+
this.activePromptStream = null;
|
|
5725
|
+
this.activeSessionSignature = null;
|
|
5726
|
+
this.activeSessionModel = null;
|
|
5727
|
+
this.activeSessionPermissionMode = null;
|
|
5728
|
+
this.sessionLinearForwarder = null;
|
|
5729
|
+
this.sessionLoop = null;
|
|
5730
|
+
this.activeBackgroundTasks.clear();
|
|
5731
|
+
}
|
|
5732
|
+
resolvePendingTurn() {
|
|
5733
|
+
const pending = this.pendingTurn;
|
|
5734
|
+
if (!pending) return;
|
|
5735
|
+
this.pendingTurn = null;
|
|
5736
|
+
this.pendingInterrupt = false;
|
|
5737
|
+
pending.resolve();
|
|
5738
|
+
}
|
|
5739
|
+
failPendingTurn(err) {
|
|
5740
|
+
const pending = this.pendingTurn;
|
|
5741
|
+
if (!pending) return;
|
|
5742
|
+
this.pendingTurn = null;
|
|
5743
|
+
this.pendingInterrupt = false;
|
|
5744
|
+
pending.reject(err);
|
|
5745
|
+
}
|
|
5746
|
+
async tearDownSession() {
|
|
5747
|
+
const query2 = this.activeQuery;
|
|
5748
|
+
const stream = this.activePromptStream;
|
|
5749
|
+
const loop = this.sessionLoop;
|
|
5750
|
+
this.failPendingTurn(new Error("Claude session torn down"));
|
|
5751
|
+
this.clearSessionState();
|
|
5752
|
+
if (query2) {
|
|
5753
|
+
try {
|
|
5754
|
+
query2.close();
|
|
5755
|
+
} catch (err) {
|
|
5756
|
+
console.warn("[ClaudeManager] query.close() failed:", err);
|
|
5757
|
+
}
|
|
5758
|
+
}
|
|
5759
|
+
stream?.close();
|
|
5760
|
+
if (loop) {
|
|
5761
|
+
try {
|
|
5762
|
+
await loop;
|
|
5763
|
+
} catch {
|
|
5764
|
+
}
|
|
5765
|
+
}
|
|
5766
|
+
}
|
|
5767
|
+
static updateBackgroundTaskState(message, activeTasks) {
|
|
5768
|
+
if (message.type !== "system") return;
|
|
5769
|
+
const payload = coerceBackgroundTaskPayload(message);
|
|
5770
|
+
if (!payload) return;
|
|
5771
|
+
const status = payload.subtype === "task_updated" ? payload.patch?.status : payload.status;
|
|
5772
|
+
if (isTerminalBackgroundTaskStatus(status)) {
|
|
5773
|
+
activeTasks.delete(payload.taskId);
|
|
5774
|
+
} else {
|
|
5775
|
+
activeTasks.add(payload.taskId);
|
|
5461
5776
|
}
|
|
5462
5777
|
}
|
|
5463
5778
|
getContextUsageProvider() {
|
|
@@ -5775,7 +6090,7 @@ var AspClient = class {
|
|
|
5775
6090
|
// src/managers/codex-asp/app-server-process.ts
|
|
5776
6091
|
var DEFAULT_CODEX_BINARY = "codex";
|
|
5777
6092
|
var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
5778
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
6093
|
+
var ENGINE_PACKAGE_VERSION = "0.1.238";
|
|
5779
6094
|
var INITIALIZE_METHOD = "initialize";
|
|
5780
6095
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
5781
6096
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -8140,7 +8455,7 @@ function getEnvironmentSection() {
|
|
|
8140
8455
|
`Platform: ${process.platform}`,
|
|
8141
8456
|
getShellInfoLine(),
|
|
8142
8457
|
`OS Version: ${unameSR}`,
|
|
8143
|
-
`The most recent Claude model family is Claude 4.5/4.6/4.
|
|
8458
|
+
`The most recent Claude model family is Claude 4.5/4.6/4.8. Model IDs \u2014 Opus 4.8: 'claude-opus-4-8', Sonnet 4.6: 'claude-sonnet-4-6', Haiku 4.5: 'claude-haiku-4-5-20251001'. When building AI applications, default to the latest and most capable Claude models.`
|
|
8144
8459
|
];
|
|
8145
8460
|
return [
|
|
8146
8461
|
`# Environment`,
|
|
@@ -8176,7 +8491,10 @@ var RELAY_TOOLS = [
|
|
|
8176
8491
|
"WebSearch",
|
|
8177
8492
|
"WebFetch",
|
|
8178
8493
|
"Skill",
|
|
8179
|
-
"
|
|
8494
|
+
"TaskCreate",
|
|
8495
|
+
"TaskUpdate",
|
|
8496
|
+
"TaskGet",
|
|
8497
|
+
"TaskList",
|
|
8180
8498
|
"TaskOutput",
|
|
8181
8499
|
"TaskStop"
|
|
8182
8500
|
];
|