@qwen-code/qwen-code 0.18.1-nightly.20260616.a68b2e1e7 → 0.18.1-preview.1
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/README.md +2 -1
- package/bundled/qc-helper/docs/features/channels/feishu.md +16 -0
- package/bundled/qc-helper/docs/features/mcp.md +1 -1
- package/bundled/qc-helper/docs/features/sub-agents.md +3 -3
- package/bundled/qc-helper/docs/qwen-serve.md +18 -7
- package/bundled/review/SKILL.md +10 -4
- package/bundled/simplify/SKILL.md +1 -1
- package/chunks/{agent-PXMT2XR5.js → agent-ZLVQLNIP.js} +5 -5
- package/chunks/{agent-headless-SY7VJUHV.js → agent-headless-H4ZT46GX.js} +5 -5
- package/chunks/{anthropicContentGenerator-DCI26OQF.js → anthropicContentGenerator-KLBHYGH6.js} +1 -1
- package/chunks/{askUserQuestion-NDNFGC35.js → askUserQuestion-QPZXR3UO.js} +1 -1
- package/chunks/{chunk-ABRZC6FA.js → chunk-BRU4Z5BG.js} +10 -5
- package/chunks/{chunk-JZFEL3RB.js → chunk-C64WAJOC.js} +1 -1
- package/chunks/{chunk-TSBXGR73.js → chunk-HISY5FYZ.js} +4 -4
- package/chunks/{chunk-A3OEZT2F.js → chunk-L6F7VZPZ.js} +6 -6
- package/chunks/{chunk-3NRO6NHX.js → chunk-MN5RAXVB.js} +3 -3
- package/chunks/{chunk-M5PJ5QAF.js → chunk-Q6WOQSR4.js} +2 -2
- package/chunks/{chunk-UOB6KPGG.js → chunk-R53CLQY7.js} +1 -1
- package/chunks/{chunk-26QELEL2.js → chunk-RTTAC5VW.js} +1 -1
- package/chunks/{chunk-H4ZDM3N6.js → chunk-UKLVRIWE.js} +1332 -1027
- package/chunks/{chunk-VXHYMZXW.js → chunk-VIEIRAK3.js} +1 -1
- package/chunks/{chunk-OT6JA3KQ.js → chunk-YJDVHAGL.js} +1 -1
- package/chunks/{chunk-6WPY6ES3.js → chunk-ZNUMXPNK.js} +565 -48
- package/chunks/{computer-use-7SEQDSHB.js → computer-use-SWC45S44.js} +5 -5
- package/chunks/{contextCommand-KM5OWV65.js → contextCommand-O5DLQUIZ.js} +7 -7
- package/chunks/{cron-create-7CXEAJ2K.js → cron-create-DQKRQMCP.js} +1 -1
- package/chunks/{cron-delete-2FQYYNQ6.js → cron-delete-DOFPHFTI.js} +1 -1
- package/chunks/{cron-list-QCAJ73XE.js → cron-list-RCVOO3CB.js} +1 -1
- package/chunks/{dist-PF2IYSMD.js → dist-UH7CYT7F.js} +1 -1
- package/chunks/{edit-BMUKPLA7.js → edit-J7M33W4D.js} +6 -6
- package/chunks/{enter-worktree-LXJ5WJ5A.js → enter-worktree-RCCPIOG6.js} +5 -5
- package/chunks/{enterPlanMode-QWRZ54ZF.js → enterPlanMode-EC7HWVXV.js} +5 -5
- package/chunks/{exit-worktree-5HTQPNZO.js → exit-worktree-V3OVN22U.js} +5 -5
- package/chunks/{exitPlanMode-5WQAXNDA.js → exitPlanMode-P3F5VTWX.js} +7 -6
- package/chunks/{geminiContentGenerator-CAKHT5YE.js → geminiContentGenerator-E2LZQIFZ.js} +1 -1
- package/chunks/{glob-5DN6NSCD.js → glob-ENPPHN24.js} +5 -5
- package/chunks/{grep-BJILOLCD.js → grep-RXZMZKHV.js} +5 -5
- package/chunks/{ls-XVGXRYWD.js → ls-TRD77UTS.js} +1 -1
- package/chunks/{lsp-S6SHPULC.js → lsp-2VFWQPZS.js} +1 -1
- package/chunks/{monitor-SUEMSRN3.js → monitor-YYWM7RUX.js} +5 -5
- package/chunks/{notebook-edit-6F6Z5P6U.js → notebook-edit-L6OODJTK.js} +6 -6
- package/chunks/{openaiContentGenerator-DO27LL6O.js → openaiContentGenerator-BPRGR5FJ.js} +5 -5
- package/chunks/{qwenContentGenerator-DQLGLQSH.js → qwenContentGenerator-ENMXX47B.js} +7 -7
- package/chunks/{read-file-3TBLYTOQ.js → read-file-3VASWJKO.js} +3 -3
- package/chunks/{ripGrep-3INYT3QV.js → ripGrep-67IQWCR7.js} +5 -5
- package/chunks/{scheduler-23KQW6CX.js → scheduler-TAPJOQHX.js} +5 -5
- package/chunks/{send-message-SMNR5DBG.js → send-message-QZOC5GA2.js} +1 -1
- package/chunks/{serve-Y5E4LKUI.js → serve-CQF2R7SG.js} +709 -26
- package/chunks/{shell-4H6XQXVY.js → shell-ZLBFZ75G.js} +5 -5
- package/chunks/{skill-SE6FECZR.js → skill-BZ2NCCJN.js} +3 -3
- package/chunks/{src-76DUBH3A.js → src-ASRB3EO3.js} +11 -5
- package/chunks/{syntheticOutput-KMNF7YG6.js → syntheticOutput-WJSUK4SZ.js} +2 -2
- package/chunks/{task-create-LIJHK75G.js → task-create-GGSC27HO.js} +2 -2
- package/chunks/{task-list-S4GNSILM.js → task-list-EDHHHSK4.js} +1 -1
- package/chunks/{task-stop-3GBRYJHM.js → task-stop-WR5PDVZY.js} +1 -1
- package/chunks/{task-update-F3UTVJMS.js → task-update-UR7NUHBV.js} +2 -2
- package/chunks/{team-create-Q5DTDDH4.js → team-create-NXTYUYLE.js} +5 -5
- package/chunks/{team-delete-54434EB7.js → team-delete-FC33URJK.js} +1 -1
- package/chunks/{todoWrite-4ENGSBUX.js → todoWrite-GO2ME7ZV.js} +1 -1
- package/chunks/{tool-search-ABZMSDTU.js → tool-search-GYO3ZDMH.js} +3 -3
- package/chunks/{web-fetch-RHZMF3MP.js → web-fetch-NLLATYIL.js} +2 -2
- package/chunks/{workflow-NEMDQB75.js → workflow-KZLZUDHE.js} +249 -24
- package/chunks/{write-file-VAEHZPSL.js → write-file-AUXVL5D2.js} +6 -6
- package/cli.js +545 -184
- package/package.json +2 -2
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
InvalidSessionMetadataError,
|
|
23
23
|
InvalidSessionScopeError,
|
|
24
24
|
MAX_WORKSPACE_PATH_LENGTH,
|
|
25
|
+
MID_TURN_QUEUE_DRAIN_METHOD,
|
|
25
26
|
McpServerNotFoundError,
|
|
26
27
|
McpServerRestartFailedError,
|
|
27
28
|
MissingCliEntryError,
|
|
@@ -65,7 +66,7 @@ import {
|
|
|
65
66
|
loadSettings,
|
|
66
67
|
mapDomainErrorToErrorKind,
|
|
67
68
|
reloadEnvironment
|
|
68
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-BRU4Z5BG.js";
|
|
69
70
|
import {
|
|
70
71
|
ClientSideConnection,
|
|
71
72
|
PROTOCOL_VERSION,
|
|
@@ -76,7 +77,7 @@ import {
|
|
|
76
77
|
SUPPORTED_LANGUAGES,
|
|
77
78
|
writeStderrLine,
|
|
78
79
|
writeStdoutLine
|
|
79
|
-
} from "./chunk-
|
|
80
|
+
} from "./chunk-R53CLQY7.js";
|
|
80
81
|
import {
|
|
81
82
|
ALL_PROVIDERS,
|
|
82
83
|
APPROVAL_MODES,
|
|
@@ -107,9 +108,9 @@ import {
|
|
|
107
108
|
resolveBaseUrl,
|
|
108
109
|
shouldShowStep,
|
|
109
110
|
writeWorkspaceContextFile
|
|
110
|
-
} from "./chunk-
|
|
111
|
+
} from "./chunk-UKLVRIWE.js";
|
|
111
112
|
import "./chunk-K5PGHDBN.js";
|
|
112
|
-
import "./chunk-
|
|
113
|
+
import "./chunk-VIEIRAK3.js";
|
|
113
114
|
import "./chunk-O4PICXES.js";
|
|
114
115
|
import "./chunk-TW522KN6.js";
|
|
115
116
|
import "./chunk-BJ5HQ23U.js";
|
|
@@ -153,14 +154,14 @@ import {
|
|
|
153
154
|
resolveTelemetrySettings,
|
|
154
155
|
shutdownTelemetry,
|
|
155
156
|
withDaemonRequestSpan
|
|
156
|
-
} from "./chunk-
|
|
157
|
+
} from "./chunk-L6F7VZPZ.js";
|
|
157
158
|
import "./chunk-3PJXIDKI.js";
|
|
158
159
|
import "./chunk-UWCTAVOD.js";
|
|
159
160
|
import "./chunk-OFEVLU4C.js";
|
|
160
161
|
import "./chunk-IQHSD7K5.js";
|
|
161
162
|
import "./chunk-LYRSMKLS.js";
|
|
162
|
-
import "./chunk-
|
|
163
|
-
import "./chunk-
|
|
163
|
+
import "./chunk-RTTAC5VW.js";
|
|
164
|
+
import "./chunk-ZNUMXPNK.js";
|
|
164
165
|
import {
|
|
165
166
|
QwenOAuth2Client,
|
|
166
167
|
QwenOAuthPollError,
|
|
@@ -17129,9 +17130,6 @@ var MultiClientPermissionMediator = class {
|
|
|
17129
17130
|
}
|
|
17130
17131
|
};
|
|
17131
17132
|
|
|
17132
|
-
// packages/acp-bridge/src/bridgeTypes.ts
|
|
17133
|
-
init_esbuild_shims();
|
|
17134
|
-
|
|
17135
17133
|
// packages/acp-bridge/src/bridgeOptions.ts
|
|
17136
17134
|
init_esbuild_shims();
|
|
17137
17135
|
|
|
@@ -17409,6 +17407,7 @@ function sliceLineRange(content, startLine, endLine) {
|
|
|
17409
17407
|
return content.slice(offset, end > offset ? end - 1 : end);
|
|
17410
17408
|
}
|
|
17411
17409
|
__name(sliceLineRange, "sliceLineRange");
|
|
17410
|
+
var MID_TURN_MESSAGE_INJECTED_EVENT = "mid_turn_message_injected";
|
|
17412
17411
|
var BridgeClient = class {
|
|
17413
17412
|
constructor(resolveEntry, resolvePendingRestoreEvents, mediator, permissionTimeoutMs, maxPendingPerSession, fileSystem, onModelPromoted, onModePromoted) {
|
|
17414
17413
|
this.resolveEntry = resolveEntry;
|
|
@@ -17551,6 +17550,49 @@ var BridgeClient = class {
|
|
|
17551
17550
|
* call and exits on settle (success or failure).
|
|
17552
17551
|
*/
|
|
17553
17552
|
inFlightRestoreIds = /* @__PURE__ */ new Set();
|
|
17553
|
+
/**
|
|
17554
|
+
* Handle child->bridge ACP `extMethod` requests (calls that expect a
|
|
17555
|
+
* response, unlike `extNotification`). The only method served today is
|
|
17556
|
+
* `craft/drainMidTurnQueue`: the ACP child calls it between tool batches to
|
|
17557
|
+
* pull any messages the browser queued mid-turn. We splice the per-session
|
|
17558
|
+
* queue, return them to the child as the response, and — when non-empty —
|
|
17559
|
+
* publish a `mid_turn_message_injected` SSE frame so the browser can move
|
|
17560
|
+
* those messages out of its pending queue (a dedupe signal, not a transcript
|
|
17561
|
+
* render). Unknown methods reject with ACP `methodNotFound` (-32601), matching
|
|
17562
|
+
* the SDK's
|
|
17563
|
+
* default for an unimplemented client surface; the child's drain caller
|
|
17564
|
+
* treats that as "drain unsupported" and stops asking.
|
|
17565
|
+
*/
|
|
17566
|
+
async extMethod(method, params) {
|
|
17567
|
+
if (method !== MID_TURN_QUEUE_DRAIN_METHOD) {
|
|
17568
|
+
throw RequestError.methodNotFound(method);
|
|
17569
|
+
}
|
|
17570
|
+
const sessionId = typeof params["sessionId"] === "string" ? params["sessionId"] : void 0;
|
|
17571
|
+
if (!sessionId) return { messages: [] };
|
|
17572
|
+
const entry = this.resolveEntry(sessionId);
|
|
17573
|
+
if (!entry) return { messages: [] };
|
|
17574
|
+
const drained = entry.midTurnMessageQueue.splice(0);
|
|
17575
|
+
const messages = drained.map((item) => item.text);
|
|
17576
|
+
if (drained.length > 0) {
|
|
17577
|
+
const byOriginator = /* @__PURE__ */ new Map();
|
|
17578
|
+
for (const item of drained) {
|
|
17579
|
+
const group = byOriginator.get(item.originatorClientId);
|
|
17580
|
+
if (group) group.push(item.text);
|
|
17581
|
+
else byOriginator.set(item.originatorClientId, [item.text]);
|
|
17582
|
+
}
|
|
17583
|
+
for (const [originatorClientId, texts] of byOriginator) {
|
|
17584
|
+
const published = entry.events.publish({
|
|
17585
|
+
type: MID_TURN_MESSAGE_INJECTED_EVENT,
|
|
17586
|
+
data: { sessionId: entry.sessionId, messages: texts },
|
|
17587
|
+
...originatorClientId ? { originatorClientId } : {}
|
|
17588
|
+
});
|
|
17589
|
+
writeStderrLine2(
|
|
17590
|
+
published ? `[mid-turn] session=${entry.sessionId} drained=${texts.length}${originatorClientId ? ` originator=${originatorClientId}` : ""} injected into running turn` : `[mid-turn] session=${entry.sessionId} drained=${texts.length} echo frame dropped (bus closed); browser may resend next turn`
|
|
17591
|
+
);
|
|
17592
|
+
}
|
|
17593
|
+
}
|
|
17594
|
+
return { messages };
|
|
17595
|
+
}
|
|
17554
17596
|
/**
|
|
17555
17597
|
* Handle child->bridge ACP `extNotification` calls. Six methods are
|
|
17556
17598
|
* recognized — `qwen/notify/session/model-update`,
|
|
@@ -18540,6 +18582,7 @@ var SESSION_RECAP_TIMEOUT_MS = 6e4;
|
|
|
18540
18582
|
var SESSION_BTW_TIMEOUT_MS = 6e4;
|
|
18541
18583
|
var SHELL_COMMAND_TIMEOUT_MS = 12e4;
|
|
18542
18584
|
var MAX_SHELL_OUTPUT_FOR_HISTORY = 1e4;
|
|
18585
|
+
var MAX_MID_TURN_QUEUE_DEPTH = 20;
|
|
18543
18586
|
var DEFAULT_MAX_SESSIONS = 20;
|
|
18544
18587
|
var DEFAULT_MAX_PENDING_PROMPTS_PER_SESSION = 5;
|
|
18545
18588
|
var MAX_EVENT_RING_SIZE = 1e6;
|
|
@@ -19263,6 +19306,7 @@ function createAcpSessionBridge(opts) {
|
|
|
19263
19306
|
events,
|
|
19264
19307
|
promptQueue: Promise.resolve(),
|
|
19265
19308
|
pendingPromptCount: 0,
|
|
19309
|
+
midTurnMessageQueue: [],
|
|
19266
19310
|
modelChangeQueue: Promise.resolve(),
|
|
19267
19311
|
approvalModeQueue: Promise.resolve(),
|
|
19268
19312
|
modelPublishGeneration: 0,
|
|
@@ -19566,6 +19610,37 @@ function createAcpSessionBridge(opts) {
|
|
|
19566
19610
|
__name(closeSessionImpl, "closeSessionImpl");
|
|
19567
19611
|
startSessionReaper();
|
|
19568
19612
|
return {
|
|
19613
|
+
getDaemonStatusSnapshot() {
|
|
19614
|
+
return {
|
|
19615
|
+
limits: {
|
|
19616
|
+
maxSessions: maxSessions === Infinity ? null : maxSessions,
|
|
19617
|
+
maxPendingPromptsPerSession: maxPendingPromptsPerSession === Infinity ? null : maxPendingPromptsPerSession,
|
|
19618
|
+
eventRingSize,
|
|
19619
|
+
channelIdleTimeoutMs: resolvedChannelIdleTimeoutMs(),
|
|
19620
|
+
sessionIdleTimeoutMs
|
|
19621
|
+
},
|
|
19622
|
+
sessionCount: byId.size,
|
|
19623
|
+
pendingPermissionCount: permissionMediator.pendingCount,
|
|
19624
|
+
channelLive: !!liveChannelInfo(),
|
|
19625
|
+
permissionPolicy: permissionMediator.policy,
|
|
19626
|
+
sessions: [...byId.values()].map((entry) => ({
|
|
19627
|
+
sessionId: entry.sessionId,
|
|
19628
|
+
workspaceCwd: entry.workspaceCwd,
|
|
19629
|
+
createdAt: entry.createdAt,
|
|
19630
|
+
...entry.displayName ? { displayName: entry.displayName } : {},
|
|
19631
|
+
clientCount: entry.clientIds.size,
|
|
19632
|
+
subscriberCount: entry.events.subscriberCount,
|
|
19633
|
+
attachCount: entry.attachCount,
|
|
19634
|
+
pendingPromptCount: entry.pendingPromptCount,
|
|
19635
|
+
pendingPermissionCount: entry.pendingPermissionIds.size,
|
|
19636
|
+
hasActivePrompt: entry.promptActive,
|
|
19637
|
+
lastEventId: entry.events.lastEventId,
|
|
19638
|
+
...entry.sessionLastSeenAt !== void 0 ? { lastSeenAt: entry.sessionLastSeenAt } : {},
|
|
19639
|
+
...entry.currentModelId ? { currentModelId: entry.currentModelId } : {},
|
|
19640
|
+
...entry.currentApprovalMode ? { currentApprovalMode: entry.currentApprovalMode } : {}
|
|
19641
|
+
}))
|
|
19642
|
+
};
|
|
19643
|
+
},
|
|
19569
19644
|
get sessionCount() {
|
|
19570
19645
|
return byId.size;
|
|
19571
19646
|
},
|
|
@@ -19840,7 +19915,15 @@ function createAcpSessionBridge(opts) {
|
|
|
19840
19915
|
() => void 0,
|
|
19841
19916
|
() => void 0
|
|
19842
19917
|
);
|
|
19843
|
-
result.finally(
|
|
19918
|
+
result.finally(() => {
|
|
19919
|
+
releasePromptSlot();
|
|
19920
|
+
if (entry.pendingPromptCount === 0 && entry.midTurnMessageQueue.length > 0) {
|
|
19921
|
+
writeStderrLine2(
|
|
19922
|
+
`[mid-turn] session=${entry.sessionId} dropped ${entry.midTurnMessageQueue.length} undrained message(s) at idle; browser resends next turn`
|
|
19923
|
+
);
|
|
19924
|
+
entry.midTurnMessageQueue.length = 0;
|
|
19925
|
+
}
|
|
19926
|
+
}).catch(() => {
|
|
19844
19927
|
});
|
|
19845
19928
|
return result;
|
|
19846
19929
|
},
|
|
@@ -20545,6 +20628,29 @@ function createAcpSessionBridge(opts) {
|
|
|
20545
20628
|
recap: response.recap ?? null
|
|
20546
20629
|
};
|
|
20547
20630
|
},
|
|
20631
|
+
enqueueMidTurnMessage(sessionId, message, context) {
|
|
20632
|
+
const entry = byId.get(sessionId);
|
|
20633
|
+
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
20634
|
+
const originatorClientId = resolveTrustedClientId(
|
|
20635
|
+
entry,
|
|
20636
|
+
context?.clientId
|
|
20637
|
+
);
|
|
20638
|
+
const trimmed = message.trim();
|
|
20639
|
+
if (trimmed.length === 0 || entry.pendingPromptCount === 0) {
|
|
20640
|
+
writeStderrLine2(
|
|
20641
|
+
`[mid-turn] session=${entry.sessionId} rejected: ${trimmed.length === 0 ? "empty message" : "session idle"}; browser keeps it for next turn`
|
|
20642
|
+
);
|
|
20643
|
+
return { accepted: false };
|
|
20644
|
+
}
|
|
20645
|
+
if (entry.midTurnMessageQueue.length >= MAX_MID_TURN_QUEUE_DEPTH) {
|
|
20646
|
+
writeStderrLine2(
|
|
20647
|
+
`[mid-turn] session=${entry.sessionId} rejected: queue full (depth ${entry.midTurnMessageQueue.length} >= ${MAX_MID_TURN_QUEUE_DEPTH}); browser keeps it for next turn`
|
|
20648
|
+
);
|
|
20649
|
+
return { accepted: false };
|
|
20650
|
+
}
|
|
20651
|
+
entry.midTurnMessageQueue.push({ text: trimmed, originatorClientId });
|
|
20652
|
+
return { accepted: true };
|
|
20653
|
+
},
|
|
20548
20654
|
async generateSessionBtw(sessionId, question, signal, _context) {
|
|
20549
20655
|
const entry = byId.get(sessionId);
|
|
20550
20656
|
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
@@ -25222,6 +25328,43 @@ var AcpConnection = class {
|
|
|
25222
25328
|
}
|
|
25223
25329
|
return binding;
|
|
25224
25330
|
}
|
|
25331
|
+
getDiagnostic() {
|
|
25332
|
+
const liveStreams = /* @__PURE__ */ new Set();
|
|
25333
|
+
if (this.connStream && !this.connStream.isClosed) {
|
|
25334
|
+
liveStreams.add(this.connStream);
|
|
25335
|
+
}
|
|
25336
|
+
let sessionStreams = 0;
|
|
25337
|
+
let bufferedSessionFrames = 0;
|
|
25338
|
+
for (const binding of this.sessions.values()) {
|
|
25339
|
+
bufferedSessionFrames += binding.buffer.length;
|
|
25340
|
+
if (binding.stream && !binding.stream.isClosed) {
|
|
25341
|
+
sessionStreams += 1;
|
|
25342
|
+
liveStreams.add(binding.stream);
|
|
25343
|
+
}
|
|
25344
|
+
}
|
|
25345
|
+
let sseStreams = 0;
|
|
25346
|
+
let wsStreams = 0;
|
|
25347
|
+
for (const stream of liveStreams) {
|
|
25348
|
+
if (stream.kind === "sse") sseStreams += 1;
|
|
25349
|
+
if (stream.kind === "ws") wsStreams += 1;
|
|
25350
|
+
}
|
|
25351
|
+
return {
|
|
25352
|
+
connectionIdPrefix: this.connectionId.slice(0, 8),
|
|
25353
|
+
fromLoopback: this.fromLoopback,
|
|
25354
|
+
destroyed: this.destroyed,
|
|
25355
|
+
lastActiveMs: this.lastActiveMs,
|
|
25356
|
+
ownedSessionCount: this.ownedSessions.size,
|
|
25357
|
+
sessionBindingCount: this.sessions.size,
|
|
25358
|
+
closingSessionCount: this.closingSessions.size,
|
|
25359
|
+
pendingClientRequests: this.pending.size,
|
|
25360
|
+
connectionStreamOpen: this.connStream !== void 0 && !this.connStream.isClosed,
|
|
25361
|
+
sessionStreams,
|
|
25362
|
+
sseStreams,
|
|
25363
|
+
wsStreams,
|
|
25364
|
+
bufferedConnectionFrames: this.connBuffer.length,
|
|
25365
|
+
bufferedSessionFrames
|
|
25366
|
+
};
|
|
25367
|
+
}
|
|
25225
25368
|
/** Send a frame on the connection-scoped stream (buffer until it attaches). */
|
|
25226
25369
|
sendConn(frame) {
|
|
25227
25370
|
if (this.connStream && !this.connStream.isClosed) {
|
|
@@ -25403,6 +25546,24 @@ var ConnectionRegistry = class {
|
|
|
25403
25546
|
get connectionCap() {
|
|
25404
25547
|
return this.maxConnections;
|
|
25405
25548
|
}
|
|
25549
|
+
getSnapshot() {
|
|
25550
|
+
const connections = [...this.byId.values()].map(
|
|
25551
|
+
(conn) => conn.getDiagnostic()
|
|
25552
|
+
);
|
|
25553
|
+
return {
|
|
25554
|
+
connectionCount: this.byId.size,
|
|
25555
|
+
connectionCap: this.maxConnections > 0 && Number.isFinite(this.maxConnections) ? this.maxConnections : null,
|
|
25556
|
+
connectionStreams: connections.filter((conn) => conn.connectionStreamOpen).length,
|
|
25557
|
+
sessionStreams: sumBy(connections, (conn) => conn.sessionStreams),
|
|
25558
|
+
sseStreams: sumBy(connections, (conn) => conn.sseStreams),
|
|
25559
|
+
wsStreams: sumBy(connections, (conn) => conn.wsStreams),
|
|
25560
|
+
pendingClientRequests: sumBy(
|
|
25561
|
+
connections,
|
|
25562
|
+
(conn) => conn.pendingClientRequests
|
|
25563
|
+
),
|
|
25564
|
+
connections
|
|
25565
|
+
};
|
|
25566
|
+
}
|
|
25406
25567
|
dispose() {
|
|
25407
25568
|
clearInterval(this.sweepTimer);
|
|
25408
25569
|
for (const id of [...this.byId.keys()]) this.delete(id);
|
|
@@ -25418,6 +25579,12 @@ var ConnectionRegistry = class {
|
|
|
25418
25579
|
}
|
|
25419
25580
|
}
|
|
25420
25581
|
};
|
|
25582
|
+
function sumBy(values, select) {
|
|
25583
|
+
let total = 0;
|
|
25584
|
+
for (const value of values) total += select(value);
|
|
25585
|
+
return total;
|
|
25586
|
+
}
|
|
25587
|
+
__name(sumBy, "sumBy");
|
|
25421
25588
|
|
|
25422
25589
|
// packages/cli/src/serve/acpHttp/sseStream.ts
|
|
25423
25590
|
init_esbuild_shims();
|
|
@@ -25430,6 +25597,7 @@ var SseStream = class {
|
|
|
25430
25597
|
static {
|
|
25431
25598
|
__name(this, "SseStream");
|
|
25432
25599
|
}
|
|
25600
|
+
kind = "sse";
|
|
25433
25601
|
writeChain = Promise.resolve();
|
|
25434
25602
|
heartbeat;
|
|
25435
25603
|
closed = false;
|
|
@@ -25576,6 +25744,7 @@ var WsStream = class {
|
|
|
25576
25744
|
static {
|
|
25577
25745
|
__name(this, "WsStream");
|
|
25578
25746
|
}
|
|
25747
|
+
kind = "ws";
|
|
25579
25748
|
writeChain = Promise.resolve();
|
|
25580
25749
|
_closed = false;
|
|
25581
25750
|
heartbeat;
|
|
@@ -26170,6 +26339,439 @@ function isLoopbackReq(req) {
|
|
|
26170
26339
|
}
|
|
26171
26340
|
__name(isLoopbackReq, "isLoopbackReq");
|
|
26172
26341
|
|
|
26342
|
+
// packages/cli/src/serve/daemonStatus.ts
|
|
26343
|
+
init_esbuild_shims();
|
|
26344
|
+
var DEFAULT_LISTENER_MAX_CONNECTIONS = 256;
|
|
26345
|
+
var SECTION_TIMEOUT_MS = 1e3;
|
|
26346
|
+
var CAPACITY_WARNING_RATIO = 0.8;
|
|
26347
|
+
var SectionTimeoutError = class extends Error {
|
|
26348
|
+
constructor(section, timeoutMs) {
|
|
26349
|
+
super(`${section} status timed out after ${timeoutMs}ms`);
|
|
26350
|
+
this.section = section;
|
|
26351
|
+
this.timeoutMs = timeoutMs;
|
|
26352
|
+
this.name = "SectionTimeoutError";
|
|
26353
|
+
}
|
|
26354
|
+
static {
|
|
26355
|
+
__name(this, "SectionTimeoutError");
|
|
26356
|
+
}
|
|
26357
|
+
};
|
|
26358
|
+
function parseDaemonStatusDetail(raw) {
|
|
26359
|
+
if (raw === void 0) return { ok: true, detail: "summary" };
|
|
26360
|
+
if (raw === "summary" || raw === "full") {
|
|
26361
|
+
return { ok: true, detail: raw };
|
|
26362
|
+
}
|
|
26363
|
+
return { ok: false };
|
|
26364
|
+
}
|
|
26365
|
+
__name(parseDaemonStatusDetail, "parseDaemonStatusDetail");
|
|
26366
|
+
async function buildDaemonStatusResponse(detail, input) {
|
|
26367
|
+
const bridgeSnapshot = input.bridge.getDaemonStatusSnapshot();
|
|
26368
|
+
const acpSnapshot = input.acpHandle?.registry.getSnapshot();
|
|
26369
|
+
const rateLimitHits = input.rateLimiter?.getHitCounts() ?? zeroRateHits();
|
|
26370
|
+
const issues = [];
|
|
26371
|
+
let full;
|
|
26372
|
+
pushRuntimeIssues(issues, bridgeSnapshot, acpSnapshot, rateLimitHits, input);
|
|
26373
|
+
if (detail === "full") {
|
|
26374
|
+
full = await buildFullStatus(input, bridgeSnapshot, acpSnapshot);
|
|
26375
|
+
pushFullIssues(issues, full);
|
|
26376
|
+
}
|
|
26377
|
+
return {
|
|
26378
|
+
v: 1,
|
|
26379
|
+
detail,
|
|
26380
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26381
|
+
status: rollupStatus(issues),
|
|
26382
|
+
issues,
|
|
26383
|
+
daemon: {
|
|
26384
|
+
pid: process.pid,
|
|
26385
|
+
uptimeMs: Math.round(process.uptime() * 1e3),
|
|
26386
|
+
mode: input.opts.mode,
|
|
26387
|
+
workspaceCwd: input.boundWorkspace,
|
|
26388
|
+
...input.qwenCodeVersion ? { qwenCodeVersion: input.qwenCodeVersion } : {},
|
|
26389
|
+
...input.daemonLog?.getDaemonId() ? { daemonId: input.daemonLog.getDaemonId() } : {},
|
|
26390
|
+
...detail === "full" && input.daemonLog?.getLogPath() ? { logPath: input.daemonLog.getLogPath() } : {}
|
|
26391
|
+
},
|
|
26392
|
+
security: {
|
|
26393
|
+
tokenConfigured: Boolean(input.opts.token),
|
|
26394
|
+
requireAuth: input.opts.requireAuth === true,
|
|
26395
|
+
loopbackBind: isLoopbackBind(input.opts.hostname),
|
|
26396
|
+
allowOriginConfigured: input.opts.allowOrigins !== void 0 && input.opts.allowOrigins.length > 0,
|
|
26397
|
+
allowOriginMode: allowOriginMode(input.opts.allowOrigins),
|
|
26398
|
+
sessionShellCommandEnabled: input.sessionShellCommandEnabled
|
|
26399
|
+
},
|
|
26400
|
+
limits: {
|
|
26401
|
+
maxSessions: bridgeSnapshot.limits.maxSessions,
|
|
26402
|
+
maxPendingPromptsPerSession: bridgeSnapshot.limits.maxPendingPromptsPerSession,
|
|
26403
|
+
listenerMaxConnections: listenerMaxConnections(input.opts.maxConnections),
|
|
26404
|
+
eventRingSize: bridgeSnapshot.limits.eventRingSize,
|
|
26405
|
+
promptDeadlineMs: positiveFiniteOrNull(input.opts.promptDeadlineMs),
|
|
26406
|
+
writerIdleTimeoutMs: positiveFiniteOrNull(input.opts.writerIdleTimeoutMs),
|
|
26407
|
+
channelIdleTimeoutMs: bridgeSnapshot.limits.channelIdleTimeoutMs,
|
|
26408
|
+
sessionIdleTimeoutMs: bridgeSnapshot.limits.sessionIdleTimeoutMs,
|
|
26409
|
+
acpConnectionCap: acpSnapshot?.connectionCap ?? null
|
|
26410
|
+
},
|
|
26411
|
+
capabilities: {
|
|
26412
|
+
protocolVersions: input.protocolVersions,
|
|
26413
|
+
features: [...input.features]
|
|
26414
|
+
},
|
|
26415
|
+
runtime: {
|
|
26416
|
+
sessions: { active: bridgeSnapshot.sessionCount },
|
|
26417
|
+
permissions: {
|
|
26418
|
+
pending: bridgeSnapshot.pendingPermissionCount,
|
|
26419
|
+
policy: bridgeSnapshot.permissionPolicy
|
|
26420
|
+
},
|
|
26421
|
+
channel: { live: bridgeSnapshot.channelLive },
|
|
26422
|
+
transport: {
|
|
26423
|
+
restSseActive: input.getRestSseActive(),
|
|
26424
|
+
acp: {
|
|
26425
|
+
enabled: acpSnapshot !== void 0,
|
|
26426
|
+
connections: acpSnapshot?.connectionCount ?? 0,
|
|
26427
|
+
connectionStreams: acpSnapshot?.connectionStreams ?? 0,
|
|
26428
|
+
sessionStreams: acpSnapshot?.sessionStreams ?? 0,
|
|
26429
|
+
sseStreams: acpSnapshot?.sseStreams ?? 0,
|
|
26430
|
+
wsStreams: acpSnapshot?.wsStreams ?? 0,
|
|
26431
|
+
pendingClientRequests: acpSnapshot?.pendingClientRequests ?? 0
|
|
26432
|
+
}
|
|
26433
|
+
},
|
|
26434
|
+
rateLimit: {
|
|
26435
|
+
enabled: input.opts.rateLimit === true,
|
|
26436
|
+
rejectedSinceStart: rateLimitHits
|
|
26437
|
+
},
|
|
26438
|
+
process: process.memoryUsage()
|
|
26439
|
+
},
|
|
26440
|
+
...full ? { full } : {}
|
|
26441
|
+
};
|
|
26442
|
+
}
|
|
26443
|
+
__name(buildDaemonStatusResponse, "buildDaemonStatusResponse");
|
|
26444
|
+
async function buildFullStatus(input, bridgeSnapshot, acpSnapshot) {
|
|
26445
|
+
const ctx = {
|
|
26446
|
+
route: "GET /daemon/status",
|
|
26447
|
+
workspaceCwd: input.boundWorkspace
|
|
26448
|
+
};
|
|
26449
|
+
const [mcp, skills, tools, providers, env, preflight, hooks, extensions] = await Promise.all([
|
|
26450
|
+
collectSection(
|
|
26451
|
+
"workspace.mcp",
|
|
26452
|
+
() => input.workspace.getWorkspaceMcpStatus(ctx)
|
|
26453
|
+
),
|
|
26454
|
+
collectSection(
|
|
26455
|
+
"workspace.skills",
|
|
26456
|
+
() => input.workspace.getWorkspaceSkillsStatus(ctx)
|
|
26457
|
+
),
|
|
26458
|
+
collectSection(
|
|
26459
|
+
"workspace.tools",
|
|
26460
|
+
() => input.bridge.getWorkspaceToolsStatus()
|
|
26461
|
+
),
|
|
26462
|
+
collectSection(
|
|
26463
|
+
"workspace.providers",
|
|
26464
|
+
() => input.workspace.getWorkspaceProvidersStatus(ctx)
|
|
26465
|
+
),
|
|
26466
|
+
collectSection(
|
|
26467
|
+
"workspace.env",
|
|
26468
|
+
() => input.workspace.getWorkspaceEnvStatus(ctx)
|
|
26469
|
+
),
|
|
26470
|
+
collectSection(
|
|
26471
|
+
"workspace.preflight",
|
|
26472
|
+
() => input.workspace.getWorkspacePreflightStatus(ctx)
|
|
26473
|
+
),
|
|
26474
|
+
collectSection(
|
|
26475
|
+
"workspace.hooks",
|
|
26476
|
+
() => input.workspace.getWorkspaceHooksStatus(ctx)
|
|
26477
|
+
),
|
|
26478
|
+
collectSection(
|
|
26479
|
+
"workspace.extensions",
|
|
26480
|
+
() => input.workspace.getWorkspaceExtensionsStatus(ctx)
|
|
26481
|
+
)
|
|
26482
|
+
]);
|
|
26483
|
+
return {
|
|
26484
|
+
sessions: bridgeSnapshot.sessions,
|
|
26485
|
+
acpConnections: acpSnapshot?.connections ?? [],
|
|
26486
|
+
workspace: {
|
|
26487
|
+
mcp,
|
|
26488
|
+
skills,
|
|
26489
|
+
tools,
|
|
26490
|
+
providers,
|
|
26491
|
+
env,
|
|
26492
|
+
preflight,
|
|
26493
|
+
hooks,
|
|
26494
|
+
extensions
|
|
26495
|
+
},
|
|
26496
|
+
auth: {
|
|
26497
|
+
supportedDeviceFlowProviders: [...input.supportedDeviceFlowProviders],
|
|
26498
|
+
pendingDeviceFlowCount: input.deviceFlowRegistry.listPending().length
|
|
26499
|
+
}
|
|
26500
|
+
};
|
|
26501
|
+
}
|
|
26502
|
+
__name(buildFullStatus, "buildFullStatus");
|
|
26503
|
+
async function collectSection(name, read) {
|
|
26504
|
+
const startMs = Date.now();
|
|
26505
|
+
try {
|
|
26506
|
+
const data = await withTimeout2(read(), name, SECTION_TIMEOUT_MS);
|
|
26507
|
+
return {
|
|
26508
|
+
status: inferSectionStatus(data),
|
|
26509
|
+
durationMs: Date.now() - startMs,
|
|
26510
|
+
summary: summarizeStatusData(data),
|
|
26511
|
+
data
|
|
26512
|
+
};
|
|
26513
|
+
} catch (err) {
|
|
26514
|
+
return {
|
|
26515
|
+
status: "unavailable",
|
|
26516
|
+
durationMs: Date.now() - startMs,
|
|
26517
|
+
error: {
|
|
26518
|
+
kind: err instanceof SectionTimeoutError ? "timeout" : "error",
|
|
26519
|
+
message: err instanceof Error ? err.message : String(err)
|
|
26520
|
+
}
|
|
26521
|
+
};
|
|
26522
|
+
}
|
|
26523
|
+
}
|
|
26524
|
+
__name(collectSection, "collectSection");
|
|
26525
|
+
async function withTimeout2(promise, section, timeoutMs) {
|
|
26526
|
+
let timer;
|
|
26527
|
+
try {
|
|
26528
|
+
return await Promise.race([
|
|
26529
|
+
promise,
|
|
26530
|
+
new Promise((_resolve, reject) => {
|
|
26531
|
+
timer = setTimeout(
|
|
26532
|
+
() => reject(new SectionTimeoutError(section, timeoutMs)),
|
|
26533
|
+
timeoutMs
|
|
26534
|
+
);
|
|
26535
|
+
})
|
|
26536
|
+
]);
|
|
26537
|
+
} finally {
|
|
26538
|
+
if (timer) clearTimeout(timer);
|
|
26539
|
+
}
|
|
26540
|
+
}
|
|
26541
|
+
__name(withTimeout2, "withTimeout");
|
|
26542
|
+
function pushRuntimeIssues(issues, bridgeSnapshot, acpSnapshot, rateLimitHits, input) {
|
|
26543
|
+
if (bridgeSnapshot.limits.maxSessions !== null && bridgeSnapshot.limits.maxSessions > 0 && bridgeSnapshot.sessionCount / bridgeSnapshot.limits.maxSessions >= CAPACITY_WARNING_RATIO) {
|
|
26544
|
+
issues.push({
|
|
26545
|
+
code: "session_capacity_high",
|
|
26546
|
+
severity: "warning",
|
|
26547
|
+
message: `Active sessions are at ${bridgeSnapshot.sessionCount}/${bridgeSnapshot.limits.maxSessions}.`
|
|
26548
|
+
});
|
|
26549
|
+
}
|
|
26550
|
+
if (acpSnapshot !== void 0 && acpSnapshot.connectionCap !== null && acpSnapshot.connectionCap > 0 && acpSnapshot.connectionCount / acpSnapshot.connectionCap >= CAPACITY_WARNING_RATIO) {
|
|
26551
|
+
issues.push({
|
|
26552
|
+
code: "connection_capacity_high",
|
|
26553
|
+
severity: "warning",
|
|
26554
|
+
message: `ACP connections are at ${acpSnapshot.connectionCount}/${acpSnapshot.connectionCap}.`
|
|
26555
|
+
});
|
|
26556
|
+
}
|
|
26557
|
+
if (bridgeSnapshot.pendingPermissionCount > 0) {
|
|
26558
|
+
issues.push({
|
|
26559
|
+
code: "pending_permissions",
|
|
26560
|
+
severity: "warning",
|
|
26561
|
+
message: `${bridgeSnapshot.pendingPermissionCount} permission request(s) are pending.`
|
|
26562
|
+
});
|
|
26563
|
+
}
|
|
26564
|
+
if (bridgeSnapshot.sessionCount > 0 && !bridgeSnapshot.channelLive) {
|
|
26565
|
+
issues.push({
|
|
26566
|
+
code: "acp_channel_down",
|
|
26567
|
+
severity: "error",
|
|
26568
|
+
message: "Active sessions exist but the ACP channel is not live."
|
|
26569
|
+
});
|
|
26570
|
+
}
|
|
26571
|
+
if (input.opts.rateLimit === true && sumRateHits(rateLimitHits) > 0) {
|
|
26572
|
+
issues.push({
|
|
26573
|
+
code: "rate_limit_hits",
|
|
26574
|
+
severity: "warning",
|
|
26575
|
+
message: `${sumRateHits(rateLimitHits)} request(s) have been rejected by rate limiting since start.`
|
|
26576
|
+
});
|
|
26577
|
+
}
|
|
26578
|
+
}
|
|
26579
|
+
__name(pushRuntimeIssues, "pushRuntimeIssues");
|
|
26580
|
+
function pushFullIssues(issues, full) {
|
|
26581
|
+
for (const [name, section] of Object.entries(full.workspace)) {
|
|
26582
|
+
if (section.status === "unavailable") {
|
|
26583
|
+
issues.push({
|
|
26584
|
+
code: "workspace_status_unavailable",
|
|
26585
|
+
severity: "warning",
|
|
26586
|
+
section: name,
|
|
26587
|
+
message: `${name} status is unavailable.`
|
|
26588
|
+
});
|
|
26589
|
+
}
|
|
26590
|
+
}
|
|
26591
|
+
const preflight = full.workspace["preflight"];
|
|
26592
|
+
if (preflight && sectionHasStatus(preflight, "error")) {
|
|
26593
|
+
issues.push({
|
|
26594
|
+
code: "preflight_error",
|
|
26595
|
+
severity: "error",
|
|
26596
|
+
section: "preflight",
|
|
26597
|
+
message: "Workspace preflight reports an error."
|
|
26598
|
+
});
|
|
26599
|
+
}
|
|
26600
|
+
const mcp = full.workspace["mcp"];
|
|
26601
|
+
const mcpBudget = mcp ? inspectMcpBudget(mcp) : void 0;
|
|
26602
|
+
if (mcpBudget === "exhausted") {
|
|
26603
|
+
issues.push({
|
|
26604
|
+
code: "mcp_budget_exhausted",
|
|
26605
|
+
severity: "error",
|
|
26606
|
+
section: "mcp",
|
|
26607
|
+
message: "MCP client budget is exhausted."
|
|
26608
|
+
});
|
|
26609
|
+
} else if (mcpBudget === "warning") {
|
|
26610
|
+
issues.push({
|
|
26611
|
+
code: "mcp_budget_warning",
|
|
26612
|
+
severity: "warning",
|
|
26613
|
+
section: "mcp",
|
|
26614
|
+
message: "MCP client budget is near capacity."
|
|
26615
|
+
});
|
|
26616
|
+
}
|
|
26617
|
+
}
|
|
26618
|
+
__name(pushFullIssues, "pushFullIssues");
|
|
26619
|
+
function inferSectionStatus(data) {
|
|
26620
|
+
const statuses = collectStatuses(data);
|
|
26621
|
+
if (statuses.includes("error")) return "error";
|
|
26622
|
+
if (statuses.includes("warning")) return "warning";
|
|
26623
|
+
return "ok";
|
|
26624
|
+
}
|
|
26625
|
+
__name(inferSectionStatus, "inferSectionStatus");
|
|
26626
|
+
function summarizeStatusData(data) {
|
|
26627
|
+
const summary = {};
|
|
26628
|
+
if (!isRecord(data)) return summary;
|
|
26629
|
+
copyBoolean(data, summary, "initialized");
|
|
26630
|
+
copyBoolean(data, summary, "acpChannelLive");
|
|
26631
|
+
copyString(data, summary, "discoveryState");
|
|
26632
|
+
copyString(data, summary, "budgetMode");
|
|
26633
|
+
copyNumber(data, summary, "clientCount");
|
|
26634
|
+
copyNumber(data, summary, "clientBudget");
|
|
26635
|
+
for (const key of [
|
|
26636
|
+
"cells",
|
|
26637
|
+
"errors",
|
|
26638
|
+
"servers",
|
|
26639
|
+
"budgets",
|
|
26640
|
+
"skills",
|
|
26641
|
+
"tools",
|
|
26642
|
+
"providers",
|
|
26643
|
+
"hooks",
|
|
26644
|
+
"extensions"
|
|
26645
|
+
]) {
|
|
26646
|
+
const value = data[key];
|
|
26647
|
+
if (Array.isArray(value)) {
|
|
26648
|
+
summary[`${key}Count`] = value.length;
|
|
26649
|
+
}
|
|
26650
|
+
}
|
|
26651
|
+
return summary;
|
|
26652
|
+
}
|
|
26653
|
+
__name(summarizeStatusData, "summarizeStatusData");
|
|
26654
|
+
function collectStatuses(data) {
|
|
26655
|
+
const statuses = [];
|
|
26656
|
+
visitStatusContainers(data, (record) => {
|
|
26657
|
+
const status = record["status"];
|
|
26658
|
+
if (typeof status === "string") statuses.push(status);
|
|
26659
|
+
});
|
|
26660
|
+
return statuses;
|
|
26661
|
+
}
|
|
26662
|
+
__name(collectStatuses, "collectStatuses");
|
|
26663
|
+
function sectionHasStatus(section, status) {
|
|
26664
|
+
return collectStatuses(section.data).includes(status);
|
|
26665
|
+
}
|
|
26666
|
+
__name(sectionHasStatus, "sectionHasStatus");
|
|
26667
|
+
function inspectMcpBudget(section) {
|
|
26668
|
+
const data = section.data;
|
|
26669
|
+
if (!isRecord(data)) return void 0;
|
|
26670
|
+
const budgetIssue = inspectBudgetContainers(data);
|
|
26671
|
+
if (budgetIssue) return budgetIssue;
|
|
26672
|
+
const clientCount = numberValue(data["clientCount"]);
|
|
26673
|
+
const clientBudget = numberValue(data["clientBudget"]);
|
|
26674
|
+
if (clientCount !== void 0 && clientBudget !== void 0 && clientBudget > 0) {
|
|
26675
|
+
const ratio = clientCount / clientBudget;
|
|
26676
|
+
if (ratio >= 1) return "exhausted";
|
|
26677
|
+
if (ratio >= 0.75) return "warning";
|
|
26678
|
+
}
|
|
26679
|
+
return void 0;
|
|
26680
|
+
}
|
|
26681
|
+
__name(inspectMcpBudget, "inspectMcpBudget");
|
|
26682
|
+
function inspectBudgetContainers(data) {
|
|
26683
|
+
let result;
|
|
26684
|
+
visitStatusContainers(data, (record) => {
|
|
26685
|
+
if (result === "exhausted") return;
|
|
26686
|
+
const errorKind = record["errorKind"];
|
|
26687
|
+
const disabledReason = record["disabledReason"];
|
|
26688
|
+
const status = record["status"];
|
|
26689
|
+
const kind = record["kind"];
|
|
26690
|
+
const refusedCount = numberValue(record["refusedCount"]);
|
|
26691
|
+
if (errorKind === "budget_exhausted" || disabledReason === "budget" || kind === "mcp_budget" && status === "error" || refusedCount !== void 0 && refusedCount > 0) {
|
|
26692
|
+
result = "exhausted";
|
|
26693
|
+
return;
|
|
26694
|
+
}
|
|
26695
|
+
if (kind === "mcp_budget" && status === "warning") {
|
|
26696
|
+
result = "warning";
|
|
26697
|
+
}
|
|
26698
|
+
});
|
|
26699
|
+
return result;
|
|
26700
|
+
}
|
|
26701
|
+
__name(inspectBudgetContainers, "inspectBudgetContainers");
|
|
26702
|
+
function visitStatusContainers(data, visit) {
|
|
26703
|
+
if (!isRecord(data)) return;
|
|
26704
|
+
visit(data);
|
|
26705
|
+
for (const key of [
|
|
26706
|
+
"cells",
|
|
26707
|
+
"errors",
|
|
26708
|
+
"servers",
|
|
26709
|
+
"budgets",
|
|
26710
|
+
"skills",
|
|
26711
|
+
"tools",
|
|
26712
|
+
"providers",
|
|
26713
|
+
"hooks",
|
|
26714
|
+
"extensions"
|
|
26715
|
+
]) {
|
|
26716
|
+
const value = data[key];
|
|
26717
|
+
if (!Array.isArray(value)) continue;
|
|
26718
|
+
for (const item of value) visitStatusContainers(item, visit);
|
|
26719
|
+
}
|
|
26720
|
+
}
|
|
26721
|
+
__name(visitStatusContainers, "visitStatusContainers");
|
|
26722
|
+
function rollupStatus(issues) {
|
|
26723
|
+
if (issues.some((issue) => issue.severity === "error")) return "error";
|
|
26724
|
+
if (issues.length > 0) return "warning";
|
|
26725
|
+
return "ok";
|
|
26726
|
+
}
|
|
26727
|
+
__name(rollupStatus, "rollupStatus");
|
|
26728
|
+
function allowOriginMode(allowOrigins) {
|
|
26729
|
+
if (!allowOrigins || allowOrigins.length === 0) return "none";
|
|
26730
|
+
return allowOrigins.includes("*") ? "any" : "specific";
|
|
26731
|
+
}
|
|
26732
|
+
__name(allowOriginMode, "allowOriginMode");
|
|
26733
|
+
function listenerMaxConnections(value) {
|
|
26734
|
+
if (value === void 0) return DEFAULT_LISTENER_MAX_CONNECTIONS;
|
|
26735
|
+
if (value === 0 || value === Infinity) return null;
|
|
26736
|
+
return Number.isFinite(value) && value > 0 ? value : null;
|
|
26737
|
+
}
|
|
26738
|
+
__name(listenerMaxConnections, "listenerMaxConnections");
|
|
26739
|
+
function positiveFiniteOrNull(value) {
|
|
26740
|
+
return value !== void 0 && Number.isFinite(value) && value > 0 ? value : null;
|
|
26741
|
+
}
|
|
26742
|
+
__name(positiveFiniteOrNull, "positiveFiniteOrNull");
|
|
26743
|
+
function zeroRateHits() {
|
|
26744
|
+
return { prompt: 0, mutation: 0, read: 0 };
|
|
26745
|
+
}
|
|
26746
|
+
__name(zeroRateHits, "zeroRateHits");
|
|
26747
|
+
function sumRateHits(hits) {
|
|
26748
|
+
return hits.prompt + hits.mutation + hits.read;
|
|
26749
|
+
}
|
|
26750
|
+
__name(sumRateHits, "sumRateHits");
|
|
26751
|
+
function isRecord(value) {
|
|
26752
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26753
|
+
}
|
|
26754
|
+
__name(isRecord, "isRecord");
|
|
26755
|
+
function numberValue(value) {
|
|
26756
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
26757
|
+
}
|
|
26758
|
+
__name(numberValue, "numberValue");
|
|
26759
|
+
function copyBoolean(from, to, key) {
|
|
26760
|
+
const value = from[key];
|
|
26761
|
+
if (typeof value === "boolean") to[key] = value;
|
|
26762
|
+
}
|
|
26763
|
+
__name(copyBoolean, "copyBoolean");
|
|
26764
|
+
function copyString(from, to, key) {
|
|
26765
|
+
const value = from[key];
|
|
26766
|
+
if (typeof value === "string") to[key] = value;
|
|
26767
|
+
}
|
|
26768
|
+
__name(copyString, "copyString");
|
|
26769
|
+
function copyNumber(from, to, key) {
|
|
26770
|
+
const value = numberValue(from[key]);
|
|
26771
|
+
if (value !== void 0) to[key] = value;
|
|
26772
|
+
}
|
|
26773
|
+
__name(copyNumber, "copyNumber");
|
|
26774
|
+
|
|
26173
26775
|
// packages/cli/src/serve/capabilities.ts
|
|
26174
26776
|
init_esbuild_shims();
|
|
26175
26777
|
var SERVE_PROTOCOL_VERSION = "v1";
|
|
@@ -26178,6 +26780,7 @@ var SUPPORTED_SERVE_PROTOCOL_VERSIONS = [
|
|
|
26178
26780
|
];
|
|
26179
26781
|
var SERVE_CAPABILITY_REGISTRY = {
|
|
26180
26782
|
health: { since: "v1" },
|
|
26783
|
+
daemon_status: { since: "v1" },
|
|
26181
26784
|
capabilities: { since: "v1" },
|
|
26182
26785
|
session_create: { since: "v1" },
|
|
26183
26786
|
session_scope_override: { since: "v1" },
|
|
@@ -30408,8 +31011,11 @@ function resolveDaemonTelemetryRoute(req) {
|
|
|
30408
31011
|
if (req.method === "POST" && path14 === "/sessions/delete") {
|
|
30409
31012
|
return { route: "POST /sessions/delete" };
|
|
30410
31013
|
}
|
|
31014
|
+
if (req.method === "GET" && path14 === "/daemon/status") {
|
|
31015
|
+
return { route: "GET /daemon/status" };
|
|
31016
|
+
}
|
|
30411
31017
|
const sessionAction = path14.match(
|
|
30412
|
-
/^\/session\/([^/]+)\/(load|resume|prompt|cancel|recap|btw|model|shell|detach|rewind|approval-mode|language|a2ui-action)$/
|
|
31018
|
+
/^\/session\/([^/]+)\/(load|resume|prompt|cancel|recap|btw|mid-turn-message|model|shell|detach|rewind|approval-mode|language|a2ui-action)$/
|
|
30413
31019
|
);
|
|
30414
31020
|
const sessionActionId = sessionAction?.[1];
|
|
30415
31021
|
const sessionActionName = sessionAction?.[2];
|
|
@@ -30815,23 +31421,65 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
30815
31421
|
}
|
|
30816
31422
|
__name(buildWorkspaceCtx, "buildWorkspaceCtx");
|
|
30817
31423
|
const LANGUAGE_CODES = [...SUPPORTED_LANGUAGES.map((l) => l.code), "auto"];
|
|
31424
|
+
const currentServeFeatures = /* @__PURE__ */ __name(() => getAdvertisedServeFeatures(void 0, {
|
|
31425
|
+
requireAuth: opts.requireAuth === true,
|
|
31426
|
+
mcpPoolActive: opts.mcpPoolActive !== false,
|
|
31427
|
+
allowOriginActive: opts.allowOrigins !== void 0 && opts.allowOrigins.length > 0,
|
|
31428
|
+
...opts.promptDeadlineMs !== void 0 ? { promptDeadlineMs: opts.promptDeadlineMs } : {},
|
|
31429
|
+
...opts.writerIdleTimeoutMs !== void 0 ? { writerIdleTimeoutMs: opts.writerIdleTimeoutMs } : {},
|
|
31430
|
+
persistSettingAvailable: deps.persistSetting !== void 0,
|
|
31431
|
+
sessionShellCommandEnabled,
|
|
31432
|
+
rateLimit: opts.rateLimit === true,
|
|
31433
|
+
reloadAvailable: deps.workspace !== void 0
|
|
31434
|
+
}), "currentServeFeatures");
|
|
31435
|
+
const acpHandleRef = {};
|
|
31436
|
+
app.get("/daemon/status", async (req, res) => {
|
|
31437
|
+
const detail = parseDaemonStatusDetail(req.query["detail"]);
|
|
31438
|
+
if (!detail.ok || !detail.detail) {
|
|
31439
|
+
res.status(400).json({
|
|
31440
|
+
error: "detail must be one of: summary, full",
|
|
31441
|
+
code: "invalid_detail"
|
|
31442
|
+
});
|
|
31443
|
+
return;
|
|
31444
|
+
}
|
|
31445
|
+
try {
|
|
31446
|
+
res.status(200).json(
|
|
31447
|
+
await buildDaemonStatusResponse(detail.detail, {
|
|
31448
|
+
opts,
|
|
31449
|
+
boundWorkspace,
|
|
31450
|
+
bridge,
|
|
31451
|
+
workspace,
|
|
31452
|
+
daemonLog,
|
|
31453
|
+
qwenCodeVersion: deps.qwenCodeVersion,
|
|
31454
|
+
acpHandle: acpHandleRef.current,
|
|
31455
|
+
rateLimiter,
|
|
31456
|
+
getRestSseActive: getActiveSseCount,
|
|
31457
|
+
features: currentServeFeatures(),
|
|
31458
|
+
protocolVersions: getServeProtocolVersions(),
|
|
31459
|
+
supportedDeviceFlowProviders: Array.from(
|
|
31460
|
+
deviceFlowProviderMap.keys()
|
|
31461
|
+
),
|
|
31462
|
+
deviceFlowRegistry,
|
|
31463
|
+
sessionShellCommandEnabled
|
|
31464
|
+
})
|
|
31465
|
+
);
|
|
31466
|
+
} catch (err) {
|
|
31467
|
+
writeStderrLine(
|
|
31468
|
+
`qwen serve: /daemon/status failed: ${err instanceof Error ? err.message : String(err)}`
|
|
31469
|
+
);
|
|
31470
|
+
res.status(500).json({
|
|
31471
|
+
error: "Failed to build daemon status",
|
|
31472
|
+
code: "daemon_status_failed"
|
|
31473
|
+
});
|
|
31474
|
+
}
|
|
31475
|
+
});
|
|
30818
31476
|
app.get("/capabilities", (_req, res) => {
|
|
30819
31477
|
const envelope = {
|
|
30820
31478
|
v: CAPABILITIES_SCHEMA_VERSION,
|
|
30821
31479
|
protocolVersions: getServeProtocolVersions(),
|
|
30822
31480
|
...deps.qwenCodeVersion ? { qwenCodeVersion: deps.qwenCodeVersion } : {},
|
|
30823
31481
|
mode: opts.mode,
|
|
30824
|
-
features:
|
|
30825
|
-
requireAuth: opts.requireAuth === true,
|
|
30826
|
-
mcpPoolActive: opts.mcpPoolActive !== false,
|
|
30827
|
-
allowOriginActive: opts.allowOrigins !== void 0 && opts.allowOrigins.length > 0,
|
|
30828
|
-
...opts.promptDeadlineMs !== void 0 ? { promptDeadlineMs: opts.promptDeadlineMs } : {},
|
|
30829
|
-
...opts.writerIdleTimeoutMs !== void 0 ? { writerIdleTimeoutMs: opts.writerIdleTimeoutMs } : {},
|
|
30830
|
-
persistSettingAvailable: deps.persistSetting !== void 0,
|
|
30831
|
-
sessionShellCommandEnabled,
|
|
30832
|
-
rateLimit: opts.rateLimit === true,
|
|
30833
|
-
reloadAvailable: deps.workspace !== void 0
|
|
30834
|
-
}),
|
|
31482
|
+
features: currentServeFeatures(),
|
|
30835
31483
|
modelServices: [],
|
|
30836
31484
|
// Surface the bound workspace so clients can detect mismatch
|
|
30837
31485
|
// pre-flight and omit `cwd` on `POST /session`.
|
|
@@ -31882,6 +32530,41 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
31882
32530
|
res.off("close", onResClose);
|
|
31883
32531
|
}
|
|
31884
32532
|
});
|
|
32533
|
+
const MID_TURN_MESSAGE_MAX_LENGTH = 16 * 1024;
|
|
32534
|
+
app.post("/session/:id/mid-turn-message", mutate(), (req, res) => {
|
|
32535
|
+
const sessionId = requireSessionId(req, res);
|
|
32536
|
+
if (sessionId === null) return;
|
|
32537
|
+
const body = safeBody(req);
|
|
32538
|
+
const message = body["message"];
|
|
32539
|
+
const trimmed = typeof message === "string" ? message.trim() : "";
|
|
32540
|
+
if (trimmed.length === 0) {
|
|
32541
|
+
res.status(400).json({
|
|
32542
|
+
error: "`message` is required and must be a non-empty string"
|
|
32543
|
+
});
|
|
32544
|
+
return;
|
|
32545
|
+
}
|
|
32546
|
+
if (trimmed.length > MID_TURN_MESSAGE_MAX_LENGTH) {
|
|
32547
|
+
res.status(400).json({
|
|
32548
|
+
error: `\`message\` must be at most ${MID_TURN_MESSAGE_MAX_LENGTH} characters`
|
|
32549
|
+
});
|
|
32550
|
+
return;
|
|
32551
|
+
}
|
|
32552
|
+
const clientId = parseClientIdHeader(req, res);
|
|
32553
|
+
if (clientId === null) return;
|
|
32554
|
+
try {
|
|
32555
|
+
const result = bridge.enqueueMidTurnMessage(
|
|
32556
|
+
sessionId,
|
|
32557
|
+
trimmed,
|
|
32558
|
+
clientId !== void 0 ? { clientId } : void 0
|
|
32559
|
+
);
|
|
32560
|
+
res.status(200).json(result);
|
|
32561
|
+
} catch (err) {
|
|
32562
|
+
sendBridgeError(res, err, {
|
|
32563
|
+
route: "POST /session/:id/mid-turn-message",
|
|
32564
|
+
sessionId
|
|
32565
|
+
});
|
|
32566
|
+
}
|
|
32567
|
+
});
|
|
31885
32568
|
app.post("/session/:id/shell", mutate({ strict: true }), async (req, res) => {
|
|
31886
32569
|
const sessionId = req.params["id"];
|
|
31887
32570
|
if (!sessionShellCommandEnabled) {
|
|
@@ -32594,7 +33277,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
32594
33277
|
}
|
|
32595
33278
|
})();
|
|
32596
33279
|
});
|
|
32597
|
-
|
|
33280
|
+
acpHandleRef.current = mountAcpHttp(app, bridge, {
|
|
32598
33281
|
boundWorkspace,
|
|
32599
33282
|
workspace,
|
|
32600
33283
|
fsFactory,
|
|
@@ -32603,8 +33286,8 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
32603
33286
|
sessionShellCommandEnabled,
|
|
32604
33287
|
checkRate: rateLimiter?.checkRate
|
|
32605
33288
|
});
|
|
32606
|
-
if (
|
|
32607
|
-
app.locals["acpHandle"] =
|
|
33289
|
+
if (acpHandleRef.current) {
|
|
33290
|
+
app.locals["acpHandle"] = acpHandleRef.current;
|
|
32608
33291
|
}
|
|
32609
33292
|
app.use(
|
|
32610
33293
|
(err, _req, res, _next) => {
|