@fangyb/ahchat-bridge 0.1.35 → 0.1.36
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 +961 -180
- package/dist/feedbackWorkerCli.cjs +165 -8
- package/dist/index.js +956 -180
- package/dist/seedanceMcpCli.cjs +53 -7
- package/dist/seedreamMcpCli.cjs +53 -7
- package/package.json +3 -2
package/dist/cli.cjs
CHANGED
|
@@ -91836,6 +91836,8 @@ var DEFAULT_QUERY_CONFIG = {
|
|
|
91836
91836
|
maxActive: 5040,
|
|
91837
91837
|
idleTimeoutMs: 6e5,
|
|
91838
91838
|
workingSilenceTimeoutMs: 12e5,
|
|
91839
|
+
replyStallTimeoutMs: 3e5,
|
|
91840
|
+
busySilenceTimeoutMs: 18e5,
|
|
91839
91841
|
evictionIntervalMs: 6e4,
|
|
91840
91842
|
statusReportIntervalMs: 6e4,
|
|
91841
91843
|
allowBuiltinWebSearch: false,
|
|
@@ -91893,6 +91895,14 @@ function mergeQueryConfig(file2) {
|
|
|
91893
91895
|
"AHCHAT_BRIDGE_WORKING_SILENCE_TIMEOUT_MS",
|
|
91894
91896
|
q?.workingSilenceTimeoutMs ?? DEFAULT_QUERY_CONFIG.workingSilenceTimeoutMs
|
|
91895
91897
|
),
|
|
91898
|
+
replyStallTimeoutMs: readEnvInt(
|
|
91899
|
+
"AHCHAT_BRIDGE_REPLY_STALL_TIMEOUT_MS",
|
|
91900
|
+
q?.replyStallTimeoutMs ?? DEFAULT_QUERY_CONFIG.replyStallTimeoutMs
|
|
91901
|
+
),
|
|
91902
|
+
busySilenceTimeoutMs: readEnvInt(
|
|
91903
|
+
"AHCHAT_BRIDGE_BUSY_SILENCE_TIMEOUT_MS",
|
|
91904
|
+
q?.busySilenceTimeoutMs ?? DEFAULT_QUERY_CONFIG.busySilenceTimeoutMs ?? 18e5
|
|
91905
|
+
),
|
|
91896
91906
|
evictionIntervalMs: readEnvInt(
|
|
91897
91907
|
"AHCHAT_BRIDGE_EVICTION_INTERVAL_MS",
|
|
91898
91908
|
q?.evictionIntervalMs ?? DEFAULT_QUERY_CONFIG.evictionIntervalMs
|
|
@@ -91973,7 +91983,11 @@ function loadBridgeConfig(opts) {
|
|
|
91973
91983
|
) || null,
|
|
91974
91984
|
logUploadIntervalMs: readEnvInt(
|
|
91975
91985
|
"AHCHAT_LOG_UPLOAD_INTERVAL_MS",
|
|
91976
|
-
|
|
91986
|
+
// Flush every 60s instead of once a day. Daily flushing let logs pile up for hours,
|
|
91987
|
+
// then dumped tens of thousands of entries in one cycle on the next process start,
|
|
91988
|
+
// blowing past the server's per-minute upload quota (3000 entries / 3MB) and getting
|
|
91989
|
+
// 429'd. Small frequent batches stay well under that ceiling.
|
|
91990
|
+
fileConfig.logUploadIntervalMs ?? 6e4
|
|
91977
91991
|
),
|
|
91978
91992
|
queryConfig: mergeQueryConfig(fileConfig)
|
|
91979
91993
|
};
|
|
@@ -92709,9 +92723,34 @@ ${entry.error.stack}` : ""}`
|
|
|
92709
92723
|
return `${ts} ${level} ${scope} ${entry.msg}${data}${trace}${errPart}`;
|
|
92710
92724
|
};
|
|
92711
92725
|
|
|
92726
|
+
// ../logger/src/fallback.ts
|
|
92727
|
+
init_cjs_shims();
|
|
92728
|
+
function logFallback(logger45, event) {
|
|
92729
|
+
const payload = {
|
|
92730
|
+
...event.traceId ? { traceId: event.traceId } : {},
|
|
92731
|
+
fallback: {
|
|
92732
|
+
fallbackId: event.fallbackId,
|
|
92733
|
+
type: event.type,
|
|
92734
|
+
phase: event.phase,
|
|
92735
|
+
expected: event.expected,
|
|
92736
|
+
...event.context ? { context: event.context } : {},
|
|
92737
|
+
...event.outcome ? { outcome: event.outcome } : {}
|
|
92738
|
+
}
|
|
92739
|
+
};
|
|
92740
|
+
const msg = `[FALLBACK] ${event.type}:${event.phase}`;
|
|
92741
|
+
const useDebug = event.expected && event.phase !== "outcome";
|
|
92742
|
+
if (useDebug) {
|
|
92743
|
+
logger45.debug(msg, payload);
|
|
92744
|
+
} else {
|
|
92745
|
+
logger45.warn(msg, payload);
|
|
92746
|
+
}
|
|
92747
|
+
}
|
|
92748
|
+
|
|
92712
92749
|
// ../logger/src/transports/console.ts
|
|
92713
92750
|
init_cjs_shims();
|
|
92714
92751
|
var protectedStreams = /* @__PURE__ */ new WeakSet();
|
|
92752
|
+
function ignoreWriteError(_error) {
|
|
92753
|
+
}
|
|
92715
92754
|
function defaultStream(kind) {
|
|
92716
92755
|
const maybeGlobal = globalThis;
|
|
92717
92756
|
return maybeGlobal.process?.[kind];
|
|
@@ -92724,12 +92763,13 @@ function safeWriteLine(stream, line, fallback) {
|
|
|
92724
92763
|
if (stream.destroyed || stream.writableEnded) return;
|
|
92725
92764
|
if (typeof stream === "object" && typeof stream.on === "function" && !protectedStreams.has(stream)) {
|
|
92726
92765
|
protectedStreams.add(stream);
|
|
92727
|
-
stream.on("error",
|
|
92766
|
+
stream.on("error", ignoreWriteError);
|
|
92728
92767
|
}
|
|
92729
92768
|
try {
|
|
92730
92769
|
stream.write(`${line}
|
|
92731
|
-
`,
|
|
92732
|
-
} catch {
|
|
92770
|
+
`, ignoreWriteError);
|
|
92771
|
+
} catch (e) {
|
|
92772
|
+
ignoreWriteError(e);
|
|
92733
92773
|
}
|
|
92734
92774
|
}
|
|
92735
92775
|
function consoleTransport(opts) {
|
|
@@ -93364,8 +93404,31 @@ function parseSize(maxSize) {
|
|
|
93364
93404
|
return trimmed;
|
|
93365
93405
|
}
|
|
93366
93406
|
var streamCache = /* @__PURE__ */ new Map();
|
|
93407
|
+
var droppedEntryCount = 0;
|
|
93408
|
+
var lastReportedDroppedTotal = 0;
|
|
93409
|
+
function buildLogDroppedSentinel(fmt, source, droppedTotal) {
|
|
93410
|
+
const entry = {
|
|
93411
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
93412
|
+
level: "WARN",
|
|
93413
|
+
source,
|
|
93414
|
+
module: "logger.file",
|
|
93415
|
+
msg: "log_dropped",
|
|
93416
|
+
data: { droppedTotal }
|
|
93417
|
+
};
|
|
93418
|
+
return fmt(entry);
|
|
93419
|
+
}
|
|
93420
|
+
function writeWithDroppedSentinel(stream, fmt, line, source) {
|
|
93421
|
+
stream.write(`${line}
|
|
93422
|
+
`);
|
|
93423
|
+
if (droppedEntryCount > lastReportedDroppedTotal) {
|
|
93424
|
+
lastReportedDroppedTotal = droppedEntryCount;
|
|
93425
|
+
stream.write(`${buildLogDroppedSentinel(fmt, source, droppedEntryCount)}
|
|
93426
|
+
`);
|
|
93427
|
+
}
|
|
93428
|
+
}
|
|
93367
93429
|
function fileTransport(opts) {
|
|
93368
93430
|
const fmt = opts.formatter ?? jsonFormatter;
|
|
93431
|
+
const logSource = opts.source ?? "server";
|
|
93369
93432
|
const resolved = import_node_path2.default.resolve(opts.path);
|
|
93370
93433
|
let cached2 = streamCache.get(resolved);
|
|
93371
93434
|
if (!cached2) {
|
|
@@ -93380,11 +93443,14 @@ function fileTransport(opts) {
|
|
|
93380
93443
|
streamCache.set(resolved, cached2);
|
|
93381
93444
|
}
|
|
93382
93445
|
return (entry) => {
|
|
93383
|
-
if (cached2.closed || cached2.stream.destroyed || cached2.stream.writableEnded)
|
|
93446
|
+
if (cached2.closed || cached2.stream.destroyed || cached2.stream.writableEnded) {
|
|
93447
|
+
droppedEntryCount += 1;
|
|
93448
|
+
return;
|
|
93449
|
+
}
|
|
93384
93450
|
try {
|
|
93385
|
-
cached2.stream
|
|
93386
|
-
`);
|
|
93451
|
+
writeWithDroppedSentinel(cached2.stream, fmt, fmt(entry), logSource);
|
|
93387
93452
|
} catch {
|
|
93453
|
+
droppedEntryCount += 1;
|
|
93388
93454
|
}
|
|
93389
93455
|
};
|
|
93390
93456
|
}
|
|
@@ -93770,8 +93836,10 @@ function resolvePnpmRuntimeBinary(sdkDir, target) {
|
|
|
93770
93836
|
} catch {
|
|
93771
93837
|
return void 0;
|
|
93772
93838
|
}
|
|
93839
|
+
const matches = [];
|
|
93773
93840
|
for (const entry of entries) {
|
|
93774
93841
|
if (!entry.startsWith(`${encodedName}@`)) continue;
|
|
93842
|
+
const version4 = entry.slice(encodedName.length + 1);
|
|
93775
93843
|
const candidate = import_node_path5.default.join(
|
|
93776
93844
|
pnpmStoreDir,
|
|
93777
93845
|
entry,
|
|
@@ -93779,9 +93847,22 @@ function resolvePnpmRuntimeBinary(sdkDir, target) {
|
|
|
93779
93847
|
...target.packageName.split("/"),
|
|
93780
93848
|
target.binaryName
|
|
93781
93849
|
);
|
|
93782
|
-
if ((0, import_node_fs3.existsSync)(candidate))
|
|
93850
|
+
if ((0, import_node_fs3.existsSync)(candidate)) matches.push({ version: version4, candidate });
|
|
93783
93851
|
}
|
|
93784
|
-
return void 0;
|
|
93852
|
+
if (matches.length === 0) return void 0;
|
|
93853
|
+
matches.sort((a, b) => compareRuntimeVersion(b.version, a.version));
|
|
93854
|
+
return matches[0].candidate;
|
|
93855
|
+
}
|
|
93856
|
+
function compareRuntimeVersion(a, b) {
|
|
93857
|
+
const parse3 = (v) => v.split(/[.+_-]/).map((n) => Number.parseInt(n, 10));
|
|
93858
|
+
const pa = parse3(a);
|
|
93859
|
+
const pb = parse3(b);
|
|
93860
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i += 1) {
|
|
93861
|
+
const da = Number.isFinite(pa[i]) ? pa[i] : 0;
|
|
93862
|
+
const db = Number.isFinite(pb[i]) ? pb[i] : 0;
|
|
93863
|
+
if (da !== db) return da - db;
|
|
93864
|
+
}
|
|
93865
|
+
return 0;
|
|
93785
93866
|
}
|
|
93786
93867
|
function resolveSdkRuntimeBinary(target) {
|
|
93787
93868
|
const directPath = safeResolve(`${target.packageName}/${target.binaryName}`);
|
|
@@ -94683,6 +94764,9 @@ function createMessageId() {
|
|
|
94683
94764
|
function createTraceId() {
|
|
94684
94765
|
return `tr_${Date.now().toString(36)}_${nanoid(6)}`;
|
|
94685
94766
|
}
|
|
94767
|
+
function createFallbackId() {
|
|
94768
|
+
return `flb_${Date.now().toString(36)}_${nanoid(6)}`;
|
|
94769
|
+
}
|
|
94686
94770
|
function createRequestId() {
|
|
94687
94771
|
return `req_${Date.now().toString(36)}_${nanoid(6)}`;
|
|
94688
94772
|
}
|
|
@@ -94692,6 +94776,12 @@ function createCronReplyMessageId() {
|
|
|
94692
94776
|
function createInboxFlushReplyMessageId() {
|
|
94693
94777
|
return `msg_inbox_${Date.now().toString(36)}_${nanoid(6)}`;
|
|
94694
94778
|
}
|
|
94779
|
+
function createNeuralSendReplyMessageId() {
|
|
94780
|
+
return `msg_nsend_${Date.now().toString(36)}_${nanoid(6)}`;
|
|
94781
|
+
}
|
|
94782
|
+
function createScopeNoticeReplyMessageId() {
|
|
94783
|
+
return `msg_scopenotice_${Date.now().toString(36)}_${nanoid(6)}`;
|
|
94784
|
+
}
|
|
94695
94785
|
function createCronTraceId() {
|
|
94696
94786
|
return `tr_cron_${Date.now().toString(36)}_${nanoid(6)}`;
|
|
94697
94787
|
}
|
|
@@ -94750,6 +94840,10 @@ function assertStringPayloadOneOf(type, payload, field, allowed) {
|
|
|
94750
94840
|
throw invalidWsMessage(type, field);
|
|
94751
94841
|
}
|
|
94752
94842
|
}
|
|
94843
|
+
function assertOptionalStringPayloadOneOf(type, payload, field, allowed) {
|
|
94844
|
+
if (payload[field] === void 0) return;
|
|
94845
|
+
assertStringPayloadOneOf(type, payload, field, allowed);
|
|
94846
|
+
}
|
|
94753
94847
|
function assertArrayPayloadField(type, payload, field) {
|
|
94754
94848
|
if (!Array.isArray(payload[field])) {
|
|
94755
94849
|
throw invalidWsMessage(type, field);
|
|
@@ -94830,6 +94924,7 @@ function validateWSMessageShape(msg) {
|
|
|
94830
94924
|
case "agent:error": {
|
|
94831
94925
|
assertPayloadRecord(type, payload);
|
|
94832
94926
|
validateRequiredStrings(type, payload, ["ackId", "agentId", "conversationId", "error", "traceId"]);
|
|
94927
|
+
assertOptionalStringPayloadOneOf(type, payload, "reason", ["user_quota_exceeded", "company_quota_exceeded"]);
|
|
94833
94928
|
return;
|
|
94834
94929
|
}
|
|
94835
94930
|
case "directory:register": {
|
|
@@ -96209,6 +96304,9 @@ init_cjs_shims();
|
|
|
96209
96304
|
// ../shared/src/utils/serverUrl.ts
|
|
96210
96305
|
init_cjs_shims();
|
|
96211
96306
|
|
|
96307
|
+
// ../shared/src/utils/phone.ts
|
|
96308
|
+
init_cjs_shims();
|
|
96309
|
+
|
|
96212
96310
|
// ../shared/src/utils/mediaPreviewHtml.ts
|
|
96213
96311
|
init_cjs_shims();
|
|
96214
96312
|
|
|
@@ -96454,6 +96552,60 @@ var readpageScrapeTool = {
|
|
|
96454
96552
|
enabled: true,
|
|
96455
96553
|
permissionPolicy: "always_allow"
|
|
96456
96554
|
};
|
|
96555
|
+
var seedreamGenerateImageTool = {
|
|
96556
|
+
name: "generate_image",
|
|
96557
|
+
displayName: "Seedream \u751F\u56FE",
|
|
96558
|
+
description: "\u4F7F\u7528\u706B\u5C71\u65B9\u821F Seedream \u751F\u6210\u5355\u5F20\u56FE\u7247\uFF0C\u652F\u6301\u6587\u672C\u751F\u56FE\u4E0E\u53C2\u8003\u56FE\u751F\u56FE\uFF0C\u4F1A\u4EA7\u751F\u516C\u53F8 Ark \u8D26\u53F7\u7528\u91CF\u3002",
|
|
96559
|
+
category: "media",
|
|
96560
|
+
riskLevel: "medium",
|
|
96561
|
+
enabled: true,
|
|
96562
|
+
permissionPolicy: "always_ask"
|
|
96563
|
+
};
|
|
96564
|
+
var seedreamEditImageTool = {
|
|
96565
|
+
name: "edit_image",
|
|
96566
|
+
displayName: "Seedream \u6539\u56FE",
|
|
96567
|
+
description: "\u4F7F\u7528\u706B\u5C71\u65B9\u821F Seedream \u6839\u636E\u53C2\u8003\u56FE\u548C\u63D0\u793A\u8BCD\u7F16\u8F91\u6216\u91CD\u7ED8\u5355\u5F20\u56FE\u7247\uFF0C\u4F1A\u4EA7\u751F\u516C\u53F8 Ark \u8D26\u53F7\u7528\u91CF\u3002",
|
|
96568
|
+
category: "media",
|
|
96569
|
+
riskLevel: "medium",
|
|
96570
|
+
enabled: true,
|
|
96571
|
+
permissionPolicy: "always_ask"
|
|
96572
|
+
};
|
|
96573
|
+
var seedreamGenerateImageGroupTool = {
|
|
96574
|
+
name: "generate_image_group",
|
|
96575
|
+
displayName: "Seedream \u5355\u56FE",
|
|
96576
|
+
description: "\u517C\u5BB9\u65E7\u540D\u79F0\u7684 Seedream \u5355\u56FE\u751F\u6210\u5DE5\u5177\uFF0C\u4F1A\u4EA7\u751F\u516C\u53F8 Ark \u8D26\u53F7\u7528\u91CF\u3002\u5F53\u524D\u6BCF\u6B21\u8BF7\u6C42\u53EA\u751F\u6210 1 \u5F20\u56FE\u7247\u3002",
|
|
96577
|
+
category: "media",
|
|
96578
|
+
riskLevel: "medium",
|
|
96579
|
+
enabled: true,
|
|
96580
|
+
permissionPolicy: "always_ask"
|
|
96581
|
+
};
|
|
96582
|
+
var seedanceUsageGuideTool = {
|
|
96583
|
+
name: "seedance_usage_guide",
|
|
96584
|
+
displayName: "Seedance \u4F7F\u7528\u8BF4\u660E",
|
|
96585
|
+
description: "\u67E5\u770B Seedance \u89C6\u9891\u751F\u6210\u6D41\u7A0B\u4E0E\u53C2\u6570\u8BF4\u660E\uFF0C\u4E0D\u521B\u5EFA\u65B0\u7684\u751F\u6210\u4EFB\u52A1\u3002",
|
|
96586
|
+
category: "media",
|
|
96587
|
+
riskLevel: "low",
|
|
96588
|
+
enabled: true,
|
|
96589
|
+
permissionPolicy: "always_allow"
|
|
96590
|
+
};
|
|
96591
|
+
var seedanceCreateTaskTool = {
|
|
96592
|
+
name: "seedance_create_task",
|
|
96593
|
+
displayName: "Seedance \u751F\u89C6\u9891",
|
|
96594
|
+
description: "\u4F7F\u7528\u706B\u5C71\u65B9\u821F Seedance \u521B\u5EFA\u5355\u4E2A\u89C6\u9891\u751F\u6210\u4EFB\u52A1\uFF0C\u4F1A\u4EA7\u751F\u516C\u53F8 Ark \u8D26\u53F7\u7528\u91CF\u3002\u5F53\u524D\u6BCF\u6B21\u8BF7\u6C42\u53EA\u751F\u6210 1 \u4E2A\u89C6\u9891\u3002",
|
|
96595
|
+
category: "media",
|
|
96596
|
+
riskLevel: "high",
|
|
96597
|
+
enabled: true,
|
|
96598
|
+
permissionPolicy: "always_ask"
|
|
96599
|
+
};
|
|
96600
|
+
var seedanceCheckTaskTool = {
|
|
96601
|
+
name: "seedance_check_task",
|
|
96602
|
+
displayName: "Seedance \u67E5\u7ED3\u679C",
|
|
96603
|
+
description: "\u67E5\u8BE2 Seedance \u89C6\u9891\u751F\u6210\u4EFB\u52A1\u72B6\u6001\u4E0E\u89C6\u9891 URL\uFF0C\u4E0D\u521B\u5EFA\u65B0\u7684\u751F\u6210\u4EFB\u52A1\u3002",
|
|
96604
|
+
category: "media",
|
|
96605
|
+
riskLevel: "low",
|
|
96606
|
+
enabled: true,
|
|
96607
|
+
permissionPolicy: "always_allow"
|
|
96608
|
+
};
|
|
96457
96609
|
var context7ResolveLibraryTool = {
|
|
96458
96610
|
name: "resolve-library-id",
|
|
96459
96611
|
displayName: "\u89E3\u6790\u6587\u6863\u5E93",
|
|
@@ -96760,8 +96912,56 @@ var ALIYUN_IQS_MCP_PROVIDERS = [
|
|
|
96760
96912
|
tools: [readpageBasicTool, readpageScrapeTool]
|
|
96761
96913
|
}
|
|
96762
96914
|
];
|
|
96915
|
+
var VOLCENGINE_SEEDREAM_MCP_PROVIDER = {
|
|
96916
|
+
providerId: "volcengine_seedream",
|
|
96917
|
+
name: "Volcengine Seedream",
|
|
96918
|
+
summary: "\u706B\u5C71\u65B9\u821F Seedream \u56FE\u7247\u751F\u6210/\u7F16\u8F91 MCP\uFF0C\u4F7F\u7528\u516C\u53F8\u7EDF\u4E00 Ark Key\uFF0C\u5E76\u8FDB\u5165 AHChat \u8C03\u7528\u5BA1\u8BA1\u3002",
|
|
96919
|
+
serverName: "seedream",
|
|
96920
|
+
transport: "stdio",
|
|
96921
|
+
url: null,
|
|
96922
|
+
command: "ahchat-builtin",
|
|
96923
|
+
args: ["seedream-mcp"],
|
|
96924
|
+
env: {
|
|
96925
|
+
ARK_API_KEY: "",
|
|
96926
|
+
ARK_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3"
|
|
96927
|
+
},
|
|
96928
|
+
authType: "x_api_key",
|
|
96929
|
+
customHeaders: [],
|
|
96930
|
+
enabled: true,
|
|
96931
|
+
alwaysLoad: true,
|
|
96932
|
+
tools: [
|
|
96933
|
+
seedreamGenerateImageTool,
|
|
96934
|
+
seedreamEditImageTool,
|
|
96935
|
+
seedreamGenerateImageGroupTool
|
|
96936
|
+
]
|
|
96937
|
+
};
|
|
96938
|
+
var VOLCENGINE_SEEDANCE_MCP_PROVIDER = {
|
|
96939
|
+
providerId: "volcengine_seedance",
|
|
96940
|
+
name: "Volcengine Seedance",
|
|
96941
|
+
summary: "\u706B\u5C71\u65B9\u821F Seedance \u89C6\u9891\u751F\u6210 MCP\uFF0C\u4F7F\u7528\u516C\u53F8\u7EDF\u4E00 Ark Key\uFF0C\u5E76\u8FDB\u5165 AHChat \u8C03\u7528\u5BA1\u8BA1\u3002",
|
|
96942
|
+
serverName: "seedance",
|
|
96943
|
+
transport: "stdio",
|
|
96944
|
+
url: null,
|
|
96945
|
+
command: "ahchat-builtin",
|
|
96946
|
+
args: ["seedance-mcp"],
|
|
96947
|
+
env: {
|
|
96948
|
+
ARK_API_KEY: "",
|
|
96949
|
+
ARK_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3"
|
|
96950
|
+
},
|
|
96951
|
+
authType: "x_api_key",
|
|
96952
|
+
customHeaders: [],
|
|
96953
|
+
enabled: true,
|
|
96954
|
+
alwaysLoad: true,
|
|
96955
|
+
tools: [
|
|
96956
|
+
seedanceUsageGuideTool,
|
|
96957
|
+
seedanceCreateTaskTool,
|
|
96958
|
+
seedanceCheckTaskTool
|
|
96959
|
+
]
|
|
96960
|
+
};
|
|
96763
96961
|
var OFFICIAL_MCP_PROVIDERS = [
|
|
96764
|
-
...ALIYUN_IQS_MCP_PROVIDERS
|
|
96962
|
+
...ALIYUN_IQS_MCP_PROVIDERS,
|
|
96963
|
+
VOLCENGINE_SEEDREAM_MCP_PROVIDER,
|
|
96964
|
+
VOLCENGINE_SEEDANCE_MCP_PROVIDER
|
|
96765
96965
|
];
|
|
96766
96966
|
var MCP_STORE_PROVIDERS = [
|
|
96767
96967
|
{
|
|
@@ -97573,8 +97773,7 @@ var AskQuestionRegistry = class {
|
|
|
97573
97773
|
questionId,
|
|
97574
97774
|
agentId: entry.agentId,
|
|
97575
97775
|
waitedMs: Date.now() - entry.askedAt,
|
|
97576
|
-
answerLen: answerText2.length
|
|
97577
|
-
answerSample: answerText2.slice(0, 200)
|
|
97776
|
+
answerLen: answerText2.length
|
|
97578
97777
|
});
|
|
97579
97778
|
entry.resolve(answerText2);
|
|
97580
97779
|
return true;
|
|
@@ -97719,7 +97918,7 @@ function makeAskUserQuestionGuard(deps) {
|
|
|
97719
97918
|
bundleIndex,
|
|
97720
97919
|
bundleSize,
|
|
97721
97920
|
replyMessageId: task.replyMessageId,
|
|
97722
|
-
|
|
97921
|
+
questionLen: q.question.length,
|
|
97723
97922
|
optionCount: options.length,
|
|
97724
97923
|
multiSelect,
|
|
97725
97924
|
traceId: task.traceId
|
|
@@ -97818,7 +98017,7 @@ function makeAskUserQuestionGuard(deps) {
|
|
|
97818
98017
|
bundleId,
|
|
97819
98018
|
bundleSize,
|
|
97820
98019
|
replyMessageId: task.replyMessageId,
|
|
97821
|
-
|
|
98020
|
+
combinedLen: combined.length,
|
|
97822
98021
|
traceId: task.traceId
|
|
97823
98022
|
});
|
|
97824
98023
|
return { behavior: "deny", message: combined };
|
|
@@ -112803,6 +113002,17 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
112803
113002
|
".yaml",
|
|
112804
113003
|
".yml"
|
|
112805
113004
|
]);
|
|
113005
|
+
var OFFICE_DOCUMENT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
113006
|
+
".docx",
|
|
113007
|
+
".xlsx",
|
|
113008
|
+
".pptx",
|
|
113009
|
+
".pdf",
|
|
113010
|
+
".odt",
|
|
113011
|
+
".ods",
|
|
113012
|
+
".odp",
|
|
113013
|
+
".rtf"
|
|
113014
|
+
]);
|
|
113015
|
+
var PLAIN_TEXT_BINARY_SNIFF_BYTES = 8192;
|
|
112806
113016
|
var DEFAULT_MAX_CHARS = 5e5;
|
|
112807
113017
|
var DEFAULT_TIMEOUT_MS = 45e3;
|
|
112808
113018
|
function isReadableDocumentPath(filePath) {
|
|
@@ -112822,9 +113032,6 @@ function resolveDocumentPath(inputPath, cwd) {
|
|
|
112822
113032
|
async function readDocumentAsMarkdown(inputPath, opts = {}) {
|
|
112823
113033
|
const resolvedPath = opts.cwd ? resolveDocumentPath(inputPath, opts.cwd) : import_node_path10.default.resolve(resolveUserPath(inputPath));
|
|
112824
113034
|
const ext = import_node_path10.default.extname(resolvedPath).toLowerCase();
|
|
112825
|
-
if (!isReadableDocumentPath(resolvedPath)) {
|
|
112826
|
-
throw new Error(`unsupported document type: ${ext || "(no extension)"}`);
|
|
112827
|
-
}
|
|
112828
113035
|
const stat3 = await import_promises2.default.stat(resolvedPath);
|
|
112829
113036
|
if (!stat3.isFile()) throw new Error("path is not a file");
|
|
112830
113037
|
const warnings = [];
|
|
@@ -112833,8 +113040,10 @@ async function readDocumentAsMarkdown(inputPath, opts = {}) {
|
|
|
112833
113040
|
markdown = await import_promises2.default.readFile(resolvedPath, "utf-8");
|
|
112834
113041
|
} else if (ext === ".xls") {
|
|
112835
113042
|
markdown = await convertLegacyExcelDocument(resolvedPath);
|
|
112836
|
-
} else {
|
|
113043
|
+
} else if (OFFICE_DOCUMENT_EXTENSIONS.has(ext)) {
|
|
112837
113044
|
markdown = await convertOfficeDocument(resolvedPath, opts.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
113045
|
+
} else {
|
|
113046
|
+
markdown = await readPlainTextDocument(resolvedPath, ext);
|
|
112838
113047
|
}
|
|
112839
113048
|
markdown = normalizeDocumentText(markdown);
|
|
112840
113049
|
const maxChars = opts.maxChars ?? DEFAULT_MAX_CHARS;
|
|
@@ -112973,6 +113182,14 @@ async function convertDocxWithOfficeCli(filePath, timeoutMs) {
|
|
|
112973
113182
|
});
|
|
112974
113183
|
return text;
|
|
112975
113184
|
}
|
|
113185
|
+
async function readPlainTextDocument(filePath, ext) {
|
|
113186
|
+
const buffer = await import_promises2.default.readFile(filePath);
|
|
113187
|
+
const sample = buffer.subarray(0, Math.min(buffer.length, PLAIN_TEXT_BINARY_SNIFF_BYTES));
|
|
113188
|
+
if (sample.includes(0)) {
|
|
113189
|
+
throw new Error(`unsupported document type: ${ext || "(no extension)"}`);
|
|
113190
|
+
}
|
|
113191
|
+
return buffer.toString("utf-8");
|
|
113192
|
+
}
|
|
112976
113193
|
async function convertLegacyExcelDocument(filePath) {
|
|
112977
113194
|
const XLSX2 = await Promise.resolve().then(() => (init_xlsx(), xlsx_exports));
|
|
112978
113195
|
const workbook = XLSX2.readFile(filePath, { cellDates: true });
|
|
@@ -113442,8 +113659,7 @@ async function createNeuralMcpServer(deps) {
|
|
|
113442
113659
|
agentId: deps.agentId,
|
|
113443
113660
|
fromScope: currentScopeKey,
|
|
113444
113661
|
rawTargetScope: args.target_scope,
|
|
113445
|
-
messageLen: args.message.length
|
|
113446
|
-
messageSample: args.message.slice(0, 120)
|
|
113662
|
+
messageLen: args.message.length
|
|
113447
113663
|
});
|
|
113448
113664
|
const trimmed = args.message.trim();
|
|
113449
113665
|
if (!trimmed) {
|
|
@@ -113537,7 +113753,7 @@ async function createNeuralMcpServer(deps) {
|
|
|
113537
113753
|
toScope: resolvedKey,
|
|
113538
113754
|
repeatsInWindow: sendHistory.length,
|
|
113539
113755
|
windowMs: NEURAL_DEDUP_WINDOW_MS,
|
|
113540
|
-
|
|
113756
|
+
messageLen: trimmed.length
|
|
113541
113757
|
});
|
|
113542
113758
|
return {
|
|
113543
113759
|
content: [{
|
|
@@ -113564,8 +113780,7 @@ async function createNeuralMcpServer(deps) {
|
|
|
113564
113780
|
agentId: deps.agentId,
|
|
113565
113781
|
fromScope: currentScopeKey,
|
|
113566
113782
|
toScope: resolvedKey,
|
|
113567
|
-
messageLen: trimmed.length
|
|
113568
|
-
messageSample: trimmed.slice(0, 120)
|
|
113783
|
+
messageLen: trimmed.length
|
|
113569
113784
|
});
|
|
113570
113785
|
return {
|
|
113571
113786
|
content: [{ type: "text", text: `[neural_send] \u5DF2\u9001\u8FBE\u5230\u300C${toLabel}\u300D(scope: ${resolvedKey})\u3002` }]
|
|
@@ -113922,6 +114137,7 @@ action="append" \u8FFD\u52A0\u65B0\u5185\u5BB9\uFF08\u6700\u5E38\u7528\uFF0Ccont
|
|
|
113922
114137
|
`Read a document from the current working directory and return extracted Markdown text.
|
|
113923
114138
|
Use this instead of the built-in Read tool for binary documents such as .docx, .xls, .xlsx, .pptx, .pdf, .odt, .ods, .odp, or .rtf.
|
|
113924
114139
|
Also supports text-like files such as .csv, .md, .txt, .json, .xml, .yaml, and .html.
|
|
114140
|
+
Plain-text and source/config files (e.g. .py, .ts, Makefile, Dockerfile, and other extension-less text files) are read as-is; only true binaries are rejected.
|
|
113925
114141
|
Pass either a relative path from the current working directory or an absolute path inside it.`,
|
|
113926
114142
|
{
|
|
113927
114143
|
path: external_exports.string().min(1).describe("Document path, relative to the current working directory or absolute inside it."),
|
|
@@ -116985,6 +117201,9 @@ function emitUsageReported(proc, emit, base, usage, messageId) {
|
|
|
116985
117201
|
function isGroupTask(proc) {
|
|
116986
117202
|
return proc.currentTask?.groupId != null;
|
|
116987
117203
|
}
|
|
117204
|
+
function shouldStreamInternals(proc) {
|
|
117205
|
+
return !isGroupTask(proc) || proc.spectating === true;
|
|
117206
|
+
}
|
|
116988
117207
|
function extractTodosFromInput(input) {
|
|
116989
117208
|
if (!input || typeof input !== "object") return null;
|
|
116990
117209
|
const raw = input.todos;
|
|
@@ -117116,7 +117335,6 @@ function emitGroupSegment(proc, emit, base, content, contentBlocks, isSilent = f
|
|
|
117116
117335
|
contentLen: content.length,
|
|
117117
117336
|
blockCount: contentBlocks.length,
|
|
117118
117337
|
blockTypes: contentBlocks.map((b) => b.type),
|
|
117119
|
-
contentSample: content.slice(0, 200),
|
|
117120
117338
|
traceId: base.traceId,
|
|
117121
117339
|
isAuditOnly: content.length === 0,
|
|
117122
117340
|
isSilent
|
|
@@ -117172,9 +117390,24 @@ function flushTextSegmentOnBlockStop(proc, emit, base) {
|
|
|
117172
117390
|
}
|
|
117173
117391
|
proc.segmentBuffer = "";
|
|
117174
117392
|
}
|
|
117393
|
+
function describeSdkEvent(message) {
|
|
117394
|
+
const rec = message;
|
|
117395
|
+
const str = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
|
|
117396
|
+
return {
|
|
117397
|
+
type: str(rec.type) ?? "unknown",
|
|
117398
|
+
subtype: str(rec.subtype),
|
|
117399
|
+
toolName: str(rec.last_tool_name),
|
|
117400
|
+
subagentType: str(rec.subagent_type),
|
|
117401
|
+
toolUseId: str(rec.tool_use_id),
|
|
117402
|
+
taskId: str(rec.task_id),
|
|
117403
|
+
at: Date.now()
|
|
117404
|
+
};
|
|
117405
|
+
}
|
|
117175
117406
|
function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProviderApiError) {
|
|
117176
117407
|
const emit = rawEmit;
|
|
117177
117408
|
proc.lastSdkEventAt = Date.now();
|
|
117409
|
+
proc.lastSdkEventInfo = describeSdkEvent(message);
|
|
117410
|
+
proc.stallWarned = false;
|
|
117178
117411
|
switch (message.type) {
|
|
117179
117412
|
case "system": {
|
|
117180
117413
|
const sysMsg = message;
|
|
@@ -117213,11 +117446,29 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117213
117446
|
sessionId: proc.ccSessionId
|
|
117214
117447
|
});
|
|
117215
117448
|
} else {
|
|
117449
|
+
const sysRec = sysMsg;
|
|
117450
|
+
const pick2 = (k) => typeof sysRec[k] === "string" || typeof sysRec[k] === "number" ? sysRec[k] : void 0;
|
|
117451
|
+
const descriptionLen = typeof sysRec.description === "string" ? sysRec.description.length : void 0;
|
|
117452
|
+
const subagentTaskId = typeof sysRec.task_id === "string" ? sysRec.task_id : void 0;
|
|
117453
|
+
if (subagentTaskId) {
|
|
117454
|
+
if (sysMsg.subtype === "task_started") {
|
|
117455
|
+
(proc.activeSubagentTaskIds ??= /* @__PURE__ */ new Set()).add(subagentTaskId);
|
|
117456
|
+
} else if (sysMsg.subtype === "task_notification") {
|
|
117457
|
+
proc.activeSubagentTaskIds?.delete(subagentTaskId);
|
|
117458
|
+
}
|
|
117459
|
+
}
|
|
117216
117460
|
logger11.info("SDK system subtype unhandled", {
|
|
117217
117461
|
agentId: proc.agentId,
|
|
117218
117462
|
scope: proc.scope.kind === "single" ? "single" : proc.scope.groupId,
|
|
117219
117463
|
subtype: sysMsg.subtype ?? "(none)",
|
|
117220
|
-
|
|
117464
|
+
taskId: pick2("task_id"),
|
|
117465
|
+
toolUseId: pick2("tool_use_id"),
|
|
117466
|
+
subagentType: pick2("subagent_type"),
|
|
117467
|
+
taskType: pick2("task_type"),
|
|
117468
|
+
lastToolName: pick2("last_tool_name"),
|
|
117469
|
+
hasDescription: descriptionLen != null,
|
|
117470
|
+
descriptionLen,
|
|
117471
|
+
keys: Object.keys(sysMsg).slice(0, 16)
|
|
117221
117472
|
});
|
|
117222
117473
|
}
|
|
117223
117474
|
break;
|
|
@@ -117243,13 +117494,14 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117243
117494
|
} else if (block.type === "tool_use") {
|
|
117244
117495
|
proc.currentBlockType = "tool_use";
|
|
117245
117496
|
proc.currentToolName = block.name ?? "unknown";
|
|
117497
|
+
proc.activeToolUseStartedAt = Date.now();
|
|
117246
117498
|
proc.accumulatedToolInput = "";
|
|
117247
117499
|
const toolName = block.name ?? "unknown";
|
|
117248
117500
|
proc.suppressCurrentToolUse = proc.officialMediaGenerationSatisfied === true && isOfficialMediaGenerationToolName(toolName);
|
|
117249
117501
|
const isMcpTool = parseMcpRuntimeToolName(toolName) != null;
|
|
117250
117502
|
proc.currentMcpInvocationId = isMcpTool ? createMcpToolInvocationId() : null;
|
|
117251
117503
|
proc.currentMcpInvocationStartedAt = isMcpTool ? (/* @__PURE__ */ new Date()).toISOString() : null;
|
|
117252
|
-
if (
|
|
117504
|
+
if (shouldStreamInternals(proc) && !proc.suppressCurrentToolUse && toolName !== "ExitPlanMode" && !isAskUserQuestionToolName(toolName)) {
|
|
117253
117505
|
emit({
|
|
117254
117506
|
type: "agent:tool_use",
|
|
117255
117507
|
payload: {
|
|
@@ -117274,7 +117526,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117274
117526
|
if (delta.type === "thinking_delta" && typeof delta.thinking === "string") {
|
|
117275
117527
|
if (proc.suppressCurrentThinking) break;
|
|
117276
117528
|
proc.accumulatedThinking += delta.thinking;
|
|
117277
|
-
if (
|
|
117529
|
+
if (shouldStreamInternals(proc)) {
|
|
117278
117530
|
emit({
|
|
117279
117531
|
type: "agent:thinking_chunk",
|
|
117280
117532
|
payload: { ...wireBase(base), chunk: delta.thinking }
|
|
@@ -117285,7 +117537,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117285
117537
|
if (typeof partial2 === "string") {
|
|
117286
117538
|
proc.accumulatedToolInput += partial2;
|
|
117287
117539
|
const liveInput = extractLiveToolInput(proc.currentToolName, proc.accumulatedToolInput);
|
|
117288
|
-
if (
|
|
117540
|
+
if (shouldStreamInternals(proc) && liveInput && proc.currentToolName != null) {
|
|
117289
117541
|
emit({
|
|
117290
117542
|
type: "agent:tool_input_update",
|
|
117291
117543
|
payload: {
|
|
@@ -117319,7 +117571,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117319
117571
|
}
|
|
117320
117572
|
case "content_block_stop": {
|
|
117321
117573
|
if (proc.currentBlockType === "thinking") {
|
|
117322
|
-
if (
|
|
117574
|
+
if (shouldStreamInternals(proc) && !proc.suppressCurrentThinking) {
|
|
117323
117575
|
emit({
|
|
117324
117576
|
type: "agent:thinking_done",
|
|
117325
117577
|
payload: wireBase(getTaskBase(proc))
|
|
@@ -117344,8 +117596,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117344
117596
|
error: error51,
|
|
117345
117597
|
agentId: proc.agentId,
|
|
117346
117598
|
toolName: proc.currentToolName,
|
|
117347
|
-
inputLen: proc.accumulatedToolInput.length
|
|
117348
|
-
sample: proc.accumulatedToolInput.slice(0, 200)
|
|
117599
|
+
inputLen: proc.accumulatedToolInput.length
|
|
117349
117600
|
});
|
|
117350
117601
|
}
|
|
117351
117602
|
}
|
|
@@ -117354,7 +117605,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117354
117605
|
if (lastToolUse && lastToolUse.type === "tool_use") {
|
|
117355
117606
|
lastToolUse.input = parsedInput;
|
|
117356
117607
|
}
|
|
117357
|
-
if (
|
|
117608
|
+
if (shouldStreamInternals(proc) && proc.currentToolName != null && LIVE_INPUT_PREVIEW_TOOLS.has(proc.currentToolName) && Object.keys(parsedInput).length > 0) {
|
|
117358
117609
|
emit({
|
|
117359
117610
|
type: "agent:tool_input_update",
|
|
117360
117611
|
payload: {
|
|
@@ -117478,7 +117729,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117478
117729
|
blockTypes,
|
|
117479
117730
|
hasToolResult,
|
|
117480
117731
|
hasPlainText,
|
|
117481
|
-
|
|
117732
|
+
contentLen: typeof content === "string" ? content.length : JSON.stringify(content).length
|
|
117482
117733
|
});
|
|
117483
117734
|
break;
|
|
117484
117735
|
}
|
|
@@ -117487,7 +117738,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117487
117738
|
agentId: proc.agentId,
|
|
117488
117739
|
scope: proc.scope.kind === "single" ? "single" : proc.scope.groupId,
|
|
117489
117740
|
blockTypes,
|
|
117490
|
-
|
|
117741
|
+
contentLen: JSON.stringify(content).length,
|
|
117491
117742
|
replyMessageId: base.replyMessageId
|
|
117492
117743
|
});
|
|
117493
117744
|
}
|
|
@@ -117508,6 +117759,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117508
117759
|
});
|
|
117509
117760
|
proc.currentMcpInvocationId = null;
|
|
117510
117761
|
proc.currentMcpInvocationStartedAt = null;
|
|
117762
|
+
proc.activeToolUseStartedAt = void 0;
|
|
117511
117763
|
proc.currentToolName = null;
|
|
117512
117764
|
continue;
|
|
117513
117765
|
}
|
|
@@ -117515,6 +117767,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117515
117767
|
proc.officialMediaGenerationSatisfied = true;
|
|
117516
117768
|
}
|
|
117517
117769
|
if (isAskUserQuestionToolName(toolName)) {
|
|
117770
|
+
proc.activeToolUseStartedAt = void 0;
|
|
117518
117771
|
proc.currentToolName = null;
|
|
117519
117772
|
continue;
|
|
117520
117773
|
}
|
|
@@ -117542,7 +117795,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117542
117795
|
proc.currentMcpInvocationId = null;
|
|
117543
117796
|
proc.currentMcpInvocationStartedAt = null;
|
|
117544
117797
|
}
|
|
117545
|
-
if (
|
|
117798
|
+
if (shouldStreamInternals(proc)) {
|
|
117546
117799
|
emit({
|
|
117547
117800
|
type: "agent:tool_result",
|
|
117548
117801
|
payload: {
|
|
@@ -117566,6 +117819,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117566
117819
|
}
|
|
117567
117820
|
}
|
|
117568
117821
|
}
|
|
117822
|
+
proc.activeToolUseStartedAt = void 0;
|
|
117569
117823
|
}
|
|
117570
117824
|
}
|
|
117571
117825
|
}
|
|
@@ -117644,7 +117898,6 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117644
117898
|
groupId,
|
|
117645
117899
|
compactScheduled: proc.compactRequested === true,
|
|
117646
117900
|
fullTextLen: proc.accumulatedText.length,
|
|
117647
|
-
fullTextSample: proc.accumulatedText.slice(0, 200),
|
|
117648
117901
|
accumulatedBlockCount: proc.contentBlocks.length,
|
|
117649
117902
|
accumulatedBlockTypes: proc.contentBlocks.map((b) => b.type),
|
|
117650
117903
|
silentSegmentEmitted: groupMode
|
|
@@ -117688,7 +117941,6 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117688
117941
|
segmentCount: proc.segmentCount,
|
|
117689
117942
|
compactScheduled: proc.compactRequested === true,
|
|
117690
117943
|
fullTextLen: proc.accumulatedText.length,
|
|
117691
|
-
fullTextSample: proc.accumulatedText.slice(0, 200),
|
|
117692
117944
|
traceId: base.traceId
|
|
117693
117945
|
});
|
|
117694
117946
|
emit({
|
|
@@ -117739,7 +117991,6 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117739
117991
|
ackId: base.replyMessageId,
|
|
117740
117992
|
messageId: carrierMessageId,
|
|
117741
117993
|
textLen: proc.accumulatedText.length,
|
|
117742
|
-
textSample: proc.accumulatedText.slice(0, 200),
|
|
117743
117994
|
tokenCount: usage.tokenCount,
|
|
117744
117995
|
traceId: base.traceId
|
|
117745
117996
|
});
|
|
@@ -117932,8 +118183,7 @@ function mapSDKMessage(proc, message, rawEmit, sessionStore, onCompleted, onProv
|
|
|
117932
118183
|
logger11.info("Captured non-streamed assistant message", {
|
|
117933
118184
|
agentId: proc.agentId,
|
|
117934
118185
|
scope: proc.scope.kind === "single" ? "single" : proc.scope.groupId,
|
|
117935
|
-
textLen: text.length
|
|
117936
|
-
textSample: text.slice(0, 100)
|
|
118186
|
+
textLen: text.length
|
|
117937
118187
|
});
|
|
117938
118188
|
} else {
|
|
117939
118189
|
proc.lastAssistantContentDescription = describeAssistantContent(am.message?.content);
|
|
@@ -117957,6 +118207,7 @@ function resetAccumulators(proc) {
|
|
|
117957
118207
|
proc.currentToolName = null;
|
|
117958
118208
|
proc.currentMcpInvocationId = null;
|
|
117959
118209
|
proc.currentMcpInvocationStartedAt = null;
|
|
118210
|
+
proc.activeToolUseStartedAt = void 0;
|
|
117960
118211
|
proc.segmentBuffer = "";
|
|
117961
118212
|
proc.segmentCount = 0;
|
|
117962
118213
|
proc.accumulatedToolInput = "";
|
|
@@ -117966,6 +118217,7 @@ function resetAccumulators(proc) {
|
|
|
117966
118217
|
proc.officialMediaGenerationSatisfied = false;
|
|
117967
118218
|
proc.suppressCurrentThinking = false;
|
|
117968
118219
|
proc.suppressCurrentToolUse = false;
|
|
118220
|
+
proc.activeSubagentTaskIds?.clear();
|
|
117969
118221
|
}
|
|
117970
118222
|
|
|
117971
118223
|
// src/forkHistoryReplay.ts
|
|
@@ -118157,7 +118409,7 @@ function missingSubscriptionMessage(subscriptionId) {
|
|
|
118157
118409
|
}
|
|
118158
118410
|
var NODE_USER_UID = 1e3;
|
|
118159
118411
|
var POST_MERGE_CONTINUATION_ROUTE_MS = 15e3;
|
|
118160
|
-
var SCOPE_PROMPT_FINGERPRINT_REVISION = "workdir-scope-prompt-
|
|
118412
|
+
var SCOPE_PROMPT_FINGERPRINT_REVISION = "workdir-scope-mcp-abi-prompt-v4";
|
|
118161
118413
|
var BINARY_ATTACHMENT_EXT_RE = /\.(?:7z|bmp|csv|doc|docx|gif|jpeg|jpg|m4a|mov|mp3|mp4|pdf|png|ppt|pptx|rar|rtf|wav|webm|webp|xls|xlsx|zip)$/i;
|
|
118162
118414
|
var DOCUMENT_READING_RULES = `DOCUMENT READING:
|
|
118163
118415
|
- The built-in Read tool cannot read binary office documents such as .docx, .xls, .xlsx, .pptx, .pdf, .odt, .ods, .odp, or .rtf.
|
|
@@ -118172,6 +118424,16 @@ var MEDIA_GENERATION_RULES = `MEDIA GENERATION:
|
|
|
118172
118424
|
- Keep media replies short. Do not print raw media URLs, request_id, task_id, polling logs, or "let me check again" narration unless the user explicitly asks for diagnostics.
|
|
118173
118425
|
- When a media task is submitted or completed, write only a natural one-line note such as "\u5DF2\u5F00\u59CB\u751F\u6210\uFF0C\u6211\u4F1A\u5728\u8FD9\u91CC\u66F4\u65B0\u7ED3\u679C\u3002" or "\u751F\u6210\u597D\u4E86\uFF0C\u53EF\u4EE5\u5728\u5361\u7247\u91CC\u67E5\u770B\u3002"; let the media card show status, preview, download, copy, and regenerate actions.
|
|
118174
118426
|
- If the user asks whether a Seedance task is ready, call mcp__seedance__seedance_check_task once and answer from that result. Do not loop, sleep, or invent external Seedance API endpoints.`;
|
|
118427
|
+
function stableFingerprintValue(value) {
|
|
118428
|
+
if (Array.isArray(value)) return value.map(stableFingerprintValue);
|
|
118429
|
+
if (!value || typeof value !== "object") return value;
|
|
118430
|
+
const out = {};
|
|
118431
|
+
for (const key of Object.keys(value).sort()) {
|
|
118432
|
+
const normalized = stableFingerprintValue(value[key]);
|
|
118433
|
+
if (normalized !== void 0) out[key] = normalized;
|
|
118434
|
+
}
|
|
118435
|
+
return out;
|
|
118436
|
+
}
|
|
118175
118437
|
function isRecoveryDispatchTask(task) {
|
|
118176
118438
|
return task.dispatchKind === "manual_continue" || task.dispatchKind === "regenerate";
|
|
118177
118439
|
}
|
|
@@ -118429,13 +118691,15 @@ var AgentManager = class {
|
|
|
118429
118691
|
agents = /* @__PURE__ */ new Map();
|
|
118430
118692
|
lastUsedAt = /* @__PURE__ */ new Map();
|
|
118431
118693
|
/** Scopes 被 zombie_watchdog 关闭后的"入睡"标记,acquire 重建时清除并 emit awake。 */
|
|
118432
|
-
dormantScopes = /* @__PURE__ */ new
|
|
118694
|
+
dormantScopes = /* @__PURE__ */ new Map();
|
|
118433
118695
|
/**
|
|
118434
118696
|
* zombie_watchdog 拆 runtime 时,把该 (agentId, scope) 的 groupInbox 快照到这里,
|
|
118435
118697
|
* 让下一次 getOrCreate 重建 runtime 时可以恢复未读消息。仅 in-memory;
|
|
118436
118698
|
* bridge 进程崩溃 / shutdownAll 时丢失,与现有 inbox 内存语义一致。
|
|
118437
118699
|
*/
|
|
118438
118700
|
dormantGroupInboxes = /* @__PURE__ */ new Map();
|
|
118701
|
+
/** Spectate requested before runtime existed; value = activatedAt epoch ms. */
|
|
118702
|
+
pendingSpectate = /* @__PURE__ */ new Map();
|
|
118439
118703
|
sessionStore;
|
|
118440
118704
|
dispatchMemory = new GroupDispatchMemoryStore();
|
|
118441
118705
|
dataDir;
|
|
@@ -118601,6 +118865,7 @@ var AgentManager = class {
|
|
|
118601
118865
|
}
|
|
118602
118866
|
async resolveRuntimeCwd(agentConfig, scope, requestedCwd) {
|
|
118603
118867
|
let cwd = this.remapServerWorkspaceCwd(agentConfig, scope, requestedCwd);
|
|
118868
|
+
let fallbackForensicsId;
|
|
118604
118869
|
if (!isFullyQualifiedAbsolutePath(cwd)) {
|
|
118605
118870
|
const fallback = import_node_path13.default.join(this.workspacesDir, this.localScopeDirName(agentConfig, scope));
|
|
118606
118871
|
logger14.error(
|
|
@@ -118615,6 +118880,23 @@ var AgentManager = class {
|
|
|
118615
118880
|
error: new Error("workdir_not_usable_on_this_machine")
|
|
118616
118881
|
}
|
|
118617
118882
|
);
|
|
118883
|
+
fallbackForensicsId = createFallbackId();
|
|
118884
|
+
logFallback(logger14, {
|
|
118885
|
+
fallbackId: fallbackForensicsId,
|
|
118886
|
+
type: "cwd_sandbox",
|
|
118887
|
+
phase: "applied",
|
|
118888
|
+
expected: false,
|
|
118889
|
+
context: {
|
|
118890
|
+
agentId: agentConfig.id,
|
|
118891
|
+
scope: scopeKey(scope),
|
|
118892
|
+
platform: process.platform,
|
|
118893
|
+
requested: requestedCwd,
|
|
118894
|
+
resolved: cwd,
|
|
118895
|
+
reason: "not_fully_qualified",
|
|
118896
|
+
fallback
|
|
118897
|
+
},
|
|
118898
|
+
outcome: { result: "sandbox_fallback" }
|
|
118899
|
+
});
|
|
118618
118900
|
cwd = fallback;
|
|
118619
118901
|
}
|
|
118620
118902
|
if (isRunningAsRoot() && cwd.startsWith("/root/")) {
|
|
@@ -118633,6 +118915,21 @@ var AgentManager = class {
|
|
|
118633
118915
|
fallback,
|
|
118634
118916
|
error: e
|
|
118635
118917
|
});
|
|
118918
|
+
const fbId = fallbackForensicsId ?? createFallbackId();
|
|
118919
|
+
logFallback(logger14, {
|
|
118920
|
+
fallbackId: fbId,
|
|
118921
|
+
type: "cwd_sandbox",
|
|
118922
|
+
phase: "applied",
|
|
118923
|
+
expected: false,
|
|
118924
|
+
context: {
|
|
118925
|
+
agentId: agentConfig.id,
|
|
118926
|
+
scope: scopeKey(scope),
|
|
118927
|
+
reason: "mkdir_failed",
|
|
118928
|
+
requested: cwd,
|
|
118929
|
+
fallback
|
|
118930
|
+
},
|
|
118931
|
+
outcome: { result: "second_layer_fallback" }
|
|
118932
|
+
});
|
|
118636
118933
|
await import_promises3.default.mkdir(fallback, { recursive: true });
|
|
118637
118934
|
return fallback;
|
|
118638
118935
|
}
|
|
@@ -118855,17 +119152,24 @@ var AgentManager = class {
|
|
|
118855
119152
|
});
|
|
118856
119153
|
return null;
|
|
118857
119154
|
}
|
|
118858
|
-
scopePromptFingerprint(agentConfig, scope, agentCwd, scopesSection) {
|
|
118859
|
-
return (0, import_node_crypto3.createHash)("sha256").update(SCOPE_PROMPT_FINGERPRINT_REVISION).update("\0").update(agentConfig.id).update("\0").update(agentConfig.name).update("\0").update(scopeKey(scope)).update("\0").update(import_node_path13.default.normalize(agentCwd)).update("\0").update(scopesSection).digest("hex");
|
|
119155
|
+
scopePromptFingerprint(agentConfig, scope, agentCwd, scopesSection, externalMcpFingerprint) {
|
|
119156
|
+
return (0, import_node_crypto3.createHash)("sha256").update(SCOPE_PROMPT_FINGERPRINT_REVISION).update("\0").update(agentConfig.id).update("\0").update(agentConfig.name).update("\0").update(scopeKey(scope)).update("\0").update(import_node_path13.default.normalize(agentCwd)).update("\0").update(scopesSection).update("\0").update(externalMcpFingerprint).digest("hex");
|
|
118860
119157
|
}
|
|
118861
|
-
|
|
119158
|
+
externalMcpFingerprint(externalMcp) {
|
|
119159
|
+
const serverNames = Object.keys(externalMcp.mcpServers).sort();
|
|
119160
|
+
const allowedTools = [...externalMcp.allowedTools].sort();
|
|
119161
|
+
const toolAbi = [...externalMcp.toolAbi ?? []].sort((a, b) => a.serverName.localeCompare(b.serverName)).map(stableFingerprintValue);
|
|
119162
|
+
if (serverNames.length === 0 && allowedTools.length === 0 && toolAbi.length === 0) return "";
|
|
119163
|
+
return JSON.stringify({ serverNames, allowedTools, toolAbi });
|
|
119164
|
+
}
|
|
119165
|
+
discardSessionIfScopePromptChanged(agentConfig, scope, sessionId, fingerprint, options = {}) {
|
|
118862
119166
|
const previous = this.sessionStore.getPromptFingerprint(agentConfig.id, scope);
|
|
118863
119167
|
if (!sessionId) {
|
|
118864
119168
|
this.sessionStore.setPromptFingerprint(agentConfig.id, scope, fingerprint);
|
|
118865
119169
|
return null;
|
|
118866
119170
|
}
|
|
118867
119171
|
if (previous === fingerprint) return sessionId;
|
|
118868
|
-
if (!previous && scope.kind === "single") {
|
|
119172
|
+
if (!previous && scope.kind === "single" && options.clearLegacySingleSession !== true) {
|
|
118869
119173
|
this.sessionStore.setPromptFingerprint(agentConfig.id, scope, fingerprint);
|
|
118870
119174
|
logger14.info("Retaining legacy single-scope session while recording prompt fingerprint", {
|
|
118871
119175
|
agentId: agentConfig.id,
|
|
@@ -118885,7 +119189,8 @@ var AgentManager = class {
|
|
|
118885
119189
|
sessionId,
|
|
118886
119190
|
previousFingerprint: previous,
|
|
118887
119191
|
nextFingerprint: fingerprint,
|
|
118888
|
-
revision: SCOPE_PROMPT_FINGERPRINT_REVISION
|
|
119192
|
+
revision: SCOPE_PROMPT_FINGERPRINT_REVISION,
|
|
119193
|
+
reason: options.reason ?? "scope_prompt_changed"
|
|
118889
119194
|
});
|
|
118890
119195
|
return null;
|
|
118891
119196
|
}
|
|
@@ -118934,6 +119239,7 @@ var AgentManager = class {
|
|
|
118934
119239
|
logger14.info("Evicting idle Agent query", { agentId: proc.agentId, scope: scopeKey(proc.scope) });
|
|
118935
119240
|
const runtime = this.asRuntime(proc);
|
|
118936
119241
|
this.clearQuietFlushTimer(runtime);
|
|
119242
|
+
this.teardownSpectate(runtime);
|
|
118937
119243
|
try {
|
|
118938
119244
|
runtime.inputController.close();
|
|
118939
119245
|
await this.awaitQueryReturn(runtime.query, 5e3, proc.agentId);
|
|
@@ -118953,6 +119259,7 @@ var AgentManager = class {
|
|
|
118953
119259
|
const runtime = this.asRuntime(proc);
|
|
118954
119260
|
const key = runtimeKey(proc.agentId, proc.scope);
|
|
118955
119261
|
this.clearQuietFlushTimer(runtime);
|
|
119262
|
+
this.teardownSpectate(runtime);
|
|
118956
119263
|
runtime.currentTask = null;
|
|
118957
119264
|
runtime.injectedTasks = [];
|
|
118958
119265
|
runtime.mergedTasks = [];
|
|
@@ -118989,6 +119296,7 @@ var AgentManager = class {
|
|
|
118989
119296
|
evictIdle() {
|
|
118990
119297
|
const now = Date.now();
|
|
118991
119298
|
const { idleTimeoutMs, workingSilenceTimeoutMs } = this.queryConfig;
|
|
119299
|
+
const stallWarnAfterMs = Math.min(9e4, this.queryConfig.replyStallTimeoutMs);
|
|
118992
119300
|
for (const [key, proc] of this.agents) {
|
|
118993
119301
|
if (!this.isEvictable(proc)) continue;
|
|
118994
119302
|
const runtime = this.asRuntime(proc);
|
|
@@ -118999,26 +119307,62 @@ var AgentManager = class {
|
|
|
118999
119307
|
for (const [, proc] of this.agents) {
|
|
119000
119308
|
if (proc.status !== "working") continue;
|
|
119001
119309
|
const runtime = this.asRuntime(proc);
|
|
119310
|
+
if (runtime.currentTask) {
|
|
119311
|
+
const sinceEventMs = now - proc.lastSdkEventAt;
|
|
119312
|
+
if (sinceEventMs > stallWarnAfterMs && !proc.stallWarned) {
|
|
119313
|
+
proc.stallWarned = true;
|
|
119314
|
+
const openTool = this.latestOpenToolUse(proc);
|
|
119315
|
+
logger14.warn("Reply stall onset: in-flight reply silent", {
|
|
119316
|
+
agentId: proc.agentId,
|
|
119317
|
+
scope: scopeKey(proc.scope),
|
|
119318
|
+
sinceEventMs,
|
|
119319
|
+
replyStallTimeoutMs: this.queryConfig.replyStallTimeoutMs,
|
|
119320
|
+
workingSilenceTimeoutMs,
|
|
119321
|
+
busySilenceTimeoutMs: this.queryConfig.busySilenceTimeoutMs ?? null,
|
|
119322
|
+
replyMessageId: runtime.currentTask.replyMessageId,
|
|
119323
|
+
model: proc.model ?? "(unknown)",
|
|
119324
|
+
lastSdkEvent: proc.lastSdkEventInfo,
|
|
119325
|
+
hasActiveToolUse: runtime.activeToolUseStartedAt != null || openTool != null,
|
|
119326
|
+
activeToolUseAgeMs: runtime.activeToolUseStartedAt != null ? now - runtime.activeToolUseStartedAt : null,
|
|
119327
|
+
openToolName: openTool?.toolName ?? proc.currentToolName ?? null,
|
|
119328
|
+
openMcpInvocationId: proc.currentMcpInvocationId ?? null,
|
|
119329
|
+
subagentInFlight: (runtime.activeSubagentTaskIds?.size ?? 0) > 0,
|
|
119330
|
+
activeSubagentCount: runtime.activeSubagentTaskIds?.size ?? 0,
|
|
119331
|
+
busyReason: this.busyReason(proc)
|
|
119332
|
+
});
|
|
119333
|
+
}
|
|
119334
|
+
}
|
|
119335
|
+
const busyReason = this.busyReason(runtime);
|
|
119336
|
+
const busy = busyReason !== null;
|
|
119337
|
+
if (runtime.currentTask && !busy && now - proc.lastSdkEventAt > this.queryConfig.replyStallTimeoutMs) {
|
|
119338
|
+
void this.recoverStalledReply(proc, now - proc.lastSdkEventAt);
|
|
119339
|
+
continue;
|
|
119340
|
+
}
|
|
119002
119341
|
const hasInjectedBacklog = runtime.injectedTasks.length > 0;
|
|
119003
|
-
const
|
|
119342
|
+
const baseCeilingMs = busy ? Math.max(workingSilenceTimeoutMs, this.queryConfig.busySilenceTimeoutMs ?? 0) : workingSilenceTimeoutMs;
|
|
119343
|
+
const effectiveTimeoutMs = hasInjectedBacklog ? baseCeilingMs * 2 : baseCeilingMs;
|
|
119004
119344
|
const silentMs = now - proc.lastSdkEventAt;
|
|
119005
119345
|
if (silentMs <= effectiveTimeoutMs) {
|
|
119006
|
-
if (
|
|
119007
|
-
logger14.warn(
|
|
119008
|
-
|
|
119009
|
-
|
|
119010
|
-
|
|
119011
|
-
|
|
119012
|
-
|
|
119013
|
-
|
|
119014
|
-
|
|
119015
|
-
|
|
119016
|
-
|
|
119017
|
-
|
|
119018
|
-
|
|
119346
|
+
if (silentMs > workingSilenceTimeoutMs) {
|
|
119347
|
+
logger14.warn("Zombie watchdog: working runtime silent past base timeout; granting extended grace", {
|
|
119348
|
+
agentId: proc.agentId,
|
|
119349
|
+
scope: scopeKey(proc.scope),
|
|
119350
|
+
silentMs,
|
|
119351
|
+
baseTimeoutMs: workingSilenceTimeoutMs,
|
|
119352
|
+
baseCeilingMs,
|
|
119353
|
+
busySilenceTimeoutMs: this.queryConfig.busySilenceTimeoutMs ?? null,
|
|
119354
|
+
effectiveTimeoutMs,
|
|
119355
|
+
busy,
|
|
119356
|
+
busyReason,
|
|
119357
|
+
injectedTaskCount: runtime.injectedTasks.length,
|
|
119358
|
+
replyMessageId: proc.currentTask?.replyMessageId
|
|
119359
|
+
});
|
|
119019
119360
|
}
|
|
119020
119361
|
continue;
|
|
119021
119362
|
}
|
|
119363
|
+
const zombieOpenTool = this.latestOpenToolUse(proc);
|
|
119364
|
+
const watchdogDetectedAt = Date.now();
|
|
119365
|
+
const watchdogFallbackId = createFallbackId();
|
|
119022
119366
|
logger14.warn("Zombie watchdog: working runtime silent too long, tearing down", {
|
|
119023
119367
|
agentId: proc.agentId,
|
|
119024
119368
|
scope: scopeKey(proc.scope),
|
|
@@ -119026,12 +119370,46 @@ var AgentManager = class {
|
|
|
119026
119370
|
lastSdkEventAt: new Date(proc.lastSdkEventAt).toISOString(),
|
|
119027
119371
|
workingSilenceTimeoutMs,
|
|
119028
119372
|
effectiveTimeoutMs,
|
|
119373
|
+
baseCeilingMs,
|
|
119374
|
+
busy,
|
|
119375
|
+
busySilenceTimeoutMs: this.queryConfig.busySilenceTimeoutMs ?? null,
|
|
119029
119376
|
replyMessageId: proc.currentTask?.replyMessageId,
|
|
119030
119377
|
injectedTaskCount: runtime.injectedTasks.length,
|
|
119031
119378
|
hadInjectedBacklog: hasInjectedBacklog,
|
|
119032
|
-
inboxSize: proc.groupInbox.length
|
|
119379
|
+
inboxSize: proc.groupInbox.length,
|
|
119380
|
+
fallbackId: watchdogFallbackId,
|
|
119381
|
+
// Breadcrumb: what the turn was waiting on when it timed out. A hung subagent
|
|
119382
|
+
// (open `Task` tool_use) lands here now that the fast path skips active tools.
|
|
119383
|
+
model: proc.model ?? "(unknown)",
|
|
119384
|
+
lastSdkEvent: proc.lastSdkEventInfo,
|
|
119385
|
+
openToolName: zombieOpenTool?.toolName ?? proc.currentToolName ?? null,
|
|
119386
|
+
activeToolUseAgeMs: runtime.activeToolUseStartedAt != null ? now - runtime.activeToolUseStartedAt : null,
|
|
119387
|
+
openMcpInvocationId: proc.currentMcpInvocationId ?? null,
|
|
119388
|
+
subagentInFlight: (runtime.activeSubagentTaskIds?.size ?? 0) > 0,
|
|
119389
|
+
activeSubagentCount: runtime.activeSubagentTaskIds?.size ?? 0,
|
|
119390
|
+
busyReason: this.busyReason(proc)
|
|
119391
|
+
});
|
|
119392
|
+
logFallback(logger14, {
|
|
119393
|
+
fallbackId: watchdogFallbackId,
|
|
119394
|
+
type: "zombie_watchdog",
|
|
119395
|
+
phase: "detected",
|
|
119396
|
+
expected: false,
|
|
119397
|
+
traceId: proc.currentTask?.traceId,
|
|
119398
|
+
context: {
|
|
119399
|
+
agentId: proc.agentId,
|
|
119400
|
+
scope: scopeKey(proc.scope),
|
|
119401
|
+
silentMs,
|
|
119402
|
+
replyMessageId: proc.currentTask?.replyMessageId ?? null,
|
|
119403
|
+
openToolName: zombieOpenTool?.toolName ?? proc.currentToolName ?? null,
|
|
119404
|
+
lastSdkEventType: proc.lastSdkEventInfo?.type ?? null,
|
|
119405
|
+
injectedTaskCount: runtime.injectedTasks.length,
|
|
119406
|
+
inboxSize: proc.groupInbox.length
|
|
119407
|
+
}
|
|
119408
|
+
});
|
|
119409
|
+
void this.closeRuntime(proc, "zombie_watchdog", {
|
|
119410
|
+
fallbackId: watchdogFallbackId,
|
|
119411
|
+
detectedAt: watchdogDetectedAt
|
|
119033
119412
|
});
|
|
119034
|
-
void this.closeRuntime(proc, "zombie_watchdog");
|
|
119035
119413
|
}
|
|
119036
119414
|
}
|
|
119037
119415
|
/**
|
|
@@ -119278,7 +119656,7 @@ ${cfg.instructions.trim()}` : "";
|
|
|
119278
119656
|
agentId: agentConfig.id,
|
|
119279
119657
|
capabilityTier: cfg.capabilityTier,
|
|
119280
119658
|
isSmith: smithAgent
|
|
119281
|
-
}) ?? { mcpServers: {}, allowedTools: [] };
|
|
119659
|
+
}) ?? { mcpServers: {}, allowedTools: [], toolAbi: [] };
|
|
119282
119660
|
logger14.info("External MCP resolved for runtime", {
|
|
119283
119661
|
agentId: agentConfig.id,
|
|
119284
119662
|
scope: scopeKey(scope),
|
|
@@ -119295,11 +119673,16 @@ ${cfg.instructions.trim()}` : "";
|
|
|
119295
119673
|
}
|
|
119296
119674
|
const notebookSection = this.buildNotebookSection(agentConfig.id);
|
|
119297
119675
|
const scopesSection = this.buildScopesSection(agentConfig, scope, agentCwd);
|
|
119676
|
+
const externalMcpFingerprint = this.externalMcpFingerprint(externalMcp);
|
|
119298
119677
|
savedSessionId = this.discardSessionIfScopePromptChanged(
|
|
119299
119678
|
agentConfig,
|
|
119300
119679
|
scope,
|
|
119301
119680
|
savedSessionId,
|
|
119302
|
-
this.scopePromptFingerprint(agentConfig, scope, agentCwd, scopesSection)
|
|
119681
|
+
this.scopePromptFingerprint(agentConfig, scope, agentCwd, scopesSection, externalMcpFingerprint),
|
|
119682
|
+
{
|
|
119683
|
+
clearLegacySingleSession: externalMcpFingerprint.length > 0,
|
|
119684
|
+
reason: externalMcpFingerprint.length > 0 ? "external_mcp_abi_changed" : "scope_prompt_changed"
|
|
119685
|
+
}
|
|
119303
119686
|
);
|
|
119304
119687
|
let forkHistorySection = "";
|
|
119305
119688
|
if (!savedSessionId && scope.kind === "single") {
|
|
@@ -119320,6 +119703,8 @@ ${cfg.instructions.trim()}` : "";
|
|
|
119320
119703
|
}
|
|
119321
119704
|
}
|
|
119322
119705
|
const cronLockSnapshot = readCronLockSnapshot();
|
|
119706
|
+
const builtinWebSearchAllowed = this.queryConfig.allowBuiltinWebSearch;
|
|
119707
|
+
const disallowedToolsForRuntime = builtinWebSearchAllowed ? [] : ["WebSearch"];
|
|
119323
119708
|
logger14.info("Creating Agent query", {
|
|
119324
119709
|
agentId: agentConfig.id,
|
|
119325
119710
|
scope: scopeKey(scope),
|
|
@@ -119328,6 +119713,8 @@ ${cfg.instructions.trim()}` : "";
|
|
|
119328
119713
|
sessionId: savedSessionId,
|
|
119329
119714
|
forkHistoryReplay: forkHistorySection.length > 0,
|
|
119330
119715
|
model: cfg.model ?? "(default)",
|
|
119716
|
+
builtinWebSearchAllowed,
|
|
119717
|
+
disallowedTools: disallowedToolsForRuntime,
|
|
119331
119718
|
// Diagnostic: who currently owns Claude's global cron lock (~/.claude/scheduled_tasks.lock).
|
|
119332
119719
|
// Cron is process-internal but the binary uses this singleton lock to elect ONE scheduler
|
|
119333
119720
|
// among concurrent claude subprocesses. If lock is held by another session at spawn time,
|
|
@@ -119339,7 +119726,6 @@ ${cfg.instructions.trim()}` : "";
|
|
|
119339
119726
|
});
|
|
119340
119727
|
const planModeRef = { active: false, denyCount: 0 };
|
|
119341
119728
|
const mediaGenerationTurnGuard = createOfficialMediaGenerationTurnGuard();
|
|
119342
|
-
const builtinWebSearchAllowed = this.queryConfig.allowBuiltinWebSearch;
|
|
119343
119729
|
const options = {
|
|
119344
119730
|
cwd: agentCwd,
|
|
119345
119731
|
systemPrompt: {
|
|
@@ -119406,6 +119792,8 @@ ${cfg.instructions.trim()}` : "";
|
|
|
119406
119792
|
] : [],
|
|
119407
119793
|
...externalMcp.allowedTools
|
|
119408
119794
|
],
|
|
119795
|
+
// Server-side WebSearch bypasses canUseTool; disallowedTools removes it from model context.
|
|
119796
|
+
disallowedTools: disallowedToolsForRuntime,
|
|
119409
119797
|
mcpServers: { ...externalMcp.mcpServers, neural: neuralServer },
|
|
119410
119798
|
includePartialMessages: true,
|
|
119411
119799
|
// Plan mode custom workflow instructions. When setPermissionMode('plan') is
|
|
@@ -119732,6 +120120,7 @@ Do NOT use "..." as content \u2014 write specific, project-relevant content.`;
|
|
|
119732
120120
|
currentTask: null,
|
|
119733
120121
|
currentTaskStartedAt: 0,
|
|
119734
120122
|
lastSdkEventAt: Date.now(),
|
|
120123
|
+
model: (typeof options.model === "string" ? options.model : cfg.model) ?? null,
|
|
119735
120124
|
compactRequested: false,
|
|
119736
120125
|
compactInProgress: false,
|
|
119737
120126
|
contextOverflowLockedUntil: 0,
|
|
@@ -119743,13 +120132,18 @@ Do NOT use "..." as content \u2014 write specific, project-relevant content.`;
|
|
|
119743
120132
|
currentToolName: null,
|
|
119744
120133
|
currentMcpInvocationId: null,
|
|
119745
120134
|
currentMcpInvocationStartedAt: null,
|
|
120135
|
+
activeSubagentTaskIds: /* @__PURE__ */ new Set(),
|
|
119746
120136
|
mcpAuditRecorder: this.mcpAuditRecorder,
|
|
119747
120137
|
segmentBuffer: "",
|
|
119748
120138
|
segmentCount: 0,
|
|
119749
120139
|
accumulatedToolInput: "",
|
|
119750
120140
|
planModeRef,
|
|
119751
120141
|
mediaGenerationTurnGuard,
|
|
119752
|
-
groupInbox: []
|
|
120142
|
+
groupInbox: [],
|
|
120143
|
+
spectating: false,
|
|
120144
|
+
spectateActivatedAt: 0,
|
|
120145
|
+
spectateViewing: false,
|
|
120146
|
+
spectateTtlExpired: false
|
|
119753
120147
|
};
|
|
119754
120148
|
const runtime = Object.assign(proc, {
|
|
119755
120149
|
query: agentQuery,
|
|
@@ -119761,7 +120155,8 @@ Do NOT use "..." as content \u2014 write specific, project-relevant content.`;
|
|
|
119761
120155
|
createdAt: Date.now(),
|
|
119762
120156
|
supportsVision: modelInputMode === "vision" && cfg.supportsVision !== false,
|
|
119763
120157
|
modelInputMode,
|
|
119764
|
-
quietFlushTimer: null
|
|
120158
|
+
quietFlushTimer: null,
|
|
120159
|
+
spectateRevertTimer: null
|
|
119765
120160
|
});
|
|
119766
120161
|
logger14.info("Agent model input mode resolved", {
|
|
119767
120162
|
agentId: agentConfig.id,
|
|
@@ -119786,6 +120181,7 @@ Do NOT use "..." as content \u2014 write specific, project-relevant content.`;
|
|
|
119786
120181
|
} else {
|
|
119787
120182
|
this.dormantGroupInboxes.delete(key);
|
|
119788
120183
|
}
|
|
120184
|
+
const dormantMeta = this.dormantScopes.get(key);
|
|
119789
120185
|
if (this.dormantScopes.delete(key)) {
|
|
119790
120186
|
this.emit({
|
|
119791
120187
|
type: "agent:awake",
|
|
@@ -119797,7 +120193,44 @@ Do NOT use "..." as content \u2014 write specific, project-relevant content.`;
|
|
|
119797
120193
|
});
|
|
119798
120194
|
logger14.info("Agent scope awakened after dormant", {
|
|
119799
120195
|
agentId: agentConfig.id,
|
|
119800
|
-
scope: scopeKey(scope)
|
|
120196
|
+
scope: scopeKey(scope),
|
|
120197
|
+
...dormantMeta ? {
|
|
120198
|
+
fallbackId: dormantMeta.fallbackId,
|
|
120199
|
+
dormantDurationMs: Date.now() - dormantMeta.detectedAt,
|
|
120200
|
+
dataLossSuspected: dormantMeta.droppedTaskCount > 0
|
|
120201
|
+
} : {}
|
|
120202
|
+
});
|
|
120203
|
+
if (dormantMeta) {
|
|
120204
|
+
logFallback(logger14, {
|
|
120205
|
+
fallbackId: dormantMeta.fallbackId,
|
|
120206
|
+
type: "zombie_watchdog",
|
|
120207
|
+
phase: "outcome",
|
|
120208
|
+
expected: false,
|
|
120209
|
+
context: {
|
|
120210
|
+
agentId: agentConfig.id,
|
|
120211
|
+
scope: scopeKey(scope)
|
|
120212
|
+
},
|
|
120213
|
+
outcome: {
|
|
120214
|
+
result: "recovered_rebuilt",
|
|
120215
|
+
durationMs: Date.now() - dormantMeta.detectedAt,
|
|
120216
|
+
dataLossSuspected: dormantMeta.droppedTaskCount > 0
|
|
120217
|
+
}
|
|
120218
|
+
});
|
|
120219
|
+
}
|
|
120220
|
+
}
|
|
120221
|
+
const pendingSpectateAt = this.pendingSpectate.get(key);
|
|
120222
|
+
if (pendingSpectateAt != null) {
|
|
120223
|
+
this.pendingSpectate.delete(key);
|
|
120224
|
+
runtime.spectating = true;
|
|
120225
|
+
runtime.spectateViewing = false;
|
|
120226
|
+
runtime.spectateActivatedAt = pendingSpectateAt;
|
|
120227
|
+
runtime.spectateTtlExpired = false;
|
|
120228
|
+
this.armSpectateTimer(runtime);
|
|
120229
|
+
this.emitSpectateState(runtime, true, "started");
|
|
120230
|
+
logger14.info("Applied pending spectate on runtime create", {
|
|
120231
|
+
agentId: agentConfig.id,
|
|
120232
|
+
scope: scopeKey(scope),
|
|
120233
|
+
activatedAt: pendingSpectateAt
|
|
119801
120234
|
});
|
|
119802
120235
|
}
|
|
119803
120236
|
if (proc.groupInbox.length > 0 && this.isRuntimeIdleForInboxFlush(runtime)) {
|
|
@@ -120935,7 +121368,6 @@ ${lines.join("\n")}`;
|
|
|
120935
121368
|
compactTrigger: "context_watermark",
|
|
120936
121369
|
injectedTasksWaiting: runtime.injectedTasks.length,
|
|
120937
121370
|
compactPromptLen: compactPrompt.length,
|
|
120938
|
-
promptSample: compactPrompt.slice(0, 80),
|
|
120939
121371
|
traceId: compactTraceId
|
|
120940
121372
|
});
|
|
120941
121373
|
runtime.inputController.push(compactPrompt, runtime.ccSessionId ?? "");
|
|
@@ -121217,7 +121649,7 @@ ${lines.join("\n")}`;
|
|
|
121217
121649
|
const enveloped = buildInnerVoiceEnvelope(payloadWithTrigger, ctx);
|
|
121218
121650
|
const task = {
|
|
121219
121651
|
content: enveloped,
|
|
121220
|
-
replyMessageId:
|
|
121652
|
+
replyMessageId: createNeuralSendReplyMessageId(),
|
|
121221
121653
|
conversationId: payload.conversationId,
|
|
121222
121654
|
traceId: createTraceId(),
|
|
121223
121655
|
groupId: payload.groupId
|
|
@@ -121463,7 +121895,7 @@ ${lines.join("\n")}`;
|
|
|
121463
121895
|
this.dormantScopes.delete(key);
|
|
121464
121896
|
this.dormantGroupInboxes.delete(key);
|
|
121465
121897
|
}
|
|
121466
|
-
for (const key of [...this.dormantScopes].filter(
|
|
121898
|
+
for (const key of [...this.dormantScopes.keys()].filter(
|
|
121467
121899
|
(k) => k === agentId || k.startsWith(`${agentId}::`)
|
|
121468
121900
|
)) {
|
|
121469
121901
|
this.dormantScopes.delete(key);
|
|
@@ -121511,7 +121943,7 @@ ${lines.join("\n")}`;
|
|
|
121511
121943
|
async reloadAgentScopes(agentId, reason) {
|
|
121512
121944
|
this.sessionStore.deleteAllForAgent(agentId);
|
|
121513
121945
|
this.dispatchMemory.deleteAllForAgent(agentId);
|
|
121514
|
-
for (const key of [...this.dormantScopes].filter(
|
|
121946
|
+
for (const key of [...this.dormantScopes.keys()].filter(
|
|
121515
121947
|
(k) => k === agentId || k.startsWith(`${agentId}::`)
|
|
121516
121948
|
)) {
|
|
121517
121949
|
this.dormantScopes.delete(key);
|
|
@@ -121663,6 +122095,125 @@ ${lines.join("\n")}`;
|
|
|
121663
122095
|
void this.terminateScope(proc.agentId, proc.scope);
|
|
121664
122096
|
}
|
|
121665
122097
|
}
|
|
122098
|
+
/** Control spectate capture/push for one scoped runtime. */
|
|
122099
|
+
async setSpectate(agentId, scope, action) {
|
|
122100
|
+
const key = runtimeKey(agentId, scope);
|
|
122101
|
+
const proc = this.agents.get(key);
|
|
122102
|
+
if (!proc || proc.status === "dead") {
|
|
122103
|
+
if (action === "start") {
|
|
122104
|
+
this.pendingSpectate.set(key, Date.now());
|
|
122105
|
+
logger14.info("setSpectate: runtime missing, pending start", { agentId, scope: scopeKey(scope) });
|
|
122106
|
+
}
|
|
122107
|
+
return;
|
|
122108
|
+
}
|
|
122109
|
+
const runtime = this.asRuntime(proc);
|
|
122110
|
+
switch (action) {
|
|
122111
|
+
case "start":
|
|
122112
|
+
runtime.spectating = true;
|
|
122113
|
+
runtime.spectateViewing = true;
|
|
122114
|
+
runtime.spectateActivatedAt = Date.now();
|
|
122115
|
+
runtime.spectateTtlExpired = false;
|
|
122116
|
+
this.pendingSpectate.delete(key);
|
|
122117
|
+
this.armSpectateTimer(runtime);
|
|
122118
|
+
this.emitSpectateState(runtime, true, "started");
|
|
122119
|
+
logger14.info("Spectate started", { agentId, scope: scopeKey(scope) });
|
|
122120
|
+
break;
|
|
122121
|
+
case "enter_view":
|
|
122122
|
+
runtime.spectateViewing = true;
|
|
122123
|
+
logger14.info("Spectate enter_view", { agentId, scope: scopeKey(scope) });
|
|
122124
|
+
break;
|
|
122125
|
+
case "leave_view":
|
|
122126
|
+
runtime.spectateViewing = false;
|
|
122127
|
+
logger14.info("Spectate leave_view", {
|
|
122128
|
+
agentId,
|
|
122129
|
+
scope: scopeKey(scope),
|
|
122130
|
+
ttlExpired: runtime.spectateTtlExpired
|
|
122131
|
+
});
|
|
122132
|
+
if (runtime.spectateTtlExpired) {
|
|
122133
|
+
this.stopSpectate(runtime, "ttl_expired");
|
|
122134
|
+
}
|
|
122135
|
+
break;
|
|
122136
|
+
case "stop":
|
|
122137
|
+
this.stopSpectate(runtime, "stopped");
|
|
122138
|
+
this.pendingSpectate.delete(key);
|
|
122139
|
+
logger14.info("Spectate stopped", { agentId, scope: scopeKey(scope) });
|
|
122140
|
+
break;
|
|
122141
|
+
default:
|
|
122142
|
+
break;
|
|
122143
|
+
}
|
|
122144
|
+
}
|
|
122145
|
+
spectateTtlMs() {
|
|
122146
|
+
return Number(process.env.AHCHAT_BRIDGE_SPECTATE_TTL_MS) || 36e5;
|
|
122147
|
+
}
|
|
122148
|
+
armSpectateTimer(runtime) {
|
|
122149
|
+
this.clearSpectateTimer(runtime);
|
|
122150
|
+
if (!runtime.spectating || runtime.spectateActivatedAt <= 0) return;
|
|
122151
|
+
const ttlMs = this.spectateTtlMs();
|
|
122152
|
+
const elapsed = Date.now() - runtime.spectateActivatedAt;
|
|
122153
|
+
const delay = Math.max(0, ttlMs - elapsed);
|
|
122154
|
+
runtime.spectateRevertTimer = setTimeout(() => {
|
|
122155
|
+
runtime.spectateRevertTimer = null;
|
|
122156
|
+
runtime.spectateTtlExpired = true;
|
|
122157
|
+
logger14.info("Spectate TTL expired", {
|
|
122158
|
+
agentId: runtime.agentId,
|
|
122159
|
+
scope: scopeKey(runtime.scope),
|
|
122160
|
+
viewing: runtime.spectateViewing
|
|
122161
|
+
});
|
|
122162
|
+
if (!runtime.spectateViewing) {
|
|
122163
|
+
this.stopSpectate(runtime, "ttl_expired");
|
|
122164
|
+
}
|
|
122165
|
+
}, delay);
|
|
122166
|
+
}
|
|
122167
|
+
clearSpectateTimer(runtime) {
|
|
122168
|
+
if (runtime.spectateRevertTimer != null) {
|
|
122169
|
+
clearTimeout(runtime.spectateRevertTimer);
|
|
122170
|
+
runtime.spectateRevertTimer = null;
|
|
122171
|
+
}
|
|
122172
|
+
}
|
|
122173
|
+
stopSpectate(runtime, reason) {
|
|
122174
|
+
const wasActive = runtime.spectating;
|
|
122175
|
+
this.clearSpectateTimer(runtime);
|
|
122176
|
+
runtime.spectating = false;
|
|
122177
|
+
runtime.spectateViewing = false;
|
|
122178
|
+
runtime.spectateTtlExpired = false;
|
|
122179
|
+
runtime.spectateActivatedAt = 0;
|
|
122180
|
+
if (wasActive) {
|
|
122181
|
+
this.emitSpectateState(runtime, false, reason);
|
|
122182
|
+
logger14.info("Spectate deactivated", {
|
|
122183
|
+
agentId: runtime.agentId,
|
|
122184
|
+
scope: scopeKey(runtime.scope),
|
|
122185
|
+
reason
|
|
122186
|
+
});
|
|
122187
|
+
}
|
|
122188
|
+
}
|
|
122189
|
+
emitSpectateState(runtime, active, reason) {
|
|
122190
|
+
const scopePayload = runtime.scope.kind === "single" ? { kind: "single" } : { kind: "group", groupId: runtime.scope.groupId };
|
|
122191
|
+
this.emit({
|
|
122192
|
+
type: "spectate:state",
|
|
122193
|
+
payload: {
|
|
122194
|
+
agentId: runtime.agentId,
|
|
122195
|
+
scope: scopePayload,
|
|
122196
|
+
active,
|
|
122197
|
+
expiresAt: active ? runtime.spectateActivatedAt + this.spectateTtlMs() : void 0,
|
|
122198
|
+
reason,
|
|
122199
|
+
traceId: createTraceId()
|
|
122200
|
+
}
|
|
122201
|
+
});
|
|
122202
|
+
logger14.info("Spectate state emitted", {
|
|
122203
|
+
agentId: runtime.agentId,
|
|
122204
|
+
scope: scopeKey(runtime.scope),
|
|
122205
|
+
active,
|
|
122206
|
+
reason,
|
|
122207
|
+
expiresAt: active ? runtime.spectateActivatedAt + this.spectateTtlMs() : void 0
|
|
122208
|
+
});
|
|
122209
|
+
}
|
|
122210
|
+
teardownSpectate(runtime) {
|
|
122211
|
+
if (runtime.spectating) {
|
|
122212
|
+
this.stopSpectate(runtime, "runtime_gone");
|
|
122213
|
+
} else {
|
|
122214
|
+
this.clearSpectateTimer(runtime);
|
|
122215
|
+
}
|
|
122216
|
+
}
|
|
121666
122217
|
/** Stop one scoped SDK runtime (workdir change). */
|
|
121667
122218
|
async terminateScope(agentId, scope) {
|
|
121668
122219
|
const key = runtimeKey(agentId, scope);
|
|
@@ -121671,6 +122222,7 @@ ${lines.join("\n")}`;
|
|
|
121671
122222
|
logger14.info("terminateScope: no active runtime", { agentId, scope: scopeKey(scope) });
|
|
121672
122223
|
this.dormantScopes.delete(key);
|
|
121673
122224
|
this.dormantGroupInboxes.delete(key);
|
|
122225
|
+
this.pendingSpectate.delete(key);
|
|
121674
122226
|
this.sessionStore.delete(agentId, scope);
|
|
121675
122227
|
this.dispatchMemory.deleteScope(agentId, scope);
|
|
121676
122228
|
return;
|
|
@@ -121693,7 +122245,7 @@ ${lines.join("\n")}`;
|
|
|
121693
122245
|
this.dispatchMemory.deleteScope(agentId, scope);
|
|
121694
122246
|
logger14.info("terminateScope: scoped query removed", { agentId, scope: scopeKey(scope) });
|
|
121695
122247
|
}
|
|
121696
|
-
async closeRuntime(proc, reason) {
|
|
122248
|
+
async closeRuntime(proc, reason, watchdogForensics) {
|
|
121697
122249
|
const key = runtimeKey(proc.agentId, proc.scope);
|
|
121698
122250
|
if (proc.status === "dead") return;
|
|
121699
122251
|
const runtime = this.asRuntime(proc);
|
|
@@ -121770,12 +122322,13 @@ ${lines.join("\n")}`;
|
|
|
121770
122322
|
runtime.currentTask = null;
|
|
121771
122323
|
if (isWatchdog) {
|
|
121772
122324
|
const preservedInbox = proc.groupInbox;
|
|
121773
|
-
|
|
122325
|
+
const preservedInboxSize = preservedInbox.length;
|
|
122326
|
+
if (preservedInboxSize > 0) {
|
|
121774
122327
|
this.dormantGroupInboxes.set(key, [...preservedInbox]);
|
|
121775
122328
|
logger14.info("Preserving groupInbox for dormant agent", {
|
|
121776
122329
|
agentId,
|
|
121777
122330
|
scope: scopeKey(proc.scope),
|
|
121778
|
-
preservedInboxSize
|
|
122331
|
+
preservedInboxSize,
|
|
121779
122332
|
preservedEntries: preservedInbox.map((e) => ({
|
|
121780
122333
|
ackId: e.ackId,
|
|
121781
122334
|
sender: e.senderName,
|
|
@@ -121784,7 +122337,26 @@ ${lines.join("\n")}`;
|
|
|
121784
122337
|
}))
|
|
121785
122338
|
});
|
|
121786
122339
|
}
|
|
121787
|
-
|
|
122340
|
+
const effectiveFallbackId = watchdogForensics?.fallbackId ?? createFallbackId();
|
|
122341
|
+
logFallback(logger14, {
|
|
122342
|
+
fallbackId: effectiveFallbackId,
|
|
122343
|
+
type: "zombie_watchdog",
|
|
122344
|
+
phase: "applied",
|
|
122345
|
+
expected: false,
|
|
122346
|
+
traceId: dormantTraceId,
|
|
122347
|
+
context: {
|
|
122348
|
+
agentId,
|
|
122349
|
+
scope: scopeKey(proc.scope),
|
|
122350
|
+
droppedTaskCount: droppedAckIds.length,
|
|
122351
|
+
preservedInboxSize,
|
|
122352
|
+
sessionDeleted: false
|
|
122353
|
+
}
|
|
122354
|
+
});
|
|
122355
|
+
this.dormantScopes.set(key, {
|
|
122356
|
+
fallbackId: effectiveFallbackId,
|
|
122357
|
+
detectedAt: watchdogForensics?.detectedAt ?? Date.now(),
|
|
122358
|
+
droppedTaskCount: droppedAckIds.length
|
|
122359
|
+
});
|
|
121788
122360
|
this.emit({
|
|
121789
122361
|
type: "agent:dormant",
|
|
121790
122362
|
payload: {
|
|
@@ -121799,13 +122371,15 @@ ${lines.join("\n")}`;
|
|
|
121799
122371
|
agentId,
|
|
121800
122372
|
scope: scopeKey(proc.scope),
|
|
121801
122373
|
droppedTaskCount: droppedAckIds.length,
|
|
121802
|
-
preservedInboxSize: this.dormantGroupInboxes.get(key)?.length ?? 0
|
|
122374
|
+
preservedInboxSize: this.dormantGroupInboxes.get(key)?.length ?? 0,
|
|
122375
|
+
fallbackId: effectiveFallbackId
|
|
121803
122376
|
});
|
|
121804
122377
|
}
|
|
121805
122378
|
proc.status = "dead";
|
|
121806
122379
|
this.agents.delete(key);
|
|
121807
122380
|
this.lastUsedAt.delete(key);
|
|
121808
122381
|
this.clearQuietFlushTimer(runtime);
|
|
122382
|
+
this.teardownSpectate(runtime);
|
|
121809
122383
|
try {
|
|
121810
122384
|
runtime.inputController.close();
|
|
121811
122385
|
await this.awaitQueryReturn(runtime.query, 5e3, agentId);
|
|
@@ -121822,6 +122396,165 @@ ${lines.join("\n")}`;
|
|
|
121822
122396
|
cwd: proc.cwd
|
|
121823
122397
|
});
|
|
121824
122398
|
}
|
|
122399
|
+
/**
|
|
122400
|
+
* Emit `agent:error` for the active reply and every queued/merged/buffered task,
|
|
122401
|
+
* then clear those queues. Used by both the SDK stream-crash path and the
|
|
122402
|
+
* reply-stall watchdog so a torn-down runtime never leaves a carrier reply
|
|
122403
|
+
* stuck in-flight on the server (which would keep absorbing new user messages
|
|
122404
|
+
* as steers of a dead turn).
|
|
122405
|
+
*/
|
|
122406
|
+
failPendingTasksWithError(runtime, errorText, fallbackId) {
|
|
122407
|
+
const pending = [];
|
|
122408
|
+
if (runtime.currentTask) pending.push(runtime.currentTask);
|
|
122409
|
+
pending.push(...runtime.injectedTasks, ...runtime.mergedTasks, ...runtime.planModeBuffer);
|
|
122410
|
+
runtime.currentTask = null;
|
|
122411
|
+
runtime.injectedTasks = [];
|
|
122412
|
+
runtime.mergedTasks = [];
|
|
122413
|
+
runtime.planModeBuffer = [];
|
|
122414
|
+
if (pending.length === 0) return { pendingCount: 0 };
|
|
122415
|
+
const carrier = pending[0];
|
|
122416
|
+
const mergedTasks = pending.slice(1);
|
|
122417
|
+
logger14.warn("Pending tasks failure consolidated", {
|
|
122418
|
+
agentId: runtime.agentId,
|
|
122419
|
+
scope: scopeKey(runtime.scope),
|
|
122420
|
+
pendingCount: pending.length,
|
|
122421
|
+
carrierAckId: carrier.replyMessageId,
|
|
122422
|
+
mergedAckIds: mergedTasks.map((t) => t.replyMessageId),
|
|
122423
|
+
traceId: carrier.traceId,
|
|
122424
|
+
...fallbackId ? { fallbackId } : {}
|
|
122425
|
+
});
|
|
122426
|
+
this.emit({
|
|
122427
|
+
type: "agent:error",
|
|
122428
|
+
payload: {
|
|
122429
|
+
agentId: runtime.agentId,
|
|
122430
|
+
conversationId: carrier.conversationId,
|
|
122431
|
+
ackId: carrier.replyMessageId,
|
|
122432
|
+
traceId: carrier.traceId,
|
|
122433
|
+
error: errorText
|
|
122434
|
+
}
|
|
122435
|
+
});
|
|
122436
|
+
for (const task of mergedTasks) {
|
|
122437
|
+
this.emit({
|
|
122438
|
+
type: "agent:merged",
|
|
122439
|
+
payload: {
|
|
122440
|
+
agentId: runtime.agentId,
|
|
122441
|
+
conversationId: task.conversationId,
|
|
122442
|
+
ackId: task.replyMessageId,
|
|
122443
|
+
mergedIntoAckId: carrier.replyMessageId,
|
|
122444
|
+
groupId: task.groupId,
|
|
122445
|
+
traceId: task.traceId
|
|
122446
|
+
}
|
|
122447
|
+
});
|
|
122448
|
+
}
|
|
122449
|
+
return { pendingCount: pending.length };
|
|
122450
|
+
}
|
|
122451
|
+
/**
|
|
122452
|
+
* Recover an in-flight reply that started but went silent past
|
|
122453
|
+
* `replyStallTimeoutMs` (see the reply-stall fast path in `evictIdle`). The
|
|
122454
|
+
* underlying SDK turn is wedged with no observable progress and no error, so:
|
|
122455
|
+
* 1. clear the (likely interrupted/dangling) session so the next dispatch
|
|
122456
|
+
* starts fresh instead of resuming the same wedged transcript;
|
|
122457
|
+
* 2. release the carrier reply + queued steers via `agent:error` so the
|
|
122458
|
+
* client stops waiting and the next user message starts a brand-new reply;
|
|
122459
|
+
* 3. tear the wedged runtime down.
|
|
122460
|
+
*/
|
|
122461
|
+
async recoverStalledReply(proc, silentMs) {
|
|
122462
|
+
if (proc.status === "dead") return;
|
|
122463
|
+
const runtime = this.asRuntime(proc);
|
|
122464
|
+
const key = runtimeKey(proc.agentId, proc.scope);
|
|
122465
|
+
const replyStallFallbackId = createFallbackId();
|
|
122466
|
+
const stallTraceId = proc.currentTask?.traceId;
|
|
122467
|
+
logger14.warn("Reply stall watchdog: in-flight reply silent too long, recovering", {
|
|
122468
|
+
agentId: proc.agentId,
|
|
122469
|
+
scope: scopeKey(proc.scope),
|
|
122470
|
+
silentMs,
|
|
122471
|
+
replyStallTimeoutMs: this.queryConfig.replyStallTimeoutMs,
|
|
122472
|
+
replyMessageId: proc.currentTask?.replyMessageId,
|
|
122473
|
+
injectedTaskCount: runtime.injectedTasks.length,
|
|
122474
|
+
lastSdkEventAt: new Date(proc.lastSdkEventAt).toISOString(),
|
|
122475
|
+
fallbackId: replyStallFallbackId,
|
|
122476
|
+
// Breadcrumb: what the wedged turn was doing the instant it went silent.
|
|
122477
|
+
// (subagent Task call? mid tool_use? which provider?) — the difference
|
|
122478
|
+
// between a one-off and a systemic provider/tool stall.
|
|
122479
|
+
model: proc.model ?? "(unknown)",
|
|
122480
|
+
lastSdkEvent: proc.lastSdkEventInfo,
|
|
122481
|
+
currentBlockType: proc.currentBlockType,
|
|
122482
|
+
currentToolName: proc.currentToolName,
|
|
122483
|
+
openMcpInvocationId: proc.currentMcpInvocationId ?? null
|
|
122484
|
+
});
|
|
122485
|
+
logFallback(logger14, {
|
|
122486
|
+
fallbackId: replyStallFallbackId,
|
|
122487
|
+
type: "reply_stall",
|
|
122488
|
+
phase: "detected",
|
|
122489
|
+
expected: false,
|
|
122490
|
+
traceId: stallTraceId,
|
|
122491
|
+
context: {
|
|
122492
|
+
agentId: proc.agentId,
|
|
122493
|
+
scope: scopeKey(proc.scope),
|
|
122494
|
+
silentMs,
|
|
122495
|
+
model: proc.model ?? "(unknown)",
|
|
122496
|
+
replyMessageId: proc.currentTask?.replyMessageId ?? null,
|
|
122497
|
+
currentToolName: proc.currentToolName ?? null,
|
|
122498
|
+
lastSdkEventType: proc.lastSdkEventInfo?.type ?? null,
|
|
122499
|
+
injectedTaskCount: runtime.injectedTasks.length,
|
|
122500
|
+
mergedTaskCount: runtime.mergedTasks.length,
|
|
122501
|
+
planModeBufferCount: runtime.planModeBuffer.length
|
|
122502
|
+
}
|
|
122503
|
+
});
|
|
122504
|
+
this.sessionStore.delete(proc.agentId, proc.scope);
|
|
122505
|
+
this.dispatchMemory.deleteScope(proc.agentId, proc.scope);
|
|
122506
|
+
const failSummary = this.failPendingTasksWithError(
|
|
122507
|
+
runtime,
|
|
122508
|
+
"\u56DE\u590D\u957F\u65F6\u95F4\u65E0\u54CD\u5E94\uFF0C\u5DF2\u91CD\u7F6E\u8BE5\u4F1A\u8BDD\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u6D88\u606F\u3002",
|
|
122509
|
+
replyStallFallbackId
|
|
122510
|
+
);
|
|
122511
|
+
proc.status = "dead";
|
|
122512
|
+
this.agents.delete(key);
|
|
122513
|
+
this.lastUsedAt.delete(key);
|
|
122514
|
+
this.clearQuietFlushTimer(runtime);
|
|
122515
|
+
let queryCloseOk = true;
|
|
122516
|
+
try {
|
|
122517
|
+
runtime.inputController.close();
|
|
122518
|
+
await this.awaitQueryReturn(runtime.query, 5e3, proc.agentId);
|
|
122519
|
+
} catch (e) {
|
|
122520
|
+
queryCloseOk = false;
|
|
122521
|
+
logger14.error("reply_stall: close query failed", {
|
|
122522
|
+
agentId: proc.agentId,
|
|
122523
|
+
scope: scopeKey(proc.scope),
|
|
122524
|
+
error: e
|
|
122525
|
+
});
|
|
122526
|
+
}
|
|
122527
|
+
logFallback(logger14, {
|
|
122528
|
+
fallbackId: replyStallFallbackId,
|
|
122529
|
+
type: "reply_stall",
|
|
122530
|
+
phase: "applied",
|
|
122531
|
+
expected: false,
|
|
122532
|
+
traceId: stallTraceId,
|
|
122533
|
+
context: {
|
|
122534
|
+
agentId: proc.agentId,
|
|
122535
|
+
scope: scopeKey(proc.scope),
|
|
122536
|
+
sessionDeleted: true,
|
|
122537
|
+
failedTaskCount: failSummary.pendingCount,
|
|
122538
|
+
queryClosed: queryCloseOk
|
|
122539
|
+
}
|
|
122540
|
+
});
|
|
122541
|
+
logFallback(logger14, {
|
|
122542
|
+
fallbackId: replyStallFallbackId,
|
|
122543
|
+
type: "reply_stall",
|
|
122544
|
+
phase: "outcome",
|
|
122545
|
+
expected: false,
|
|
122546
|
+
traceId: stallTraceId,
|
|
122547
|
+
context: {
|
|
122548
|
+
agentId: proc.agentId,
|
|
122549
|
+
scope: scopeKey(proc.scope),
|
|
122550
|
+
failedTaskCount: failSummary.pendingCount
|
|
122551
|
+
},
|
|
122552
|
+
outcome: {
|
|
122553
|
+
result: "session_reset_awaiting_user",
|
|
122554
|
+
dataLossSuspected: failSummary.pendingCount > 0
|
|
122555
|
+
}
|
|
122556
|
+
});
|
|
122557
|
+
}
|
|
121825
122558
|
async recoverFromRestart(agents) {
|
|
121826
122559
|
const lockSnapshot = readCronLockSnapshot();
|
|
121827
122560
|
logger14.info("Recovering Agent sessions after restart", {
|
|
@@ -121944,58 +122677,7 @@ ${lines.join("\n")}`;
|
|
|
121944
122677
|
this.lastUsedAt.delete(key);
|
|
121945
122678
|
const errorText = isResumeFail ? `\u4F1A\u8BDD\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u6D88\u606F\uFF08${errMsg}\uFF09` : `Agent query crashed: ${errMsg}`;
|
|
121946
122679
|
const emittedErrorText = isUnsupportedVisionInput ? "Current model/backend does not support image multimodal input. This image message failed; AHChat has cleared this scope session and future messages will send attachments as paths/text references." : errorText;
|
|
121947
|
-
|
|
121948
|
-
this.emit({
|
|
121949
|
-
type: "agent:error",
|
|
121950
|
-
payload: {
|
|
121951
|
-
agentId: runtime.agentId,
|
|
121952
|
-
conversationId: runtime.currentTask.conversationId,
|
|
121953
|
-
ackId: runtime.currentTask.replyMessageId,
|
|
121954
|
-
traceId: runtime.currentTask.traceId,
|
|
121955
|
-
error: emittedErrorText
|
|
121956
|
-
}
|
|
121957
|
-
});
|
|
121958
|
-
runtime.currentTask = null;
|
|
121959
|
-
}
|
|
121960
|
-
for (const task of runtime.injectedTasks) {
|
|
121961
|
-
this.emit({
|
|
121962
|
-
type: "agent:error",
|
|
121963
|
-
payload: {
|
|
121964
|
-
agentId: runtime.agentId,
|
|
121965
|
-
conversationId: task.conversationId,
|
|
121966
|
-
ackId: task.replyMessageId,
|
|
121967
|
-
traceId: task.traceId,
|
|
121968
|
-
error: emittedErrorText
|
|
121969
|
-
}
|
|
121970
|
-
});
|
|
121971
|
-
}
|
|
121972
|
-
runtime.injectedTasks = [];
|
|
121973
|
-
for (const task of runtime.mergedTasks) {
|
|
121974
|
-
this.emit({
|
|
121975
|
-
type: "agent:error",
|
|
121976
|
-
payload: {
|
|
121977
|
-
agentId: runtime.agentId,
|
|
121978
|
-
conversationId: task.conversationId,
|
|
121979
|
-
ackId: task.replyMessageId,
|
|
121980
|
-
traceId: task.traceId,
|
|
121981
|
-
error: emittedErrorText
|
|
121982
|
-
}
|
|
121983
|
-
});
|
|
121984
|
-
}
|
|
121985
|
-
runtime.mergedTasks = [];
|
|
121986
|
-
for (const task of runtime.planModeBuffer) {
|
|
121987
|
-
this.emit({
|
|
121988
|
-
type: "agent:error",
|
|
121989
|
-
payload: {
|
|
121990
|
-
agentId: runtime.agentId,
|
|
121991
|
-
conversationId: task.conversationId,
|
|
121992
|
-
ackId: task.replyMessageId,
|
|
121993
|
-
traceId: task.traceId,
|
|
121994
|
-
error: emittedErrorText
|
|
121995
|
-
}
|
|
121996
|
-
});
|
|
121997
|
-
}
|
|
121998
|
-
runtime.planModeBuffer = [];
|
|
122680
|
+
this.failPendingTasksWithError(runtime, emittedErrorText);
|
|
121999
122681
|
}
|
|
122000
122682
|
}
|
|
122001
122683
|
getStatus(agentId, scope = { kind: "single" }) {
|
|
@@ -122009,6 +122691,18 @@ ${lines.join("\n")}`;
|
|
|
122009
122691
|
}
|
|
122010
122692
|
return [...ids];
|
|
122011
122693
|
}
|
|
122694
|
+
/** Unified signal: is the turn legitimately waiting on a live external call that emits no
|
|
122695
|
+
* parent heartbeat? Used by BOTH the reply-stall fast path and the zombie watchdog so neither
|
|
122696
|
+
* tears down a turn that is merely slow. Returns the reason for diagnostics, or null when idle.
|
|
122697
|
+
* - open_tool: regular tool, MCP tool, AskUserQuestion wait, or ExitPlanMode (tool_use open).
|
|
122698
|
+
* - subagent: Task/Agent in flight (its inner tool_results clear activeToolUseStartedAt).
|
|
122699
|
+
* - compact: bridge-injected /compact running. */
|
|
122700
|
+
busyReason(proc) {
|
|
122701
|
+
if (proc.activeToolUseStartedAt != null || this.latestOpenToolUse(proc) != null) return "open_tool";
|
|
122702
|
+
if ((proc.activeSubagentTaskIds?.size ?? 0) > 0) return "subagent";
|
|
122703
|
+
if (proc.compactInProgress === true) return "compact";
|
|
122704
|
+
return null;
|
|
122705
|
+
}
|
|
122012
122706
|
latestOpenToolUse(proc) {
|
|
122013
122707
|
for (let i = proc.contentBlocks.length - 1; i >= 0; i -= 1) {
|
|
122014
122708
|
const block = proc.contentBlocks[i];
|
|
@@ -122157,7 +122851,7 @@ ${lines.join("\n")}`;
|
|
|
122157
122851
|
}
|
|
122158
122852
|
const task = {
|
|
122159
122853
|
content: notice,
|
|
122160
|
-
replyMessageId:
|
|
122854
|
+
replyMessageId: createScopeNoticeReplyMessageId(),
|
|
122161
122855
|
conversationId,
|
|
122162
122856
|
traceId: createTraceId(),
|
|
122163
122857
|
groupId: proc.scope.kind === "group" ? proc.scope.groupId : void 0
|
|
@@ -123244,6 +123938,7 @@ var HttpMcpRegistry = class {
|
|
|
123244
123938
|
buildForAgent(ctx) {
|
|
123245
123939
|
const mcpServers = {};
|
|
123246
123940
|
const allowedTools = [];
|
|
123941
|
+
const toolAbi = [];
|
|
123247
123942
|
const usedNames = /* @__PURE__ */ new Set();
|
|
123248
123943
|
for (const connection of this.allConnections()) {
|
|
123249
123944
|
if (!this.connectionAppliesToAgent(connection, ctx)) continue;
|
|
@@ -123252,12 +123947,18 @@ var HttpMcpRegistry = class {
|
|
|
123252
123947
|
const serverName = uniqueServerName(normalizeMcpServerName(connection.serverName), usedNames);
|
|
123253
123948
|
usedNames.add(serverName);
|
|
123254
123949
|
mcpServers[serverName] = sdkConfig;
|
|
123255
|
-
|
|
123256
|
-
|
|
123257
|
-
|
|
123258
|
-
|
|
123950
|
+
const visibleTools = connection.tools.filter((tool2) => tool2.enabled && tool2.permissionPolicy !== "always_deny");
|
|
123951
|
+
for (const tool2 of visibleTools) allowedTools.push(mcpRuntimeToolName(serverName, tool2.name));
|
|
123952
|
+
toolAbi.push({
|
|
123953
|
+
serverName,
|
|
123954
|
+
providerId: connection.providerId,
|
|
123955
|
+
transport: connection.transport,
|
|
123956
|
+
alwaysLoad: connection.alwaysLoad,
|
|
123957
|
+
isBuiltin: connection.isBuiltin,
|
|
123958
|
+
tools: visibleTools.map((tool2) => runtimeToolAbi(serverName, tool2)).sort((a, b) => a.runtimeToolName.localeCompare(b.runtimeToolName))
|
|
123959
|
+
});
|
|
123259
123960
|
}
|
|
123260
|
-
return { mcpServers, allowedTools };
|
|
123961
|
+
return { mcpServers, allowedTools, toolAbi };
|
|
123261
123962
|
}
|
|
123262
123963
|
allConnections() {
|
|
123263
123964
|
return [...this.serverConnections.values(), ...this.localConnections.values()];
|
|
@@ -123443,6 +124144,18 @@ function uniqueServerName(serverName, usedNames) {
|
|
|
123443
124144
|
while (usedNames.has(`${serverName}_${idx}`)) idx += 1;
|
|
123444
124145
|
return `${serverName}_${idx}`;
|
|
123445
124146
|
}
|
|
124147
|
+
function runtimeToolAbi(serverName, tool2) {
|
|
124148
|
+
return {
|
|
124149
|
+
name: tool2.name,
|
|
124150
|
+
runtimeToolName: mcpRuntimeToolName(serverName, tool2.name),
|
|
124151
|
+
displayName: tool2.displayName,
|
|
124152
|
+
description: tool2.description,
|
|
124153
|
+
category: tool2.category,
|
|
124154
|
+
riskLevel: tool2.riskLevel,
|
|
124155
|
+
permissionPolicy: tool2.permissionPolicy,
|
|
124156
|
+
...tool2.inputSchema !== void 0 ? { inputSchema: tool2.inputSchema } : {}
|
|
124157
|
+
};
|
|
124158
|
+
}
|
|
123446
124159
|
function buildHeaders(authType, authSecret, customHeaders) {
|
|
123447
124160
|
const headers = {};
|
|
123448
124161
|
for (const header of customHeaders) {
|
|
@@ -124099,6 +124812,7 @@ var ServerConnector = class {
|
|
|
124099
124812
|
case "agent:terminate":
|
|
124100
124813
|
case "agent:runtime_reload":
|
|
124101
124814
|
case "agent:terminate_scope":
|
|
124815
|
+
case "spectate:set":
|
|
124102
124816
|
case "agent:created":
|
|
124103
124817
|
case "agent:updated":
|
|
124104
124818
|
case "agent:workdir-updated":
|
|
@@ -125076,24 +125790,6 @@ function normalizeLocalPath(targetPath) {
|
|
|
125076
125790
|
const expanded = trimmed === "~" || trimmed.startsWith("~/") || trimmed.startsWith("~\\") ? import_node_path18.default.join(import_node_os10.default.homedir(), trimmed.slice(2)) : trimmed;
|
|
125077
125791
|
return import_node_path18.default.normalize(import_node_path18.default.resolve(expanded));
|
|
125078
125792
|
}
|
|
125079
|
-
function isAbsoluteLocalPathCandidate(value) {
|
|
125080
|
-
if (process.platform === "win32") {
|
|
125081
|
-
return /^[a-zA-Z]:[\\/]/.test(value) || /^\\\\[^\\]/.test(value);
|
|
125082
|
-
}
|
|
125083
|
-
return value.startsWith("/");
|
|
125084
|
-
}
|
|
125085
|
-
function clipboardTextToPathCandidates(value) {
|
|
125086
|
-
return value.replace(/\0/g, "\n").split(/\r?\n/).map((line) => line.trim().replace(/^"(.+)"$/, "$1")).map((line) => {
|
|
125087
|
-
if (!line.toLowerCase().startsWith("file://")) return line;
|
|
125088
|
-
try {
|
|
125089
|
-
const url2 = new URL(line);
|
|
125090
|
-
return decodeURIComponent(url2.pathname.replace(/^\/([a-zA-Z]:\/)/, "$1"));
|
|
125091
|
-
} catch (e) {
|
|
125092
|
-
logger25.debug("Failed to parse clipboard file URL", { error: e });
|
|
125093
|
-
return "";
|
|
125094
|
-
}
|
|
125095
|
-
}).filter((line) => line.length > 0 && isAbsoluteLocalPathCandidate(line));
|
|
125096
|
-
}
|
|
125097
125793
|
function normalizeClipboardIdentityKey(value) {
|
|
125098
125794
|
return process.platform === "win32" ? value.toLowerCase() : value;
|
|
125099
125795
|
}
|
|
@@ -125131,18 +125827,15 @@ function mimeTypeForFileName(fileName) {
|
|
|
125131
125827
|
}
|
|
125132
125828
|
function parseWindowsClipboardResult(stdout) {
|
|
125133
125829
|
const raw = stdout.trim();
|
|
125134
|
-
if (!raw) return { files: []
|
|
125830
|
+
if (!raw) return { files: [] };
|
|
125135
125831
|
try {
|
|
125136
125832
|
const parsed = JSON.parse(raw);
|
|
125137
|
-
if (!isRecord5(parsed)) return { files: []
|
|
125833
|
+
if (!isRecord5(parsed)) return { files: [] };
|
|
125138
125834
|
const files = Array.isArray(parsed.files) ? parsed.files.filter((item) => typeof item === "string") : [];
|
|
125139
|
-
return {
|
|
125140
|
-
files,
|
|
125141
|
-
text: typeof parsed.text === "string" ? parsed.text : ""
|
|
125142
|
-
};
|
|
125835
|
+
return { files };
|
|
125143
125836
|
} catch (e) {
|
|
125144
125837
|
logger25.debug("Windows clipboard JSON parse skipped", { error: e });
|
|
125145
|
-
return { files:
|
|
125838
|
+
return { files: [] };
|
|
125146
125839
|
}
|
|
125147
125840
|
}
|
|
125148
125841
|
async function readWindowsClipboardPathCandidates() {
|
|
@@ -125155,9 +125848,7 @@ async function readWindowsClipboardPathCandidates() {
|
|
|
125155
125848
|
" $drop = [System.Windows.Forms.Clipboard]::GetFileDropList();",
|
|
125156
125849
|
" foreach ($file in $drop) { $files += [string]$file }",
|
|
125157
125850
|
"} catch {}",
|
|
125158
|
-
|
|
125159
|
-
"try { $text = [System.Windows.Forms.Clipboard]::GetText() } catch {}",
|
|
125160
|
-
"[pscustomobject]@{ files = $files; text = $text } | ConvertTo-Json -Compress;"
|
|
125851
|
+
"[pscustomobject]@{ files = $files } | ConvertTo-Json -Compress;"
|
|
125161
125852
|
].join(" ");
|
|
125162
125853
|
try {
|
|
125163
125854
|
const { stdout } = await execFileAsync2("powershell.exe", [
|
|
@@ -125175,7 +125866,7 @@ async function readWindowsClipboardPathCandidates() {
|
|
|
125175
125866
|
maxBuffer: 1024 * 1024
|
|
125176
125867
|
});
|
|
125177
125868
|
const result = parseWindowsClipboardResult(stdout);
|
|
125178
|
-
return
|
|
125869
|
+
return result.files;
|
|
125179
125870
|
} catch (e) {
|
|
125180
125871
|
logger25.debug("Windows clipboard file read skipped", { error: e });
|
|
125181
125872
|
return [];
|
|
@@ -125581,7 +126272,7 @@ async function readStreamText(filePath, start) {
|
|
|
125581
126272
|
function parseProcessedLines(raw, cursor, fileName, fingerprint) {
|
|
125582
126273
|
const lastNewline = raw.lastIndexOf("\n");
|
|
125583
126274
|
if (lastNewline < 0) {
|
|
125584
|
-
return { entries: [], nextCursor: cursor, advanced: false };
|
|
126275
|
+
return { entries: [], nextCursor: cursor, advanced: false, reason: "partial_line" };
|
|
125585
126276
|
}
|
|
125586
126277
|
const processed = raw.slice(0, lastNewline + 1);
|
|
125587
126278
|
const lines = processed.split(/\r?\n/);
|
|
@@ -125607,7 +126298,8 @@ function parseProcessedLines(raw, cursor, fileName, fingerprint) {
|
|
|
125607
126298
|
lineNum,
|
|
125608
126299
|
...fingerprint ? { fingerprint } : {}
|
|
125609
126300
|
},
|
|
125610
|
-
advanced: true
|
|
126301
|
+
advanced: true,
|
|
126302
|
+
reason: "advanced"
|
|
125611
126303
|
};
|
|
125612
126304
|
}
|
|
125613
126305
|
function chunkEntries(entries, size) {
|
|
@@ -125665,24 +126357,55 @@ var BridgeLogUploader = class {
|
|
|
125665
126357
|
async flushOnce() {
|
|
125666
126358
|
if (this.running || this.stopped) return;
|
|
125667
126359
|
this.running = true;
|
|
126360
|
+
const startedAt = Date.now();
|
|
126361
|
+
const summary = {
|
|
126362
|
+
targetCount: 0,
|
|
126363
|
+
advancedTargetCount: 0,
|
|
126364
|
+
missingTargetCount: 0,
|
|
126365
|
+
idleTargetCount: 0,
|
|
126366
|
+
partialLineTargetCount: 0,
|
|
126367
|
+
failedTargetCount: 0,
|
|
126368
|
+
parsedEntryCount: 0,
|
|
126369
|
+
bridgeEntryCount: 0,
|
|
126370
|
+
uploadedChunkCount: 0,
|
|
126371
|
+
accepted: 0,
|
|
126372
|
+
skipped: 0
|
|
126373
|
+
};
|
|
125668
126374
|
try {
|
|
125669
126375
|
const targets = await this.resolveTargets();
|
|
126376
|
+
summary.targetCount = targets.length;
|
|
125670
126377
|
for (const target of targets) {
|
|
125671
126378
|
try {
|
|
125672
126379
|
const cursor = await readCursor(target.cursorFile);
|
|
125673
126380
|
const batch = await this.readNewEntries(target, cursor);
|
|
125674
|
-
if (!batch.advanced)
|
|
126381
|
+
if (!batch.advanced) {
|
|
126382
|
+
summary.idleTargetCount += 1;
|
|
126383
|
+
if (batch.reason === "missing_file") summary.missingTargetCount += 1;
|
|
126384
|
+
if (batch.reason === "partial_line") summary.partialLineTargetCount += 1;
|
|
126385
|
+
continue;
|
|
126386
|
+
}
|
|
126387
|
+
summary.advancedTargetCount += 1;
|
|
126388
|
+
summary.parsedEntryCount += batch.entries.length;
|
|
125675
126389
|
if (batch.entries.length > 0) {
|
|
125676
|
-
await this.uploadEntries(batch.entries);
|
|
126390
|
+
const result = await this.uploadEntries(batch.entries);
|
|
126391
|
+
summary.bridgeEntryCount += result.bridgeEntryCount;
|
|
126392
|
+
summary.uploadedChunkCount += result.uploadedChunkCount;
|
|
126393
|
+
summary.accepted += result.accepted;
|
|
126394
|
+
summary.skipped += result.skipped;
|
|
125677
126395
|
}
|
|
125678
126396
|
await writeCursor(target.cursorFile, batch.nextCursor);
|
|
125679
126397
|
} catch (e) {
|
|
126398
|
+
summary.failedTargetCount += 1;
|
|
125680
126399
|
logger28.warn("Bridge log upload target failed", { error: e, logFile: target.logFile });
|
|
125681
126400
|
}
|
|
125682
126401
|
}
|
|
125683
126402
|
} catch (e) {
|
|
125684
126403
|
logger28.warn("Bridge log upload cycle failed", { error: e });
|
|
125685
126404
|
} finally {
|
|
126405
|
+
logger28.info("Bridge log upload cycle summary", {
|
|
126406
|
+
...summary,
|
|
126407
|
+
durationMs: Date.now() - startedAt
|
|
126408
|
+
});
|
|
125686
126409
|
this.running = false;
|
|
125687
126410
|
}
|
|
125688
126411
|
}
|
|
@@ -125705,7 +126428,7 @@ var BridgeLogUploader = class {
|
|
|
125705
126428
|
} catch (e) {
|
|
125706
126429
|
if (e instanceof Error && "code" in e && e.code === "ENOENT") {
|
|
125707
126430
|
logger28.debug("Bridge log file not found for upload yet", { logFile: target.logFile });
|
|
125708
|
-
return { entries: [], nextCursor: cursor, advanced: false };
|
|
126431
|
+
return { entries: [], nextCursor: cursor, advanced: false, reason: "missing_file" };
|
|
125709
126432
|
}
|
|
125710
126433
|
throw e;
|
|
125711
126434
|
}
|
|
@@ -125713,13 +126436,19 @@ var BridgeLogUploader = class {
|
|
|
125713
126436
|
const samePhysicalFile = !fingerprint || !cursor.fingerprint || cursor.fingerprint === fingerprint;
|
|
125714
126437
|
const normalizedCursor = stat3.size < cursor.offset || !samePhysicalFile ? { offset: 0, lineNum: 0, ...fingerprint ? { fingerprint } : {} } : { ...cursor, ...fingerprint ? { fingerprint } : {} };
|
|
125715
126438
|
if (stat3.size <= normalizedCursor.offset) {
|
|
125716
|
-
return { entries: [], nextCursor: normalizedCursor, advanced: false };
|
|
126439
|
+
return { entries: [], nextCursor: normalizedCursor, advanced: false, reason: "no_new_entries" };
|
|
125717
126440
|
}
|
|
125718
126441
|
const raw = await readStreamText(target.logFile, normalizedCursor.offset);
|
|
125719
126442
|
return parseProcessedLines(raw, normalizedCursor, target.uploadedFileName, fingerprint);
|
|
125720
126443
|
}
|
|
125721
126444
|
async uploadEntries(entries) {
|
|
125722
126445
|
const bridgeEntries = entries.filter((entry) => entry.source === "bridge");
|
|
126446
|
+
const result = {
|
|
126447
|
+
bridgeEntryCount: bridgeEntries.length,
|
|
126448
|
+
uploadedChunkCount: 0,
|
|
126449
|
+
accepted: 0,
|
|
126450
|
+
skipped: 0
|
|
126451
|
+
};
|
|
125723
126452
|
for (const chunk of chunkEntries(bridgeEntries, this.options.batchSize)) {
|
|
125724
126453
|
const res = await fetch(`${this.options.serverApiUrl}/api/logs/upload`, {
|
|
125725
126454
|
method: "POST",
|
|
@@ -125734,14 +126463,18 @@ var BridgeLogUploader = class {
|
|
|
125734
126463
|
})
|
|
125735
126464
|
});
|
|
125736
126465
|
if (!res.ok) {
|
|
125737
|
-
const
|
|
126466
|
+
const body2 = await res.text().catch((e) => {
|
|
125738
126467
|
logger28.debug("Failed to read log upload error body", { error: e });
|
|
125739
126468
|
return "";
|
|
125740
126469
|
});
|
|
125741
|
-
throw new Error(`upload failed HTTP ${res.status}: ${
|
|
126470
|
+
throw new Error(`upload failed HTTP ${res.status}: ${body2.slice(0, 160)}`);
|
|
125742
126471
|
}
|
|
125743
|
-
await res.json();
|
|
126472
|
+
const body = await res.json();
|
|
126473
|
+
result.uploadedChunkCount += 1;
|
|
126474
|
+
result.accepted += typeof body.accepted === "number" ? body.accepted : 0;
|
|
126475
|
+
result.skipped += typeof body.skipped === "number" ? body.skipped : 0;
|
|
125744
126476
|
}
|
|
126477
|
+
return result;
|
|
125745
126478
|
}
|
|
125746
126479
|
};
|
|
125747
126480
|
|
|
@@ -127739,6 +128472,33 @@ function syncLocalRuntimeSkills(skillStore, localSkills, options = {}) {
|
|
|
127739
128472
|
]);
|
|
127740
128473
|
}
|
|
127741
128474
|
|
|
128475
|
+
// src/processOutput.ts
|
|
128476
|
+
init_cjs_shims();
|
|
128477
|
+
var protectedStreams2 = /* @__PURE__ */ new WeakSet();
|
|
128478
|
+
var reportedErrors = /* @__PURE__ */ new WeakSet();
|
|
128479
|
+
function reportWriteError(error51, onError) {
|
|
128480
|
+
if (typeof error51 === "object" && error51 !== null) {
|
|
128481
|
+
if (reportedErrors.has(error51)) return;
|
|
128482
|
+
reportedErrors.add(error51);
|
|
128483
|
+
}
|
|
128484
|
+
onError(error51);
|
|
128485
|
+
}
|
|
128486
|
+
function safeWriteProcessOutput(stream, text, onError) {
|
|
128487
|
+
if (!stream) return;
|
|
128488
|
+
if (stream.destroyed || stream.writableEnded) return;
|
|
128489
|
+
if (typeof stream === "object" && typeof stream.on === "function" && !protectedStreams2.has(stream)) {
|
|
128490
|
+
protectedStreams2.add(stream);
|
|
128491
|
+
stream.on("error", (e) => reportWriteError(e, onError));
|
|
128492
|
+
}
|
|
128493
|
+
try {
|
|
128494
|
+
stream.write(text, (error51) => {
|
|
128495
|
+
if (error51) reportWriteError(error51, onError);
|
|
128496
|
+
});
|
|
128497
|
+
} catch (e) {
|
|
128498
|
+
reportWriteError(e, onError);
|
|
128499
|
+
}
|
|
128500
|
+
}
|
|
128501
|
+
|
|
127742
128502
|
// src/start.ts
|
|
127743
128503
|
var logger41 = createModuleLogger("bridge");
|
|
127744
128504
|
var NODE_USER_UID2 = 1e3;
|
|
@@ -127825,14 +128585,16 @@ async function startBridge(config2) {
|
|
|
127825
128585
|
const claudeRuntime = resolveClaudeRuntime();
|
|
127826
128586
|
logClaudeRuntimeResolution(claudeRuntime);
|
|
127827
128587
|
if (!claudeRuntime.ok || !claudeRuntime.path) {
|
|
127828
|
-
|
|
128588
|
+
safeWriteProcessOutput(
|
|
128589
|
+
process.stderr,
|
|
127829
128590
|
`
|
|
127830
128591
|
Claude runtime is unavailable.
|
|
127831
128592
|
|
|
127832
128593
|
${claudeRuntime.error ?? "Install Claude Code manually or use the bundled desktop runtime."}
|
|
127833
128594
|
|
|
127834
128595
|
Reinstall @fangyb/ahchat-bridge with npm optional dependencies, set AHCHAT_CLAUDE_EXECUTABLE to a valid Claude Code binary path, install Claude Code, or use ALL-CAN Desktop with its bundled runtime.
|
|
127835
|
-
|
|
128596
|
+
`,
|
|
128597
|
+
(e) => logger41.error("Bridge process stderr write failed", { error: e })
|
|
127836
128598
|
);
|
|
127837
128599
|
process.exit(1);
|
|
127838
128600
|
}
|
|
@@ -127889,12 +128651,14 @@ Reinstall @fangyb/ahchat-bridge with npm optional dependencies, set AHCHAT_CLAUD
|
|
|
127889
128651
|
claudeRuntimeVersion: claudeRuntime.version ?? null
|
|
127890
128652
|
});
|
|
127891
128653
|
const shouldPrintRawBridgeToken = process.stdout.isTTY && process.env.AHCHAT_SUPPRESS_BRIDGE_TOKEN_STDOUT !== "1";
|
|
127892
|
-
|
|
128654
|
+
safeWriteProcessOutput(
|
|
128655
|
+
process.stdout,
|
|
127893
128656
|
`
|
|
127894
128657
|
Bridge token (register this machine at Settings \u2192 \u5DF2\u8FDE\u63A5\u7684\u673A\u5668):
|
|
127895
128658
|
${shouldPrintRawBridgeToken ? config2.bridgeToken : "***"}
|
|
127896
128659
|
|
|
127897
|
-
|
|
128660
|
+
`,
|
|
128661
|
+
(e) => logger41.error("Bridge process stdout write failed", { error: e })
|
|
127898
128662
|
);
|
|
127899
128663
|
wsMetrics.start(5e3);
|
|
127900
128664
|
const sessionStore = new SessionStore(config2.dataDir);
|
|
@@ -128693,6 +129457,19 @@ Bridge token (register this machine at Settings \u2192 \u5DF2\u8FDE\u63A5\u7684\
|
|
|
128693
129457
|
});
|
|
128694
129458
|
await agentManager.terminateScope(msg.payload.agentId, msg.payload.scope);
|
|
128695
129459
|
break;
|
|
129460
|
+
case "spectate:set":
|
|
129461
|
+
logger41.info("spectate:set received", {
|
|
129462
|
+
agentId: msg.payload.agentId,
|
|
129463
|
+
scope: msg.payload.scope,
|
|
129464
|
+
action: msg.payload.action,
|
|
129465
|
+
traceId: msg.payload.traceId
|
|
129466
|
+
});
|
|
129467
|
+
await agentManager.setSpectate(
|
|
129468
|
+
msg.payload.agentId,
|
|
129469
|
+
msg.payload.scope,
|
|
129470
|
+
msg.payload.action
|
|
129471
|
+
);
|
|
129472
|
+
break;
|
|
128696
129473
|
case "agent:created":
|
|
128697
129474
|
agentRegistry.upsert(msg.payload.agent);
|
|
128698
129475
|
ensureLocalWorkdirPath(msg.payload.agent.workingDirectory, "agent:created", {
|
|
@@ -128910,8 +129687,12 @@ function writeAlreadyRunningMessage(error51) {
|
|
|
128910
129687
|
` ${buildStopCommand(error51.pid)}`,
|
|
128911
129688
|
""
|
|
128912
129689
|
];
|
|
128913
|
-
|
|
128914
|
-
|
|
129690
|
+
safeWriteProcessOutput(
|
|
129691
|
+
process.stdout,
|
|
129692
|
+
`${lines.join("\n")}
|
|
129693
|
+
`,
|
|
129694
|
+
(e) => logger42.error("Bridge already-running message write failed", { error: e })
|
|
129695
|
+
);
|
|
128915
129696
|
}
|
|
128916
129697
|
function handleBridgeStartError(e, message) {
|
|
128917
129698
|
if (isBridgeAlreadyRunningError(e)) {
|