@fangyb/ahchat-bridge 0.1.18 → 0.1.19
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/cli.cjs +316 -52
- package/dist/index.js +316 -49
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -4361,8 +4361,8 @@ function resolveAgentConfigDir(dataDir) {
|
|
|
4361
4361
|
}
|
|
4362
4362
|
return newPath;
|
|
4363
4363
|
}
|
|
4364
|
-
function loadBridgeConfig() {
|
|
4365
|
-
const dataDir = readEnvString(
|
|
4364
|
+
function loadBridgeConfig(opts) {
|
|
4365
|
+
const dataDir = opts?.dataDir ?? readEnvString(
|
|
4366
4366
|
"AHCHAT_DATA_DIR",
|
|
4367
4367
|
import_node_path.default.join(import_node_os.default.homedir(), ".ahchat")
|
|
4368
4368
|
);
|
|
@@ -6510,6 +6510,9 @@ var LOG_LEVEL_VALUE2 = {
|
|
|
6510
6510
|
|
|
6511
6511
|
// ../shared/src/types/onboarding.ts
|
|
6512
6512
|
init_cjs_shims();
|
|
6513
|
+
function isCapabilityTier(v9) {
|
|
6514
|
+
return v9 === "smart" || v9 === "balanced" || v9 === "fast";
|
|
6515
|
+
}
|
|
6513
6516
|
|
|
6514
6517
|
// ../shared/src/utils.ts
|
|
6515
6518
|
init_cjs_shims();
|
|
@@ -6588,18 +6591,6 @@ function parseWSMessage(raw) {
|
|
|
6588
6591
|
|
|
6589
6592
|
// ../shared/src/utils/workdir.ts
|
|
6590
6593
|
init_cjs_shims();
|
|
6591
|
-
var SLUG_MAX_LEN = 32;
|
|
6592
|
-
function slugifyForFs(name) {
|
|
6593
|
-
const trimmed = name.trim();
|
|
6594
|
-
if (!trimmed) return "unnamed";
|
|
6595
|
-
const slug = trimmed.replace(/[^\w\u4e00-\u9fa5 \-]/gu, "_").replace(/\s+/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
6596
|
-
const base = slug.length > 0 ? slug : "unnamed";
|
|
6597
|
-
return base.length > SLUG_MAX_LEN ? base.slice(0, SLUG_MAX_LEN) : base;
|
|
6598
|
-
}
|
|
6599
|
-
function defaultGroupWorkdir(home, name, id) {
|
|
6600
|
-
const slug = slugifyForFs(name);
|
|
6601
|
-
return `${home}/.ahchat/Group-${slug}-${id}`;
|
|
6602
|
-
}
|
|
6603
6594
|
|
|
6604
6595
|
// ../shared/src/utils/groupAuto.ts
|
|
6605
6596
|
init_cjs_shims();
|
|
@@ -6622,6 +6613,7 @@ function parseAgentConfig(raw) {
|
|
|
6622
6613
|
const out = {};
|
|
6623
6614
|
const obj = v9;
|
|
6624
6615
|
if (typeof obj.model === "string" && obj.model.trim()) out.model = obj.model.trim();
|
|
6616
|
+
if (isCapabilityTier(obj.capabilityTier)) out.capabilityTier = obj.capabilityTier;
|
|
6625
6617
|
if (typeof obj.subscriptionId === "string") {
|
|
6626
6618
|
const trimmed = obj.subscriptionId.trim();
|
|
6627
6619
|
if (/^sub_[A-Za-z0-9_-]{1,64}$/.test(trimmed)) {
|
|
@@ -44852,9 +44844,12 @@ limit \u9ED8\u8BA4 500\uFF0C\u786C\u4E0A\u9650 2000\u3002\u8FD4\u56DE\u7ED3\u679
|
|
|
44852
44844
|
const tierRes = await fetch(tierUrl);
|
|
44853
44845
|
if (tierRes.ok) {
|
|
44854
44846
|
const tiers = await tierRes.json();
|
|
44855
|
-
const
|
|
44847
|
+
const self2 = deps.agentRegistry?.getById(deps.agentId);
|
|
44848
|
+
const preferredSubscriptionId = parseAgentConfig(self2?.config).subscriptionId;
|
|
44849
|
+
const tierConfig = tiers.find((t2) => t2.tier === tier && t2.subscriptionId === preferredSubscriptionId) ?? tiers.find((t2) => t2.tier === tier);
|
|
44856
44850
|
if (tierConfig) {
|
|
44857
44851
|
agentConfig = JSON.stringify({
|
|
44852
|
+
capabilityTier: tier,
|
|
44858
44853
|
subscriptionId: tierConfig.subscriptionId,
|
|
44859
44854
|
model: tierConfig.modelName
|
|
44860
44855
|
});
|
|
@@ -45006,9 +45001,11 @@ limit \u9ED8\u8BA4 500\uFF0C\u786C\u4E0A\u9650 2000\u3002\u8FD4\u56DE\u7ED3\u679
|
|
|
45006
45001
|
const tierRes = await fetch(tierUrl);
|
|
45007
45002
|
if (tierRes.ok) {
|
|
45008
45003
|
const tiers = await tierRes.json();
|
|
45009
|
-
const
|
|
45004
|
+
const preferredSubscriptionId = parseAgentConfig(existing.config).subscriptionId;
|
|
45005
|
+
const tierConfig = tiers.find((t2) => t2.tier === tier && t2.subscriptionId === preferredSubscriptionId) ?? tiers.find((t2) => t2.tier === tier);
|
|
45010
45006
|
if (tierConfig) {
|
|
45011
45007
|
agentConfig = JSON.stringify({
|
|
45008
|
+
capabilityTier: tier,
|
|
45012
45009
|
subscriptionId: tierConfig.subscriptionId,
|
|
45013
45010
|
model: tierConfig.modelName
|
|
45014
45011
|
});
|
|
@@ -45743,11 +45740,117 @@ init_cjs_shims();
|
|
|
45743
45740
|
var logger7 = createModuleLogger("sdk.mapper");
|
|
45744
45741
|
var HIGH_WATERMARK_INPUT_TOKENS = 12e4;
|
|
45745
45742
|
var WARN_THRESHOLD_INPUT_TOKENS = 1e5;
|
|
45743
|
+
var LIVE_INPUT_PREVIEW_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit"]);
|
|
45746
45744
|
var CONTEXT_OVERFLOW_LOCK_MS = 6e4;
|
|
45747
45745
|
function isContextOverflowText(text) {
|
|
45748
45746
|
const trimmed = text.trim();
|
|
45749
45747
|
return /^prompt is too long\b/i.test(trimmed) || /context length .* exceed/i.test(trimmed);
|
|
45750
45748
|
}
|
|
45749
|
+
function isAuthFailureText(text, sdkError) {
|
|
45750
|
+
return sdkError === "authentication_failed" || /not logged in|please run \/login/i.test(text);
|
|
45751
|
+
}
|
|
45752
|
+
function buildAuthFailureMessage(errorText) {
|
|
45753
|
+
return `Claude Code SDK \u672A\u767B\u5F55\uFF08${errorText}\uFF09\u3002\u8BF7\u5728 bridge \u4E3B\u673A\u4E0A\u914D\u7F6E\u8BA4\u8BC1\uFF1A\u82E5\u8BE5 Agent \u7528 system \u8BA2\u9605\uFF0C\u5C06\u5176 subscriptionType \u8BBE\u4E3A "system"\uFF08\u8D70 ~/.claude\uFF09\uFF1B\u5426\u5219\u5728 ~/.ahchat/claude-config \u4E0B\u767B\u5F55\uFF0C\u6216\u5728 Agent config \u4E2D\u63D0\u4F9B apiKey / apiBaseUrl\u3002`;
|
|
45754
|
+
}
|
|
45755
|
+
function decodeJsonStringFragment(raw) {
|
|
45756
|
+
let out = "";
|
|
45757
|
+
for (let i = 0; i < raw.length; i++) {
|
|
45758
|
+
const ch2 = raw[i];
|
|
45759
|
+
if (ch2 !== "\\") {
|
|
45760
|
+
out += ch2;
|
|
45761
|
+
continue;
|
|
45762
|
+
}
|
|
45763
|
+
const next = raw[i + 1];
|
|
45764
|
+
if (next === void 0) break;
|
|
45765
|
+
i += 1;
|
|
45766
|
+
switch (next) {
|
|
45767
|
+
case '"':
|
|
45768
|
+
case "\\":
|
|
45769
|
+
case "/":
|
|
45770
|
+
out += next;
|
|
45771
|
+
break;
|
|
45772
|
+
case "b":
|
|
45773
|
+
out += "\b";
|
|
45774
|
+
break;
|
|
45775
|
+
case "f":
|
|
45776
|
+
out += "\f";
|
|
45777
|
+
break;
|
|
45778
|
+
case "n":
|
|
45779
|
+
out += "\n";
|
|
45780
|
+
break;
|
|
45781
|
+
case "r":
|
|
45782
|
+
out += "\r";
|
|
45783
|
+
break;
|
|
45784
|
+
case "t":
|
|
45785
|
+
out += " ";
|
|
45786
|
+
break;
|
|
45787
|
+
case "u": {
|
|
45788
|
+
const hex3 = raw.slice(i + 1, i + 5);
|
|
45789
|
+
if (!/^[0-9a-fA-F]{4}$/.test(hex3)) return out;
|
|
45790
|
+
out += String.fromCharCode(Number.parseInt(hex3, 16));
|
|
45791
|
+
i += 4;
|
|
45792
|
+
break;
|
|
45793
|
+
}
|
|
45794
|
+
default:
|
|
45795
|
+
out += next;
|
|
45796
|
+
}
|
|
45797
|
+
}
|
|
45798
|
+
return out;
|
|
45799
|
+
}
|
|
45800
|
+
function extractJsonStringPrefix(source, key) {
|
|
45801
|
+
const keyToken = `"${key}"`;
|
|
45802
|
+
const keyIndex = source.indexOf(keyToken);
|
|
45803
|
+
if (keyIndex < 0) return null;
|
|
45804
|
+
let i = keyIndex + keyToken.length;
|
|
45805
|
+
while (i < source.length && /\s/.test(source[i] ?? "")) i += 1;
|
|
45806
|
+
if (source[i] !== ":") return null;
|
|
45807
|
+
i += 1;
|
|
45808
|
+
while (i < source.length && /\s/.test(source[i] ?? "")) i += 1;
|
|
45809
|
+
if (source[i] !== '"') return null;
|
|
45810
|
+
i += 1;
|
|
45811
|
+
let raw = "";
|
|
45812
|
+
let escaped = false;
|
|
45813
|
+
for (; i < source.length; i++) {
|
|
45814
|
+
const ch2 = source[i];
|
|
45815
|
+
if (ch2 === void 0) break;
|
|
45816
|
+
if (escaped) {
|
|
45817
|
+
raw += `\\${ch2}`;
|
|
45818
|
+
escaped = false;
|
|
45819
|
+
continue;
|
|
45820
|
+
}
|
|
45821
|
+
if (ch2 === "\\") {
|
|
45822
|
+
escaped = true;
|
|
45823
|
+
continue;
|
|
45824
|
+
}
|
|
45825
|
+
if (ch2 === '"') {
|
|
45826
|
+
return decodeJsonStringFragment(raw);
|
|
45827
|
+
}
|
|
45828
|
+
raw += ch2;
|
|
45829
|
+
}
|
|
45830
|
+
if (escaped) raw += "\\";
|
|
45831
|
+
return decodeJsonStringFragment(raw);
|
|
45832
|
+
}
|
|
45833
|
+
function extractLiveToolInput(toolName, inputJson) {
|
|
45834
|
+
if (toolName === "Write") {
|
|
45835
|
+
const content = extractJsonStringPrefix(inputJson, "content");
|
|
45836
|
+
if (content == null) return null;
|
|
45837
|
+
const filePath = extractJsonStringPrefix(inputJson, "file_path");
|
|
45838
|
+
return filePath == null ? { content } : { file_path: filePath, content };
|
|
45839
|
+
}
|
|
45840
|
+
if (toolName === "Edit") {
|
|
45841
|
+
const newString = extractJsonStringPrefix(inputJson, "new_string");
|
|
45842
|
+
if (newString == null) return null;
|
|
45843
|
+
const oldString = extractJsonStringPrefix(inputJson, "old_string");
|
|
45844
|
+
const filePath = extractJsonStringPrefix(inputJson, "file_path");
|
|
45845
|
+
const input = {
|
|
45846
|
+
new_string: newString
|
|
45847
|
+
};
|
|
45848
|
+
if (filePath != null) input.file_path = filePath;
|
|
45849
|
+
if (oldString != null) input.old_string = oldString;
|
|
45850
|
+
return input;
|
|
45851
|
+
}
|
|
45852
|
+
return null;
|
|
45853
|
+
}
|
|
45751
45854
|
function recordAssistantContextUsage(proc, am2) {
|
|
45752
45855
|
const u = am2.message?.usage;
|
|
45753
45856
|
if (!u) return;
|
|
@@ -45815,6 +45918,45 @@ function cleanupPlanMode(proc, emit, base, reason) {
|
|
|
45815
45918
|
});
|
|
45816
45919
|
proc.planModeActive = false;
|
|
45817
45920
|
}
|
|
45921
|
+
function extractAssistantTextParts(content, depth = 0) {
|
|
45922
|
+
if (depth > 4) return [];
|
|
45923
|
+
if (typeof content === "string") return [content];
|
|
45924
|
+
if (Array.isArray(content)) {
|
|
45925
|
+
return content.flatMap((item) => extractAssistantTextParts(item, depth + 1));
|
|
45926
|
+
}
|
|
45927
|
+
if (typeof content !== "object" || content === null) return [];
|
|
45928
|
+
const block = content;
|
|
45929
|
+
const type = typeof block.type === "string" ? block.type : null;
|
|
45930
|
+
if (type === "tool_use" || type === "tool_result") return [];
|
|
45931
|
+
if (type === "text" || type === "output_text" || type == null) {
|
|
45932
|
+
const textParts = extractAssistantTextParts(block.text, depth + 1);
|
|
45933
|
+
if (textParts.length > 0) return textParts;
|
|
45934
|
+
return extractAssistantTextParts(block.content, depth + 1);
|
|
45935
|
+
}
|
|
45936
|
+
return [];
|
|
45937
|
+
}
|
|
45938
|
+
function describeAssistantContent(content) {
|
|
45939
|
+
if (Array.isArray(content)) {
|
|
45940
|
+
return {
|
|
45941
|
+
contentShape: "array",
|
|
45942
|
+
blockTypes: content.map((item) => {
|
|
45943
|
+
if (typeof item !== "object" || item === null) return typeof item;
|
|
45944
|
+
const type = item.type;
|
|
45945
|
+
return typeof type === "string" ? type : "(no-type)";
|
|
45946
|
+
}).slice(0, 12)
|
|
45947
|
+
};
|
|
45948
|
+
}
|
|
45949
|
+
if (typeof content === "object" && content !== null) {
|
|
45950
|
+
return {
|
|
45951
|
+
contentShape: "object",
|
|
45952
|
+
contentKeys: Object.keys(content).slice(0, 12)
|
|
45953
|
+
};
|
|
45954
|
+
}
|
|
45955
|
+
return { contentShape: typeof content };
|
|
45956
|
+
}
|
|
45957
|
+
function scopeLogLabel(scope) {
|
|
45958
|
+
return scope.kind === "single" ? "single" : scope.groupId;
|
|
45959
|
+
}
|
|
45818
45960
|
function getTaskBase(proc) {
|
|
45819
45961
|
if (proc.currentTask) {
|
|
45820
45962
|
return {
|
|
@@ -45824,10 +45966,42 @@ function getTaskBase(proc) {
|
|
|
45824
45966
|
replyMessageId: proc.currentTask.replyMessageId
|
|
45825
45967
|
};
|
|
45826
45968
|
}
|
|
45969
|
+
const continuation = proc.postMergeContinuationTask;
|
|
45970
|
+
const continuationUntil = proc.postMergeContinuationUntil ?? 0;
|
|
45971
|
+
if (continuation) {
|
|
45972
|
+
if (Date.now() <= continuationUntil) {
|
|
45973
|
+
proc.currentTask = continuation;
|
|
45974
|
+
proc.status = "working";
|
|
45975
|
+
proc.currentTaskStartedAt = Date.now();
|
|
45976
|
+
delete proc.postMergeContinuationTask;
|
|
45977
|
+
delete proc.postMergeContinuationUntil;
|
|
45978
|
+
logger7.info("SDK post-merge continuation routed to merged task", {
|
|
45979
|
+
agentId: proc.agentId,
|
|
45980
|
+
scope: scopeLogLabel(proc.scope),
|
|
45981
|
+
replyMessageId: continuation.replyMessageId,
|
|
45982
|
+
conversationId: continuation.conversationId,
|
|
45983
|
+
traceId: continuation.traceId
|
|
45984
|
+
});
|
|
45985
|
+
return {
|
|
45986
|
+
agentId: proc.agentId,
|
|
45987
|
+
conversationId: continuation.conversationId,
|
|
45988
|
+
traceId: continuation.traceId,
|
|
45989
|
+
replyMessageId: continuation.replyMessageId
|
|
45990
|
+
};
|
|
45991
|
+
}
|
|
45992
|
+
logger7.info("SDK post-merge continuation route expired", {
|
|
45993
|
+
agentId: proc.agentId,
|
|
45994
|
+
scope: scopeLogLabel(proc.scope),
|
|
45995
|
+
replyMessageId: continuation.replyMessageId,
|
|
45996
|
+
routeUntil: new Date(continuationUntil).toISOString()
|
|
45997
|
+
});
|
|
45998
|
+
delete proc.postMergeContinuationTask;
|
|
45999
|
+
delete proc.postMergeContinuationUntil;
|
|
46000
|
+
}
|
|
45827
46001
|
if (!proc.cachedConversationId) {
|
|
45828
46002
|
logger7.warn("SDK self-initiated turn without cachedConversationId; dropping", {
|
|
45829
46003
|
agentId: proc.agentId,
|
|
45830
|
-
scope: proc.scope
|
|
46004
|
+
scope: scopeLogLabel(proc.scope)
|
|
45831
46005
|
});
|
|
45832
46006
|
return null;
|
|
45833
46007
|
}
|
|
@@ -45844,7 +46018,7 @@ function getTaskBase(proc) {
|
|
|
45844
46018
|
proc.currentTaskStartedAt = Date.now();
|
|
45845
46019
|
logger7.info("Cron-initiated turn detected, synthesized task", {
|
|
45846
46020
|
agentId: proc.agentId,
|
|
45847
|
-
scope: proc.scope
|
|
46021
|
+
scope: scopeLogLabel(proc.scope),
|
|
45848
46022
|
replyMessageId,
|
|
45849
46023
|
conversationId: proc.cachedConversationId,
|
|
45850
46024
|
traceId
|
|
@@ -46088,6 +46262,17 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
46088
46262
|
const partial2 = delta.partial_json;
|
|
46089
46263
|
if (typeof partial2 === "string") {
|
|
46090
46264
|
proc.accumulatedToolInput += partial2;
|
|
46265
|
+
const liveInput = extractLiveToolInput(proc.currentToolName, proc.accumulatedToolInput);
|
|
46266
|
+
if (liveInput && proc.currentToolName != null) {
|
|
46267
|
+
emit({
|
|
46268
|
+
type: "agent:tool_input_update",
|
|
46269
|
+
payload: {
|
|
46270
|
+
...wireBase(base),
|
|
46271
|
+
toolName: proc.currentToolName,
|
|
46272
|
+
input: liveInput
|
|
46273
|
+
}
|
|
46274
|
+
});
|
|
46275
|
+
}
|
|
46091
46276
|
}
|
|
46092
46277
|
} else if (delta.type === "text_delta" && typeof delta.text === "string") {
|
|
46093
46278
|
if (proc.accumulatedText.length === 0) {
|
|
@@ -46142,6 +46327,16 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
46142
46327
|
if (lastToolUse && lastToolUse.type === "tool_use") {
|
|
46143
46328
|
lastToolUse.input = parsedInput;
|
|
46144
46329
|
}
|
|
46330
|
+
if (proc.currentToolName != null && LIVE_INPUT_PREVIEW_TOOLS.has(proc.currentToolName) && Object.keys(parsedInput).length > 0) {
|
|
46331
|
+
emit({
|
|
46332
|
+
type: "agent:tool_input_update",
|
|
46333
|
+
payload: {
|
|
46334
|
+
...wireBase(base),
|
|
46335
|
+
toolName: proc.currentToolName,
|
|
46336
|
+
input: parsedInput
|
|
46337
|
+
}
|
|
46338
|
+
});
|
|
46339
|
+
}
|
|
46145
46340
|
if (proc.currentToolName === "TodoWrite") {
|
|
46146
46341
|
const todos = extractTodosFromInput(parsedInput);
|
|
46147
46342
|
if (todos) {
|
|
@@ -46386,6 +46581,29 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
46386
46581
|
onCompleted();
|
|
46387
46582
|
break;
|
|
46388
46583
|
}
|
|
46584
|
+
if (proc.accumulatedText.length === 0 && proc.contentBlocks.length === 0) {
|
|
46585
|
+
cleanupPlanMode(proc, emit, base, "error");
|
|
46586
|
+
logger7.warn("SDK success produced empty assistant output; emitting agent:error", {
|
|
46587
|
+
agentId: proc.agentId,
|
|
46588
|
+
ackId: base.replyMessageId,
|
|
46589
|
+
tokenCount: usage.tokenCount,
|
|
46590
|
+
inputTokens: usage.inputTokens,
|
|
46591
|
+
cacheReadTokens: usage.cacheReadTokens,
|
|
46592
|
+
cacheCreationTokens: usage.cacheCreationTokens,
|
|
46593
|
+
assistantContent: proc.lastAssistantContentDescription,
|
|
46594
|
+
traceId: base.traceId
|
|
46595
|
+
});
|
|
46596
|
+
emit({
|
|
46597
|
+
type: "agent:error",
|
|
46598
|
+
payload: {
|
|
46599
|
+
...wireBase(base),
|
|
46600
|
+
error: "Agent \u8FD4\u56DE\u4E86\u7A7A\u7ED3\u679C\uFF0C\u5DF2\u963B\u6B62\u7A7A\u6D88\u606F\u8986\u76D6\u601D\u8003\u6C14\u6CE1\u3002\u8BF7\u91CD\u8BD5\uFF1B\u5982\u679C\u53CD\u590D\u51FA\u73B0\uFF0C\u8BF7\u68C0\u67E5 Claude Code \u767B\u5F55\u72B6\u6001\u6216\u6A21\u578B\u914D\u7F6E\u3002"
|
|
46601
|
+
}
|
|
46602
|
+
});
|
|
46603
|
+
resetAccumulators(proc);
|
|
46604
|
+
onCompleted();
|
|
46605
|
+
break;
|
|
46606
|
+
}
|
|
46389
46607
|
if (proc.accumulatedText) {
|
|
46390
46608
|
proc.contentBlocks.push({ type: "text", content: proc.accumulatedText });
|
|
46391
46609
|
}
|
|
@@ -46455,14 +46673,9 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
46455
46673
|
if (am2.isApiErrorMessage === true) {
|
|
46456
46674
|
const base = getTaskBase(proc);
|
|
46457
46675
|
if (!base) break;
|
|
46458
|
-
const errorTexts =
|
|
46459
|
-
for (const block of am2.message?.content ?? []) {
|
|
46460
|
-
if (block?.type === "text" && typeof block.text === "string") {
|
|
46461
|
-
errorTexts.push(block.text);
|
|
46462
|
-
}
|
|
46463
|
-
}
|
|
46676
|
+
const errorTexts = extractAssistantTextParts(am2.message?.content);
|
|
46464
46677
|
const errorText = errorTexts.join("\n").trim() || `SDK ${am2.error ?? "api_error"}`;
|
|
46465
|
-
const isAuthFail = am2.error
|
|
46678
|
+
const isAuthFail = isAuthFailureText(errorText, am2.error);
|
|
46466
46679
|
if (isAuthFail) {
|
|
46467
46680
|
sessionStore.delete(proc.agentId, proc.scope);
|
|
46468
46681
|
}
|
|
@@ -46474,7 +46687,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
46474
46687
|
isAuthFail,
|
|
46475
46688
|
traceId: base.traceId
|
|
46476
46689
|
});
|
|
46477
|
-
const friendlyError = isAuthFail ?
|
|
46690
|
+
const friendlyError = isAuthFail ? buildAuthFailureMessage(errorText) : errorText;
|
|
46478
46691
|
emit({
|
|
46479
46692
|
type: "agent:error",
|
|
46480
46693
|
payload: { ...wireBase(base), error: friendlyError }
|
|
@@ -46487,14 +46700,36 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
46487
46700
|
break;
|
|
46488
46701
|
}
|
|
46489
46702
|
if (proc.accumulatedText.length === 0 && proc.contentBlocks.length === 0) {
|
|
46490
|
-
const captured =
|
|
46491
|
-
for (const block of am2.message?.content ?? []) {
|
|
46492
|
-
if (block?.type === "text" && typeof block.text === "string") {
|
|
46493
|
-
captured.push(block.text);
|
|
46494
|
-
}
|
|
46495
|
-
}
|
|
46703
|
+
const captured = extractAssistantTextParts(am2.message?.content);
|
|
46496
46704
|
if (captured.length > 0) {
|
|
46497
46705
|
const text = captured.join("");
|
|
46706
|
+
if (isAuthFailureText(text, am2.error)) {
|
|
46707
|
+
const base = getTaskBase(proc);
|
|
46708
|
+
logger7.warn("SDK auth failure assistant detected without api-error flag, emitting agent:error", {
|
|
46709
|
+
agentId: proc.agentId,
|
|
46710
|
+
scope: proc.scope.kind === "single" ? "single" : proc.scope.groupId,
|
|
46711
|
+
sdkError: am2.error,
|
|
46712
|
+
errorText: text.slice(0, 200),
|
|
46713
|
+
traceId: base?.traceId,
|
|
46714
|
+
hasCurrentTask: base != null
|
|
46715
|
+
});
|
|
46716
|
+
if (base) {
|
|
46717
|
+
sessionStore.delete(proc.agentId, proc.scope);
|
|
46718
|
+
emit({
|
|
46719
|
+
type: "agent:error",
|
|
46720
|
+
payload: {
|
|
46721
|
+
...wireBase(base),
|
|
46722
|
+
error: buildAuthFailureMessage(text)
|
|
46723
|
+
}
|
|
46724
|
+
});
|
|
46725
|
+
proc.apiErrorEmitted = true;
|
|
46726
|
+
}
|
|
46727
|
+
proc.contentBlocks = [];
|
|
46728
|
+
proc.accumulatedText = "";
|
|
46729
|
+
proc.accumulatedThinking = "";
|
|
46730
|
+
proc.segmentBuffer = "";
|
|
46731
|
+
break;
|
|
46732
|
+
}
|
|
46498
46733
|
if (isContextOverflowText(text)) {
|
|
46499
46734
|
const base = getTaskBase(proc);
|
|
46500
46735
|
logger7.warn("SDK reported context overflow; auto-compact already failed inside SDK", {
|
|
@@ -46538,6 +46773,8 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
46538
46773
|
textLen: text.length,
|
|
46539
46774
|
textSample: text.slice(0, 100)
|
|
46540
46775
|
});
|
|
46776
|
+
} else {
|
|
46777
|
+
proc.lastAssistantContentDescription = describeAssistantContent(am2.message?.content);
|
|
46541
46778
|
}
|
|
46542
46779
|
}
|
|
46543
46780
|
break;
|
|
@@ -46561,6 +46798,7 @@ function resetAccumulators(proc) {
|
|
|
46561
46798
|
proc.accumulatedToolInput = "";
|
|
46562
46799
|
proc.apiErrorEmitted = false;
|
|
46563
46800
|
proc.peakContextUsage = void 0;
|
|
46801
|
+
proc.lastAssistantContentDescription = void 0;
|
|
46564
46802
|
}
|
|
46565
46803
|
|
|
46566
46804
|
// src/forkHistoryReplay.ts
|
|
@@ -46675,8 +46913,15 @@ var wsMetrics = new WsMetrics();
|
|
|
46675
46913
|
// src/agentManager.ts
|
|
46676
46914
|
var logger10 = createModuleLogger("agent.manager");
|
|
46677
46915
|
var NODE_USER_UID = 1e3;
|
|
46916
|
+
var POST_MERGE_CONTINUATION_ROUTE_MS = 15e3;
|
|
46678
46917
|
function isSmithAgent(agent) {
|
|
46679
|
-
|
|
46918
|
+
if (agent.id === SMITH_AGENT_ID) return true;
|
|
46919
|
+
if (agent.systemPrompt === SMITH_SYSTEM_PROMPT) return true;
|
|
46920
|
+
const prompt = agent.systemPrompt ?? "";
|
|
46921
|
+
if (prompt.includes("\u4F60\u662F\u7279\u5DE5\u53F2\u5BC6\u65AF") && prompt.includes("create_agent")) return true;
|
|
46922
|
+
const name = agent.name?.toLowerCase() ?? "";
|
|
46923
|
+
const role = agent.role?.toLowerCase() ?? "";
|
|
46924
|
+
return role === "system" && (name.includes("\u53F2\u5BC6\u65AF") || name.includes("smith"));
|
|
46680
46925
|
}
|
|
46681
46926
|
function isRunningAsRoot() {
|
|
46682
46927
|
try {
|
|
@@ -46685,6 +46930,13 @@ function isRunningAsRoot() {
|
|
|
46685
46930
|
return false;
|
|
46686
46931
|
}
|
|
46687
46932
|
}
|
|
46933
|
+
async function chownForRootSpawn(targetPath, target) {
|
|
46934
|
+
try {
|
|
46935
|
+
await import_promises8.default.chown(targetPath, NODE_USER_UID, NODE_USER_UID);
|
|
46936
|
+
} catch (error51) {
|
|
46937
|
+
logger10.error("Best-effort root chown failed", { error: error51, target, path: targetPath });
|
|
46938
|
+
}
|
|
46939
|
+
}
|
|
46688
46940
|
function readCronLockSnapshot() {
|
|
46689
46941
|
try {
|
|
46690
46942
|
const lockPath2 = import_node_path8.default.join(import_node_os5.default.homedir(), ".claude", "scheduled_tasks.lock");
|
|
@@ -47433,19 +47685,10 @@ Do NOT use "..." as content \u2014 write specific, project-relevant content.`;
|
|
|
47433
47685
|
options.resume = savedSessionId;
|
|
47434
47686
|
}
|
|
47435
47687
|
if (isRunningAsRoot()) {
|
|
47436
|
-
|
|
47437
|
-
|
|
47438
|
-
} catch {
|
|
47439
|
-
}
|
|
47440
|
-
try {
|
|
47441
|
-
await import_promises8.default.chown(agentCwd, NODE_USER_UID, NODE_USER_UID);
|
|
47442
|
-
} catch {
|
|
47443
|
-
}
|
|
47688
|
+
await chownForRootSpawn(effectiveConfigDir, "configDir");
|
|
47689
|
+
await chownForRootSpawn(agentCwd, "agentCwd");
|
|
47444
47690
|
const settingsFilePath = import_node_path8.default.join(effectiveConfigDir, "settings.json");
|
|
47445
|
-
|
|
47446
|
-
await import_promises8.default.chown(settingsFilePath, NODE_USER_UID, NODE_USER_UID);
|
|
47447
|
-
} catch {
|
|
47448
|
-
}
|
|
47691
|
+
await chownForRootSpawn(settingsFilePath, "settingsFile");
|
|
47449
47692
|
options.spawnClaudeCodeProcess = (spawnOptions) => {
|
|
47450
47693
|
const env2 = { ...spawnOptions.env, HOME: "/home/node" };
|
|
47451
47694
|
return (0, import_node_child_process.spawn)(spawnOptions.command, spawnOptions.args, {
|
|
@@ -47611,7 +47854,7 @@ ${trimmed}`;
|
|
|
47611
47854
|
lines.push(` workdir: ${currentCwd}`);
|
|
47612
47855
|
} else {
|
|
47613
47856
|
const a = this.agentRegistry?.getById(agentId);
|
|
47614
|
-
const singleCwd = a?.workingDirectory || import_node_path8.default.join(
|
|
47857
|
+
const singleCwd = a?.workingDirectory || import_node_path8.default.join(this.workspacesDir, agentId);
|
|
47615
47858
|
lines.push(` workdir: ${singleCwd}`);
|
|
47616
47859
|
}
|
|
47617
47860
|
let rosterCount = 0;
|
|
@@ -47623,7 +47866,7 @@ ${trimmed}`;
|
|
|
47623
47866
|
if (key === curKey) {
|
|
47624
47867
|
lines.push(` workdir: ${currentCwd}`);
|
|
47625
47868
|
} else {
|
|
47626
|
-
const groupCwd =
|
|
47869
|
+
const groupCwd = g2.workingDirectory || import_node_path8.default.join(this.workspacesDir, g2.groupId);
|
|
47627
47870
|
lines.push(` workdir: ${groupCwd}`);
|
|
47628
47871
|
}
|
|
47629
47872
|
const others = g2.members.filter((id) => id !== agentId).map((id) => {
|
|
@@ -47970,6 +48213,16 @@ ${lines.join("\n")}`;
|
|
|
47970
48213
|
}
|
|
47971
48214
|
}
|
|
47972
48215
|
async dispatchToSDK(runtime, task) {
|
|
48216
|
+
if (runtime.postMergeContinuationTask) {
|
|
48217
|
+
logger10.info("Clearing stale post-merge continuation route before explicit dispatch", {
|
|
48218
|
+
agentId: runtime.agentId,
|
|
48219
|
+
staleReplyMessageId: runtime.postMergeContinuationTask.replyMessageId,
|
|
48220
|
+
nextReplyMessageId: task.replyMessageId,
|
|
48221
|
+
traceId: task.traceId
|
|
48222
|
+
});
|
|
48223
|
+
delete runtime.postMergeContinuationTask;
|
|
48224
|
+
delete runtime.postMergeContinuationUntil;
|
|
48225
|
+
}
|
|
47973
48226
|
await this.applyEffortMode(runtime, "high", {
|
|
47974
48227
|
source: "dispatchToSDK",
|
|
47975
48228
|
replyMessageId: task.replyMessageId
|
|
@@ -48178,6 +48431,19 @@ ${lines.join("\n")}`;
|
|
|
48178
48431
|
}
|
|
48179
48432
|
});
|
|
48180
48433
|
}
|
|
48434
|
+
const continuationTask = mergedBatch.at(-1);
|
|
48435
|
+
if (continuationTask) {
|
|
48436
|
+
proc.postMergeContinuationTask = continuationTask;
|
|
48437
|
+
proc.postMergeContinuationUntil = Date.now() + POST_MERGE_CONTINUATION_ROUTE_MS;
|
|
48438
|
+
logger10.info("Armed SDK post-merge continuation routing", {
|
|
48439
|
+
agentId: proc.agentId,
|
|
48440
|
+
carrierReplyMessageId: completedTask.replyMessageId,
|
|
48441
|
+
continuationReplyMessageId: continuationTask.replyMessageId,
|
|
48442
|
+
mergedCount: mergedBatch.length,
|
|
48443
|
+
routeUntil: new Date(proc.postMergeContinuationUntil).toISOString(),
|
|
48444
|
+
traceId: completedTask.traceId
|
|
48445
|
+
});
|
|
48446
|
+
}
|
|
48181
48447
|
runtime.mergedTasks = [];
|
|
48182
48448
|
} else if (runtime.mergedTasks.length > 0) {
|
|
48183
48449
|
logger10.warn("mergedTasks non-empty but no currentTask; dropping", {
|
|
@@ -51489,6 +51755,7 @@ Bridge token (register this machine at Settings \u2192 \u5DF2\u8FDE\u63A5\u7684\
|
|
|
51489
51755
|
agentRegistry,
|
|
51490
51756
|
subscriptionRegistry,
|
|
51491
51757
|
serverApiUrl: config2.serverApiUrl,
|
|
51758
|
+
bridgeToken: config2.bridgeToken,
|
|
51492
51759
|
dataDir: config2.dataDir
|
|
51493
51760
|
});
|
|
51494
51761
|
const taskDispatchHandler = createTaskDispatchHandler(agentManager, agentRegistry, emit);
|
|
@@ -52096,17 +52363,14 @@ function parseAhchatUrl(url2) {
|
|
|
52096
52363
|
}
|
|
52097
52364
|
}
|
|
52098
52365
|
async function run(args) {
|
|
52099
|
-
|
|
52366
|
+
const dataDir = args.dataDir ? resolveDataDir(args.dataDir) : void 0;
|
|
52367
|
+
let config2 = loadBridgeConfig(dataDir ? { dataDir } : void 0);
|
|
52100
52368
|
if (args.serverUrl) {
|
|
52101
52369
|
const wsUrl = new URL(args.serverUrl);
|
|
52102
52370
|
const httpBase = `${wsUrl.protocol === "wss:" ? "https" : "http"}://${wsUrl.host}`;
|
|
52103
52371
|
config2 = { ...config2, serverUrl: args.serverUrl, serverApiUrl: httpBase };
|
|
52104
52372
|
}
|
|
52105
52373
|
if (args.token) config2 = { ...config2, bridgeToken: args.token };
|
|
52106
|
-
if (args.dataDir) {
|
|
52107
|
-
const resolved = resolveDataDir(args.dataDir);
|
|
52108
|
-
config2 = { ...config2, dataDir: resolved };
|
|
52109
|
-
}
|
|
52110
52374
|
if (args.logLevel) config2 = { ...config2, logLevel: args.logLevel };
|
|
52111
52375
|
await startBridge(config2);
|
|
52112
52376
|
}
|
package/dist/index.js
CHANGED
|
@@ -3746,8 +3746,8 @@ function resolveAgentConfigDir(dataDir) {
|
|
|
3746
3746
|
}
|
|
3747
3747
|
return newPath;
|
|
3748
3748
|
}
|
|
3749
|
-
function loadBridgeConfig() {
|
|
3750
|
-
const dataDir = readEnvString(
|
|
3749
|
+
function loadBridgeConfig(opts) {
|
|
3750
|
+
const dataDir = opts?.dataDir ?? readEnvString(
|
|
3751
3751
|
"AHCHAT_DATA_DIR",
|
|
3752
3752
|
path.join(os.homedir(), ".ahchat")
|
|
3753
3753
|
);
|
|
@@ -5851,6 +5851,11 @@ var LOG_LEVEL_VALUE2 = {
|
|
|
5851
5851
|
FATAL: 5
|
|
5852
5852
|
};
|
|
5853
5853
|
|
|
5854
|
+
// ../shared/src/types/onboarding.ts
|
|
5855
|
+
function isCapabilityTier(v9) {
|
|
5856
|
+
return v9 === "smart" || v9 === "balanced" || v9 === "fast";
|
|
5857
|
+
}
|
|
5858
|
+
|
|
5854
5859
|
// ../../node_modules/.pnpm/nanoid@5.1.11/node_modules/nanoid/index.js
|
|
5855
5860
|
import { webcrypto as crypto2 } from "crypto";
|
|
5856
5861
|
|
|
@@ -5921,20 +5926,6 @@ function parseWSMessage(raw) {
|
|
|
5921
5926
|
return parsed;
|
|
5922
5927
|
}
|
|
5923
5928
|
|
|
5924
|
-
// ../shared/src/utils/workdir.ts
|
|
5925
|
-
var SLUG_MAX_LEN = 32;
|
|
5926
|
-
function slugifyForFs(name) {
|
|
5927
|
-
const trimmed = name.trim();
|
|
5928
|
-
if (!trimmed) return "unnamed";
|
|
5929
|
-
const slug = trimmed.replace(/[^\w\u4e00-\u9fa5 \-]/gu, "_").replace(/\s+/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
5930
|
-
const base = slug.length > 0 ? slug : "unnamed";
|
|
5931
|
-
return base.length > SLUG_MAX_LEN ? base.slice(0, SLUG_MAX_LEN) : base;
|
|
5932
|
-
}
|
|
5933
|
-
function defaultGroupWorkdir(home, name, id) {
|
|
5934
|
-
const slug = slugifyForFs(name);
|
|
5935
|
-
return `${home}/.ahchat/Group-${slug}-${id}`;
|
|
5936
|
-
}
|
|
5937
|
-
|
|
5938
5929
|
// ../shared/src/utils/subscription.ts
|
|
5939
5930
|
function isSubscriptionType(v9) {
|
|
5940
5931
|
return v9 === "system" || v9 === "project";
|
|
@@ -5949,6 +5940,7 @@ function parseAgentConfig(raw) {
|
|
|
5949
5940
|
const out = {};
|
|
5950
5941
|
const obj = v9;
|
|
5951
5942
|
if (typeof obj.model === "string" && obj.model.trim()) out.model = obj.model.trim();
|
|
5943
|
+
if (isCapabilityTier(obj.capabilityTier)) out.capabilityTier = obj.capabilityTier;
|
|
5952
5944
|
if (typeof obj.subscriptionId === "string") {
|
|
5953
5945
|
const trimmed = obj.subscriptionId.trim();
|
|
5954
5946
|
if (/^sub_[A-Za-z0-9_-]{1,64}$/.test(trimmed)) {
|
|
@@ -44055,9 +44047,12 @@ limit \u9ED8\u8BA4 500\uFF0C\u786C\u4E0A\u9650 2000\u3002\u8FD4\u56DE\u7ED3\u679
|
|
|
44055
44047
|
const tierRes = await fetch(tierUrl);
|
|
44056
44048
|
if (tierRes.ok) {
|
|
44057
44049
|
const tiers = await tierRes.json();
|
|
44058
|
-
const
|
|
44050
|
+
const self2 = deps.agentRegistry?.getById(deps.agentId);
|
|
44051
|
+
const preferredSubscriptionId = parseAgentConfig(self2?.config).subscriptionId;
|
|
44052
|
+
const tierConfig = tiers.find((t2) => t2.tier === tier && t2.subscriptionId === preferredSubscriptionId) ?? tiers.find((t2) => t2.tier === tier);
|
|
44059
44053
|
if (tierConfig) {
|
|
44060
44054
|
agentConfig = JSON.stringify({
|
|
44055
|
+
capabilityTier: tier,
|
|
44061
44056
|
subscriptionId: tierConfig.subscriptionId,
|
|
44062
44057
|
model: tierConfig.modelName
|
|
44063
44058
|
});
|
|
@@ -44209,9 +44204,11 @@ limit \u9ED8\u8BA4 500\uFF0C\u786C\u4E0A\u9650 2000\u3002\u8FD4\u56DE\u7ED3\u679
|
|
|
44209
44204
|
const tierRes = await fetch(tierUrl);
|
|
44210
44205
|
if (tierRes.ok) {
|
|
44211
44206
|
const tiers = await tierRes.json();
|
|
44212
|
-
const
|
|
44207
|
+
const preferredSubscriptionId = parseAgentConfig(existing.config).subscriptionId;
|
|
44208
|
+
const tierConfig = tiers.find((t2) => t2.tier === tier && t2.subscriptionId === preferredSubscriptionId) ?? tiers.find((t2) => t2.tier === tier);
|
|
44213
44209
|
if (tierConfig) {
|
|
44214
44210
|
agentConfig = JSON.stringify({
|
|
44211
|
+
capabilityTier: tier,
|
|
44215
44212
|
subscriptionId: tierConfig.subscriptionId,
|
|
44216
44213
|
model: tierConfig.modelName
|
|
44217
44214
|
});
|
|
@@ -44943,11 +44940,117 @@ function buildGroupInboxPrompt(entries, opts = {}) {
|
|
|
44943
44940
|
var logger7 = createModuleLogger("sdk.mapper");
|
|
44944
44941
|
var HIGH_WATERMARK_INPUT_TOKENS = 12e4;
|
|
44945
44942
|
var WARN_THRESHOLD_INPUT_TOKENS = 1e5;
|
|
44943
|
+
var LIVE_INPUT_PREVIEW_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit"]);
|
|
44946
44944
|
var CONTEXT_OVERFLOW_LOCK_MS = 6e4;
|
|
44947
44945
|
function isContextOverflowText(text) {
|
|
44948
44946
|
const trimmed = text.trim();
|
|
44949
44947
|
return /^prompt is too long\b/i.test(trimmed) || /context length .* exceed/i.test(trimmed);
|
|
44950
44948
|
}
|
|
44949
|
+
function isAuthFailureText(text, sdkError) {
|
|
44950
|
+
return sdkError === "authentication_failed" || /not logged in|please run \/login/i.test(text);
|
|
44951
|
+
}
|
|
44952
|
+
function buildAuthFailureMessage(errorText) {
|
|
44953
|
+
return `Claude Code SDK \u672A\u767B\u5F55\uFF08${errorText}\uFF09\u3002\u8BF7\u5728 bridge \u4E3B\u673A\u4E0A\u914D\u7F6E\u8BA4\u8BC1\uFF1A\u82E5\u8BE5 Agent \u7528 system \u8BA2\u9605\uFF0C\u5C06\u5176 subscriptionType \u8BBE\u4E3A "system"\uFF08\u8D70 ~/.claude\uFF09\uFF1B\u5426\u5219\u5728 ~/.ahchat/claude-config \u4E0B\u767B\u5F55\uFF0C\u6216\u5728 Agent config \u4E2D\u63D0\u4F9B apiKey / apiBaseUrl\u3002`;
|
|
44954
|
+
}
|
|
44955
|
+
function decodeJsonStringFragment(raw) {
|
|
44956
|
+
let out = "";
|
|
44957
|
+
for (let i = 0; i < raw.length; i++) {
|
|
44958
|
+
const ch2 = raw[i];
|
|
44959
|
+
if (ch2 !== "\\") {
|
|
44960
|
+
out += ch2;
|
|
44961
|
+
continue;
|
|
44962
|
+
}
|
|
44963
|
+
const next = raw[i + 1];
|
|
44964
|
+
if (next === void 0) break;
|
|
44965
|
+
i += 1;
|
|
44966
|
+
switch (next) {
|
|
44967
|
+
case '"':
|
|
44968
|
+
case "\\":
|
|
44969
|
+
case "/":
|
|
44970
|
+
out += next;
|
|
44971
|
+
break;
|
|
44972
|
+
case "b":
|
|
44973
|
+
out += "\b";
|
|
44974
|
+
break;
|
|
44975
|
+
case "f":
|
|
44976
|
+
out += "\f";
|
|
44977
|
+
break;
|
|
44978
|
+
case "n":
|
|
44979
|
+
out += "\n";
|
|
44980
|
+
break;
|
|
44981
|
+
case "r":
|
|
44982
|
+
out += "\r";
|
|
44983
|
+
break;
|
|
44984
|
+
case "t":
|
|
44985
|
+
out += " ";
|
|
44986
|
+
break;
|
|
44987
|
+
case "u": {
|
|
44988
|
+
const hex3 = raw.slice(i + 1, i + 5);
|
|
44989
|
+
if (!/^[0-9a-fA-F]{4}$/.test(hex3)) return out;
|
|
44990
|
+
out += String.fromCharCode(Number.parseInt(hex3, 16));
|
|
44991
|
+
i += 4;
|
|
44992
|
+
break;
|
|
44993
|
+
}
|
|
44994
|
+
default:
|
|
44995
|
+
out += next;
|
|
44996
|
+
}
|
|
44997
|
+
}
|
|
44998
|
+
return out;
|
|
44999
|
+
}
|
|
45000
|
+
function extractJsonStringPrefix(source, key) {
|
|
45001
|
+
const keyToken = `"${key}"`;
|
|
45002
|
+
const keyIndex = source.indexOf(keyToken);
|
|
45003
|
+
if (keyIndex < 0) return null;
|
|
45004
|
+
let i = keyIndex + keyToken.length;
|
|
45005
|
+
while (i < source.length && /\s/.test(source[i] ?? "")) i += 1;
|
|
45006
|
+
if (source[i] !== ":") return null;
|
|
45007
|
+
i += 1;
|
|
45008
|
+
while (i < source.length && /\s/.test(source[i] ?? "")) i += 1;
|
|
45009
|
+
if (source[i] !== '"') return null;
|
|
45010
|
+
i += 1;
|
|
45011
|
+
let raw = "";
|
|
45012
|
+
let escaped = false;
|
|
45013
|
+
for (; i < source.length; i++) {
|
|
45014
|
+
const ch2 = source[i];
|
|
45015
|
+
if (ch2 === void 0) break;
|
|
45016
|
+
if (escaped) {
|
|
45017
|
+
raw += `\\${ch2}`;
|
|
45018
|
+
escaped = false;
|
|
45019
|
+
continue;
|
|
45020
|
+
}
|
|
45021
|
+
if (ch2 === "\\") {
|
|
45022
|
+
escaped = true;
|
|
45023
|
+
continue;
|
|
45024
|
+
}
|
|
45025
|
+
if (ch2 === '"') {
|
|
45026
|
+
return decodeJsonStringFragment(raw);
|
|
45027
|
+
}
|
|
45028
|
+
raw += ch2;
|
|
45029
|
+
}
|
|
45030
|
+
if (escaped) raw += "\\";
|
|
45031
|
+
return decodeJsonStringFragment(raw);
|
|
45032
|
+
}
|
|
45033
|
+
function extractLiveToolInput(toolName, inputJson) {
|
|
45034
|
+
if (toolName === "Write") {
|
|
45035
|
+
const content = extractJsonStringPrefix(inputJson, "content");
|
|
45036
|
+
if (content == null) return null;
|
|
45037
|
+
const filePath = extractJsonStringPrefix(inputJson, "file_path");
|
|
45038
|
+
return filePath == null ? { content } : { file_path: filePath, content };
|
|
45039
|
+
}
|
|
45040
|
+
if (toolName === "Edit") {
|
|
45041
|
+
const newString = extractJsonStringPrefix(inputJson, "new_string");
|
|
45042
|
+
if (newString == null) return null;
|
|
45043
|
+
const oldString = extractJsonStringPrefix(inputJson, "old_string");
|
|
45044
|
+
const filePath = extractJsonStringPrefix(inputJson, "file_path");
|
|
45045
|
+
const input = {
|
|
45046
|
+
new_string: newString
|
|
45047
|
+
};
|
|
45048
|
+
if (filePath != null) input.file_path = filePath;
|
|
45049
|
+
if (oldString != null) input.old_string = oldString;
|
|
45050
|
+
return input;
|
|
45051
|
+
}
|
|
45052
|
+
return null;
|
|
45053
|
+
}
|
|
44951
45054
|
function recordAssistantContextUsage(proc, am2) {
|
|
44952
45055
|
const u = am2.message?.usage;
|
|
44953
45056
|
if (!u) return;
|
|
@@ -45015,6 +45118,45 @@ function cleanupPlanMode(proc, emit, base, reason) {
|
|
|
45015
45118
|
});
|
|
45016
45119
|
proc.planModeActive = false;
|
|
45017
45120
|
}
|
|
45121
|
+
function extractAssistantTextParts(content, depth = 0) {
|
|
45122
|
+
if (depth > 4) return [];
|
|
45123
|
+
if (typeof content === "string") return [content];
|
|
45124
|
+
if (Array.isArray(content)) {
|
|
45125
|
+
return content.flatMap((item) => extractAssistantTextParts(item, depth + 1));
|
|
45126
|
+
}
|
|
45127
|
+
if (typeof content !== "object" || content === null) return [];
|
|
45128
|
+
const block = content;
|
|
45129
|
+
const type = typeof block.type === "string" ? block.type : null;
|
|
45130
|
+
if (type === "tool_use" || type === "tool_result") return [];
|
|
45131
|
+
if (type === "text" || type === "output_text" || type == null) {
|
|
45132
|
+
const textParts = extractAssistantTextParts(block.text, depth + 1);
|
|
45133
|
+
if (textParts.length > 0) return textParts;
|
|
45134
|
+
return extractAssistantTextParts(block.content, depth + 1);
|
|
45135
|
+
}
|
|
45136
|
+
return [];
|
|
45137
|
+
}
|
|
45138
|
+
function describeAssistantContent(content) {
|
|
45139
|
+
if (Array.isArray(content)) {
|
|
45140
|
+
return {
|
|
45141
|
+
contentShape: "array",
|
|
45142
|
+
blockTypes: content.map((item) => {
|
|
45143
|
+
if (typeof item !== "object" || item === null) return typeof item;
|
|
45144
|
+
const type = item.type;
|
|
45145
|
+
return typeof type === "string" ? type : "(no-type)";
|
|
45146
|
+
}).slice(0, 12)
|
|
45147
|
+
};
|
|
45148
|
+
}
|
|
45149
|
+
if (typeof content === "object" && content !== null) {
|
|
45150
|
+
return {
|
|
45151
|
+
contentShape: "object",
|
|
45152
|
+
contentKeys: Object.keys(content).slice(0, 12)
|
|
45153
|
+
};
|
|
45154
|
+
}
|
|
45155
|
+
return { contentShape: typeof content };
|
|
45156
|
+
}
|
|
45157
|
+
function scopeLogLabel(scope) {
|
|
45158
|
+
return scope.kind === "single" ? "single" : scope.groupId;
|
|
45159
|
+
}
|
|
45018
45160
|
function getTaskBase(proc) {
|
|
45019
45161
|
if (proc.currentTask) {
|
|
45020
45162
|
return {
|
|
@@ -45024,10 +45166,42 @@ function getTaskBase(proc) {
|
|
|
45024
45166
|
replyMessageId: proc.currentTask.replyMessageId
|
|
45025
45167
|
};
|
|
45026
45168
|
}
|
|
45169
|
+
const continuation = proc.postMergeContinuationTask;
|
|
45170
|
+
const continuationUntil = proc.postMergeContinuationUntil ?? 0;
|
|
45171
|
+
if (continuation) {
|
|
45172
|
+
if (Date.now() <= continuationUntil) {
|
|
45173
|
+
proc.currentTask = continuation;
|
|
45174
|
+
proc.status = "working";
|
|
45175
|
+
proc.currentTaskStartedAt = Date.now();
|
|
45176
|
+
delete proc.postMergeContinuationTask;
|
|
45177
|
+
delete proc.postMergeContinuationUntil;
|
|
45178
|
+
logger7.info("SDK post-merge continuation routed to merged task", {
|
|
45179
|
+
agentId: proc.agentId,
|
|
45180
|
+
scope: scopeLogLabel(proc.scope),
|
|
45181
|
+
replyMessageId: continuation.replyMessageId,
|
|
45182
|
+
conversationId: continuation.conversationId,
|
|
45183
|
+
traceId: continuation.traceId
|
|
45184
|
+
});
|
|
45185
|
+
return {
|
|
45186
|
+
agentId: proc.agentId,
|
|
45187
|
+
conversationId: continuation.conversationId,
|
|
45188
|
+
traceId: continuation.traceId,
|
|
45189
|
+
replyMessageId: continuation.replyMessageId
|
|
45190
|
+
};
|
|
45191
|
+
}
|
|
45192
|
+
logger7.info("SDK post-merge continuation route expired", {
|
|
45193
|
+
agentId: proc.agentId,
|
|
45194
|
+
scope: scopeLogLabel(proc.scope),
|
|
45195
|
+
replyMessageId: continuation.replyMessageId,
|
|
45196
|
+
routeUntil: new Date(continuationUntil).toISOString()
|
|
45197
|
+
});
|
|
45198
|
+
delete proc.postMergeContinuationTask;
|
|
45199
|
+
delete proc.postMergeContinuationUntil;
|
|
45200
|
+
}
|
|
45027
45201
|
if (!proc.cachedConversationId) {
|
|
45028
45202
|
logger7.warn("SDK self-initiated turn without cachedConversationId; dropping", {
|
|
45029
45203
|
agentId: proc.agentId,
|
|
45030
|
-
scope: proc.scope
|
|
45204
|
+
scope: scopeLogLabel(proc.scope)
|
|
45031
45205
|
});
|
|
45032
45206
|
return null;
|
|
45033
45207
|
}
|
|
@@ -45044,7 +45218,7 @@ function getTaskBase(proc) {
|
|
|
45044
45218
|
proc.currentTaskStartedAt = Date.now();
|
|
45045
45219
|
logger7.info("Cron-initiated turn detected, synthesized task", {
|
|
45046
45220
|
agentId: proc.agentId,
|
|
45047
|
-
scope: proc.scope
|
|
45221
|
+
scope: scopeLogLabel(proc.scope),
|
|
45048
45222
|
replyMessageId,
|
|
45049
45223
|
conversationId: proc.cachedConversationId,
|
|
45050
45224
|
traceId
|
|
@@ -45288,6 +45462,17 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45288
45462
|
const partial2 = delta.partial_json;
|
|
45289
45463
|
if (typeof partial2 === "string") {
|
|
45290
45464
|
proc.accumulatedToolInput += partial2;
|
|
45465
|
+
const liveInput = extractLiveToolInput(proc.currentToolName, proc.accumulatedToolInput);
|
|
45466
|
+
if (liveInput && proc.currentToolName != null) {
|
|
45467
|
+
emit({
|
|
45468
|
+
type: "agent:tool_input_update",
|
|
45469
|
+
payload: {
|
|
45470
|
+
...wireBase(base),
|
|
45471
|
+
toolName: proc.currentToolName,
|
|
45472
|
+
input: liveInput
|
|
45473
|
+
}
|
|
45474
|
+
});
|
|
45475
|
+
}
|
|
45291
45476
|
}
|
|
45292
45477
|
} else if (delta.type === "text_delta" && typeof delta.text === "string") {
|
|
45293
45478
|
if (proc.accumulatedText.length === 0) {
|
|
@@ -45342,6 +45527,16 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45342
45527
|
if (lastToolUse && lastToolUse.type === "tool_use") {
|
|
45343
45528
|
lastToolUse.input = parsedInput;
|
|
45344
45529
|
}
|
|
45530
|
+
if (proc.currentToolName != null && LIVE_INPUT_PREVIEW_TOOLS.has(proc.currentToolName) && Object.keys(parsedInput).length > 0) {
|
|
45531
|
+
emit({
|
|
45532
|
+
type: "agent:tool_input_update",
|
|
45533
|
+
payload: {
|
|
45534
|
+
...wireBase(base),
|
|
45535
|
+
toolName: proc.currentToolName,
|
|
45536
|
+
input: parsedInput
|
|
45537
|
+
}
|
|
45538
|
+
});
|
|
45539
|
+
}
|
|
45345
45540
|
if (proc.currentToolName === "TodoWrite") {
|
|
45346
45541
|
const todos = extractTodosFromInput(parsedInput);
|
|
45347
45542
|
if (todos) {
|
|
@@ -45586,6 +45781,29 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45586
45781
|
onCompleted();
|
|
45587
45782
|
break;
|
|
45588
45783
|
}
|
|
45784
|
+
if (proc.accumulatedText.length === 0 && proc.contentBlocks.length === 0) {
|
|
45785
|
+
cleanupPlanMode(proc, emit, base, "error");
|
|
45786
|
+
logger7.warn("SDK success produced empty assistant output; emitting agent:error", {
|
|
45787
|
+
agentId: proc.agentId,
|
|
45788
|
+
ackId: base.replyMessageId,
|
|
45789
|
+
tokenCount: usage.tokenCount,
|
|
45790
|
+
inputTokens: usage.inputTokens,
|
|
45791
|
+
cacheReadTokens: usage.cacheReadTokens,
|
|
45792
|
+
cacheCreationTokens: usage.cacheCreationTokens,
|
|
45793
|
+
assistantContent: proc.lastAssistantContentDescription,
|
|
45794
|
+
traceId: base.traceId
|
|
45795
|
+
});
|
|
45796
|
+
emit({
|
|
45797
|
+
type: "agent:error",
|
|
45798
|
+
payload: {
|
|
45799
|
+
...wireBase(base),
|
|
45800
|
+
error: "Agent \u8FD4\u56DE\u4E86\u7A7A\u7ED3\u679C\uFF0C\u5DF2\u963B\u6B62\u7A7A\u6D88\u606F\u8986\u76D6\u601D\u8003\u6C14\u6CE1\u3002\u8BF7\u91CD\u8BD5\uFF1B\u5982\u679C\u53CD\u590D\u51FA\u73B0\uFF0C\u8BF7\u68C0\u67E5 Claude Code \u767B\u5F55\u72B6\u6001\u6216\u6A21\u578B\u914D\u7F6E\u3002"
|
|
45801
|
+
}
|
|
45802
|
+
});
|
|
45803
|
+
resetAccumulators(proc);
|
|
45804
|
+
onCompleted();
|
|
45805
|
+
break;
|
|
45806
|
+
}
|
|
45589
45807
|
if (proc.accumulatedText) {
|
|
45590
45808
|
proc.contentBlocks.push({ type: "text", content: proc.accumulatedText });
|
|
45591
45809
|
}
|
|
@@ -45655,14 +45873,9 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45655
45873
|
if (am2.isApiErrorMessage === true) {
|
|
45656
45874
|
const base = getTaskBase(proc);
|
|
45657
45875
|
if (!base) break;
|
|
45658
|
-
const errorTexts =
|
|
45659
|
-
for (const block of am2.message?.content ?? []) {
|
|
45660
|
-
if (block?.type === "text" && typeof block.text === "string") {
|
|
45661
|
-
errorTexts.push(block.text);
|
|
45662
|
-
}
|
|
45663
|
-
}
|
|
45876
|
+
const errorTexts = extractAssistantTextParts(am2.message?.content);
|
|
45664
45877
|
const errorText = errorTexts.join("\n").trim() || `SDK ${am2.error ?? "api_error"}`;
|
|
45665
|
-
const isAuthFail = am2.error
|
|
45878
|
+
const isAuthFail = isAuthFailureText(errorText, am2.error);
|
|
45666
45879
|
if (isAuthFail) {
|
|
45667
45880
|
sessionStore.delete(proc.agentId, proc.scope);
|
|
45668
45881
|
}
|
|
@@ -45674,7 +45887,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45674
45887
|
isAuthFail,
|
|
45675
45888
|
traceId: base.traceId
|
|
45676
45889
|
});
|
|
45677
|
-
const friendlyError = isAuthFail ?
|
|
45890
|
+
const friendlyError = isAuthFail ? buildAuthFailureMessage(errorText) : errorText;
|
|
45678
45891
|
emit({
|
|
45679
45892
|
type: "agent:error",
|
|
45680
45893
|
payload: { ...wireBase(base), error: friendlyError }
|
|
@@ -45687,14 +45900,36 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45687
45900
|
break;
|
|
45688
45901
|
}
|
|
45689
45902
|
if (proc.accumulatedText.length === 0 && proc.contentBlocks.length === 0) {
|
|
45690
|
-
const captured =
|
|
45691
|
-
for (const block of am2.message?.content ?? []) {
|
|
45692
|
-
if (block?.type === "text" && typeof block.text === "string") {
|
|
45693
|
-
captured.push(block.text);
|
|
45694
|
-
}
|
|
45695
|
-
}
|
|
45903
|
+
const captured = extractAssistantTextParts(am2.message?.content);
|
|
45696
45904
|
if (captured.length > 0) {
|
|
45697
45905
|
const text = captured.join("");
|
|
45906
|
+
if (isAuthFailureText(text, am2.error)) {
|
|
45907
|
+
const base = getTaskBase(proc);
|
|
45908
|
+
logger7.warn("SDK auth failure assistant detected without api-error flag, emitting agent:error", {
|
|
45909
|
+
agentId: proc.agentId,
|
|
45910
|
+
scope: proc.scope.kind === "single" ? "single" : proc.scope.groupId,
|
|
45911
|
+
sdkError: am2.error,
|
|
45912
|
+
errorText: text.slice(0, 200),
|
|
45913
|
+
traceId: base?.traceId,
|
|
45914
|
+
hasCurrentTask: base != null
|
|
45915
|
+
});
|
|
45916
|
+
if (base) {
|
|
45917
|
+
sessionStore.delete(proc.agentId, proc.scope);
|
|
45918
|
+
emit({
|
|
45919
|
+
type: "agent:error",
|
|
45920
|
+
payload: {
|
|
45921
|
+
...wireBase(base),
|
|
45922
|
+
error: buildAuthFailureMessage(text)
|
|
45923
|
+
}
|
|
45924
|
+
});
|
|
45925
|
+
proc.apiErrorEmitted = true;
|
|
45926
|
+
}
|
|
45927
|
+
proc.contentBlocks = [];
|
|
45928
|
+
proc.accumulatedText = "";
|
|
45929
|
+
proc.accumulatedThinking = "";
|
|
45930
|
+
proc.segmentBuffer = "";
|
|
45931
|
+
break;
|
|
45932
|
+
}
|
|
45698
45933
|
if (isContextOverflowText(text)) {
|
|
45699
45934
|
const base = getTaskBase(proc);
|
|
45700
45935
|
logger7.warn("SDK reported context overflow; auto-compact already failed inside SDK", {
|
|
@@ -45738,6 +45973,8 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted) {
|
|
|
45738
45973
|
textLen: text.length,
|
|
45739
45974
|
textSample: text.slice(0, 100)
|
|
45740
45975
|
});
|
|
45976
|
+
} else {
|
|
45977
|
+
proc.lastAssistantContentDescription = describeAssistantContent(am2.message?.content);
|
|
45741
45978
|
}
|
|
45742
45979
|
}
|
|
45743
45980
|
break;
|
|
@@ -45761,6 +45998,7 @@ function resetAccumulators(proc) {
|
|
|
45761
45998
|
proc.accumulatedToolInput = "";
|
|
45762
45999
|
proc.apiErrorEmitted = false;
|
|
45763
46000
|
proc.peakContextUsage = void 0;
|
|
46001
|
+
proc.lastAssistantContentDescription = void 0;
|
|
45764
46002
|
}
|
|
45765
46003
|
|
|
45766
46004
|
// src/forkHistoryReplay.ts
|
|
@@ -45873,8 +46111,15 @@ var wsMetrics = new WsMetrics();
|
|
|
45873
46111
|
// src/agentManager.ts
|
|
45874
46112
|
var logger10 = createModuleLogger("agent.manager");
|
|
45875
46113
|
var NODE_USER_UID = 1e3;
|
|
46114
|
+
var POST_MERGE_CONTINUATION_ROUTE_MS = 15e3;
|
|
45876
46115
|
function isSmithAgent(agent) {
|
|
45877
|
-
|
|
46116
|
+
if (agent.id === SMITH_AGENT_ID) return true;
|
|
46117
|
+
if (agent.systemPrompt === SMITH_SYSTEM_PROMPT) return true;
|
|
46118
|
+
const prompt = agent.systemPrompt ?? "";
|
|
46119
|
+
if (prompt.includes("\u4F60\u662F\u7279\u5DE5\u53F2\u5BC6\u65AF") && prompt.includes("create_agent")) return true;
|
|
46120
|
+
const name = agent.name?.toLowerCase() ?? "";
|
|
46121
|
+
const role = agent.role?.toLowerCase() ?? "";
|
|
46122
|
+
return role === "system" && (name.includes("\u53F2\u5BC6\u65AF") || name.includes("smith"));
|
|
45878
46123
|
}
|
|
45879
46124
|
function isRunningAsRoot() {
|
|
45880
46125
|
try {
|
|
@@ -45883,6 +46128,13 @@ function isRunningAsRoot() {
|
|
|
45883
46128
|
return false;
|
|
45884
46129
|
}
|
|
45885
46130
|
}
|
|
46131
|
+
async function chownForRootSpawn(targetPath, target) {
|
|
46132
|
+
try {
|
|
46133
|
+
await fs4.chown(targetPath, NODE_USER_UID, NODE_USER_UID);
|
|
46134
|
+
} catch (error51) {
|
|
46135
|
+
logger10.error("Best-effort root chown failed", { error: error51, target, path: targetPath });
|
|
46136
|
+
}
|
|
46137
|
+
}
|
|
45886
46138
|
function readCronLockSnapshot() {
|
|
45887
46139
|
try {
|
|
45888
46140
|
const lockPath2 = path8.join(os5.homedir(), ".claude", "scheduled_tasks.lock");
|
|
@@ -46631,19 +46883,10 @@ Do NOT use "..." as content \u2014 write specific, project-relevant content.`;
|
|
|
46631
46883
|
options.resume = savedSessionId;
|
|
46632
46884
|
}
|
|
46633
46885
|
if (isRunningAsRoot()) {
|
|
46634
|
-
|
|
46635
|
-
|
|
46636
|
-
} catch {
|
|
46637
|
-
}
|
|
46638
|
-
try {
|
|
46639
|
-
await fs4.chown(agentCwd, NODE_USER_UID, NODE_USER_UID);
|
|
46640
|
-
} catch {
|
|
46641
|
-
}
|
|
46886
|
+
await chownForRootSpawn(effectiveConfigDir, "configDir");
|
|
46887
|
+
await chownForRootSpawn(agentCwd, "agentCwd");
|
|
46642
46888
|
const settingsFilePath = path8.join(effectiveConfigDir, "settings.json");
|
|
46643
|
-
|
|
46644
|
-
await fs4.chown(settingsFilePath, NODE_USER_UID, NODE_USER_UID);
|
|
46645
|
-
} catch {
|
|
46646
|
-
}
|
|
46889
|
+
await chownForRootSpawn(settingsFilePath, "settingsFile");
|
|
46647
46890
|
options.spawnClaudeCodeProcess = (spawnOptions) => {
|
|
46648
46891
|
const env2 = { ...spawnOptions.env, HOME: "/home/node" };
|
|
46649
46892
|
return nodeSpawn(spawnOptions.command, spawnOptions.args, {
|
|
@@ -46809,7 +47052,7 @@ ${trimmed}`;
|
|
|
46809
47052
|
lines.push(` workdir: ${currentCwd}`);
|
|
46810
47053
|
} else {
|
|
46811
47054
|
const a = this.agentRegistry?.getById(agentId);
|
|
46812
|
-
const singleCwd = a?.workingDirectory || path8.join(
|
|
47055
|
+
const singleCwd = a?.workingDirectory || path8.join(this.workspacesDir, agentId);
|
|
46813
47056
|
lines.push(` workdir: ${singleCwd}`);
|
|
46814
47057
|
}
|
|
46815
47058
|
let rosterCount = 0;
|
|
@@ -46821,7 +47064,7 @@ ${trimmed}`;
|
|
|
46821
47064
|
if (key === curKey) {
|
|
46822
47065
|
lines.push(` workdir: ${currentCwd}`);
|
|
46823
47066
|
} else {
|
|
46824
|
-
const groupCwd =
|
|
47067
|
+
const groupCwd = g2.workingDirectory || path8.join(this.workspacesDir, g2.groupId);
|
|
46825
47068
|
lines.push(` workdir: ${groupCwd}`);
|
|
46826
47069
|
}
|
|
46827
47070
|
const others = g2.members.filter((id) => id !== agentId).map((id) => {
|
|
@@ -47168,6 +47411,16 @@ ${lines.join("\n")}`;
|
|
|
47168
47411
|
}
|
|
47169
47412
|
}
|
|
47170
47413
|
async dispatchToSDK(runtime, task) {
|
|
47414
|
+
if (runtime.postMergeContinuationTask) {
|
|
47415
|
+
logger10.info("Clearing stale post-merge continuation route before explicit dispatch", {
|
|
47416
|
+
agentId: runtime.agentId,
|
|
47417
|
+
staleReplyMessageId: runtime.postMergeContinuationTask.replyMessageId,
|
|
47418
|
+
nextReplyMessageId: task.replyMessageId,
|
|
47419
|
+
traceId: task.traceId
|
|
47420
|
+
});
|
|
47421
|
+
delete runtime.postMergeContinuationTask;
|
|
47422
|
+
delete runtime.postMergeContinuationUntil;
|
|
47423
|
+
}
|
|
47171
47424
|
await this.applyEffortMode(runtime, "high", {
|
|
47172
47425
|
source: "dispatchToSDK",
|
|
47173
47426
|
replyMessageId: task.replyMessageId
|
|
@@ -47376,6 +47629,19 @@ ${lines.join("\n")}`;
|
|
|
47376
47629
|
}
|
|
47377
47630
|
});
|
|
47378
47631
|
}
|
|
47632
|
+
const continuationTask = mergedBatch.at(-1);
|
|
47633
|
+
if (continuationTask) {
|
|
47634
|
+
proc.postMergeContinuationTask = continuationTask;
|
|
47635
|
+
proc.postMergeContinuationUntil = Date.now() + POST_MERGE_CONTINUATION_ROUTE_MS;
|
|
47636
|
+
logger10.info("Armed SDK post-merge continuation routing", {
|
|
47637
|
+
agentId: proc.agentId,
|
|
47638
|
+
carrierReplyMessageId: completedTask.replyMessageId,
|
|
47639
|
+
continuationReplyMessageId: continuationTask.replyMessageId,
|
|
47640
|
+
mergedCount: mergedBatch.length,
|
|
47641
|
+
routeUntil: new Date(proc.postMergeContinuationUntil).toISOString(),
|
|
47642
|
+
traceId: completedTask.traceId
|
|
47643
|
+
});
|
|
47644
|
+
}
|
|
47379
47645
|
runtime.mergedTasks = [];
|
|
47380
47646
|
} else if (runtime.mergedTasks.length > 0) {
|
|
47381
47647
|
logger10.warn("mergedTasks non-empty but no currentTask; dropping", {
|
|
@@ -50665,6 +50931,7 @@ Bridge token (register this machine at Settings \u2192 \u5DF2\u8FDE\u63A5\u7684\
|
|
|
50665
50931
|
agentRegistry,
|
|
50666
50932
|
subscriptionRegistry,
|
|
50667
50933
|
serverApiUrl: config2.serverApiUrl,
|
|
50934
|
+
bridgeToken: config2.bridgeToken,
|
|
50668
50935
|
dataDir: config2.dataDir
|
|
50669
50936
|
});
|
|
50670
50937
|
const taskDispatchHandler = createTaskDispatchHandler(agentManager, agentRegistry, emit);
|