@tea-agent/loop-agent 0.44.0-next.3 → 0.44.0-next.5
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/CHANGELOG.md +8 -2
- package/dist/build-stamp.json +3 -3
- package/dist/executors/dag-pi-executor.js +2 -2
- package/dist/executors/shell-write-guard.js +26 -3
- package/dist/shared/file-identity.js +23 -0
- package/dist/shared/git-workspace-status.js +480 -0
- package/dist/shared/path-safety.js +2 -2
- package/dist/task/config-types.js +2 -1
- package/dist/task/contract/schema.js +1 -0
- package/dist/worker/console/chat/chat-event-store.js +32 -0
- package/dist/worker/console/chat/context-insights.js +723 -0
- package/dist/worker/console/chat/conversation-nodes.js +383 -0
- package/dist/worker/console/chat/pi-runtime.js +128 -12
- package/dist/worker/console/chat/provider-error.js +0 -12
- package/dist/worker/console/chat/repo-browser.js +3 -4
- package/dist/worker/console/chat/routes.js +209 -4
- package/dist/worker/console/chat/shortcuts.js +7 -0
- package/dist/worker/console/chat/turn-process.js +128 -7
- package/dist/worker/console/prd-intake-bridge.js +3 -0
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-COQlLTI7.js → abnfDiagram-N423BO3Z-BHuhGM1e.js} +1 -1
- package/dist/worker/console/static/assets/{arc-zN3QkNaV.js → arc-CKh5E_sr.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-Pyoyj5f2.js → architectureDiagram-T3A2C74G-DizhiBEv.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-BNppA5WW.js → blockDiagram-VBNYF7ZC-3Neea-Z-.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-lyxL8nTx.js → c4Diagram-5PPSVZJV-BCP_Qrgi.js} +1 -1
- package/dist/worker/console/static/assets/channel-DxgzA1GF.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-0hgjcdK4.js → chunk-2GRJ4B5K-C_wydftK.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-D63N9d4i.js → chunk-2Q5K7J3B-jRPXZbzx.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-CUw2AyB5.js → chunk-5RXB4S5H-BLQf2OYO.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-Q_kwZT30.js → chunk-5VM5RSS4-0qRq64rI.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-C7vMiKcw.js → chunk-6Q2QTUOP-ClMg8xmV.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-T9GbV5Hz.js → chunk-GF5L2VYU-Coop2FlL.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-D8nUSUJI.js → chunk-JWPE2WC7-CDdO-jPJ.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BCH2ewdp.js → chunk-KBJHAD2P-D8Gkppjl.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-BTdDuDBN.js → chunk-RYQCIY6F-DA9HIySf.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-Cqm2RcKF.js → chunk-XXDRQBXY-DZNDRX1k.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BZcm7fs6.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BZcm7fs6.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-pjwfpVu4.js → cose-bilkent-JH36ORCC-CZ1zGyjq.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BvalptKA.js → cynefin-VYW2F7L2-B8u1_FtM.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-BU4qJ6d7.js → cynefinDiagram-MW4NZA55-CPBB6lfo.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-DVTpq8J9.js → dagre-VZM6K2ZE-CG3Eov3E.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-B8s1W6Fc.js → diagram-7IWD3JNH-ycI-dOjh.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-DPrFk9yH.js → diagram-B4RE2ZJO-Bx_GyQ7Y.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-CnQIQsHC.js → diagram-LBJQPF4R-m0G6mP4d.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-op0DEpCv.js → diagram-Q27KOJAE-DTDJkqcJ.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-DXQamm4T.js → diagram-UB23O5K3-BCfFrG-p.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-b1ad2C0r.js → ebnfDiagram-BXEA7PRR-BIkTNPpp.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-B4cD-ZFJ.js → erDiagram-JOGREHBK-DTcMWrd2.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CrgGjlQ1.js → flowDiagram-UKHOOZJN-BqzDaNQ7.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DovmXQNV.js → ganttDiagram-PKOTCBZU-BSl_vGFe.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-DpFyu2Jn.js → gitGraphDiagram-DS77QQ5N-DCA5HXM6.js} +1 -1
- package/dist/worker/console/static/assets/index-BAEDjTbD.css +1 -0
- package/dist/worker/console/static/assets/index-wKEJUaP5.js +482 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-D3MoQZIl.js → infoDiagram-6WML65LV-DvqT18ge.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-Ci6C1yjS.js → ishikawaDiagram-WSZJBQD7-B6zGKrQ3.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-BWMo2lIP.js → journeyDiagram-NVQOT4AX-BpLQPI9C.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BdthIAg3.js → kanban-definition-27J2QSJJ-CzIz_-Lt.js} +1 -1
- package/dist/worker/console/static/assets/{linear-DuFAlSOj.js → linear-CMQ8Jpp-.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-Dqz3Slj9.js → mermaid.core-BdAMrTf7.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DNVTrD09.js → mindmap-definition-FAOFIHXS-hSwF6sOq.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-CgfZPfBh.js → pegDiagram-VL7TDLO6-DZdv509B.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-ClM9P7yo.js → pieDiagram-7S7Q4E2Y-CmD4-b0K.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-DwnEak2J.js → quadrantDiagram-CIZ2JOQS-DtKxNxlS.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-rK4hxt9P.js → railroadDiagram-AXF67PYL-D48iIoiS.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-Cjqa6vo3.js → requirementDiagram-LRYGKXZP-C3N0K-2p.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-D3Fa250Z.js → sankeyDiagram-W5VNT64P-CACWR-Xs.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-2PdrNajj.js → sequenceDiagram-SI44F4Z6-g_QgugvZ.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-BBcuGeZn.js → sizeCapture-X5ZJPWSS-DqLoRPGK.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-CSJX9X6s.js → stateDiagram-OKZ733FA-ES59VgMG.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DyCIq6jx.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-pOUU1bic.js → swimlanes-SLNWSIFB-fjyLVNWo.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CsKtO34q.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CAeqfQn0.js → timeline-definition-Z64GVDOM-Cd5-biKv.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-DYPLOMVO.js → vennDiagram-T6HMQDX7-CZTu6mPf.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-Dy2V0Cha.js → wardleyDiagram-T6FBY63Y-DR01jjbe.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-Dj9o7jrn.js → xychartDiagram-ELKLHX3M-iZcuGVGa.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/animation-frame-batcher.js +38 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +97 -3
- package/dist/worker/console/static-src/operator-chat/context-insights-store.js +64 -0
- package/dist/worker/console/static-src/operator-chat/process-label.js +11 -2
- package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +2 -1
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +2 -0
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +9 -0
- package/dist/worker/observe/node-context-insights.js +479 -0
- package/dist/workflows/dag/frontend-implementation-contract.js +3 -1
- package/dist/workflows/dag/frontend-plan-completeness.js +13 -3
- package/dist/workflows/dag/frontend-recovery-plan.js +10 -6
- package/dist/workflows/dag/frontend-typed-event-store.js +5 -0
- package/dist/workflows/dag/frontend-writer-admission.js +1 -0
- package/dist/workflows/dag/output-protocol.js +1 -0
- package/dist/workflows/dag/rerun-task.js +1 -0
- package/docs/README.md +1 -1
- package/docs/governance/harness-methodology-verification.md +11 -0
- package/package.json +1 -1
- package/dist/worker/console/static/assets/channel-CgLPkTw2.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-CuSD1Mhb.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-CuSD1Mhb.js +0 -1
- package/dist/worker/console/static/assets/index-DHBWEwz_.css +0 -1
- package/dist/worker/console/static/assets/index-JRfTUgP7.js +0 -478
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Cqskj0zt.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CM0ZIhNP.js +0 -8
|
@@ -19,7 +19,7 @@ import { OPERATOR_CHAT_ALLOWED_TOOLS, OPERATOR_CHAT_DENIED_TOOLS, OPERATOR_CHAT_
|
|
|
19
19
|
import { InvalidChatSessionModeError, SESSION_MODE_ACTION_DENIED_CODE, SESSION_MODE_ACTION_DENIED_MESSAGE, SESSION_MODE_IMMUTABLE_CODE, UnknownChatSessionModeError, isWorkflowSessionMode, parseCreateSessionMode, readStoredSessionMode, shouldAcceptOperatorSnapshot, } from "./session-mode.js";
|
|
20
20
|
import { buildModelCallableToolSchemas } from "./tool-adapter.js";
|
|
21
21
|
import { cleanChatTitle, acceptedOperationIdFromResult, isBlankChatSession } from "./session-store.js";
|
|
22
|
-
import { hashChatTurnPayload, projectChatToolEventPayload, projectCompactSnapshot, } from "./chat-event-store.js";
|
|
22
|
+
import { hashChatTurnPayload, projectChatToolEventPayload, projectUnknownChatEventPayload, projectCompactSnapshot, } from "./chat-event-store.js";
|
|
23
23
|
import { projectDeferredTurnSummary, projectDeferredTurnSummaries, } from "./deferred-turn.js";
|
|
24
24
|
import { THINKING_LEVELS, RuntimeSnapshotUnavailableError, } from "./pi-runtime.js";
|
|
25
25
|
import { ResourcePreferencesError, setSkillAutoInvocationPreference, } from "./resource-preferences-store.js";
|
|
@@ -36,6 +36,7 @@ import { dispatchOperatorAction } from "../operator-actions.js";
|
|
|
36
36
|
import { makeHumanGateCard, } from "./human-gate-card.js";
|
|
37
37
|
import { ContractApplyReceiptStore } from "./contract-apply-receipt-store.js";
|
|
38
38
|
import { projectTaskContext } from "./context-panel.js";
|
|
39
|
+
import { deriveContextInsights, estimateTokensFromText, } from "./context-insights.js";
|
|
39
40
|
import { deriveChatSessionTelemetry, deriveChatTurnTelemetry } from "./session-stats.js";
|
|
40
41
|
import { contractApplyPayloadHash, issueHumanGateToken, verifyHumanGateToken, } from "../human-gate-token.js";
|
|
41
42
|
import { sendJson } from "../routes.js";
|
|
@@ -197,6 +198,16 @@ export function projectStoredMessagesWithEventOrder(messages, events) {
|
|
|
197
198
|
...(finish
|
|
198
199
|
? { finishedSeq: finish.seq, finishedAt: finish.at }
|
|
199
200
|
: {}),
|
|
201
|
+
...(start && typeof start.data.step === "number"
|
|
202
|
+
? { step: start.data.step }
|
|
203
|
+
: {}),
|
|
204
|
+
...(start &&
|
|
205
|
+
typeof start.data.parentToolCallId ===
|
|
206
|
+
"string"
|
|
207
|
+
? {
|
|
208
|
+
parentToolCallId: start.data.parentToolCallId,
|
|
209
|
+
}
|
|
210
|
+
: {}),
|
|
200
211
|
};
|
|
201
212
|
});
|
|
202
213
|
}
|
|
@@ -243,10 +254,99 @@ function writeChatSse(res, event) {
|
|
|
243
254
|
/** Map a runtime ChatTurnEvent to the persisted event-store partial.
|
|
244
255
|
*
|
|
245
256
|
* Returns undefined for heartbeat (not persisted — keep-alive only). */
|
|
246
|
-
function turnEventToStorePartial(event) {
|
|
257
|
+
export function turnEventToStorePartial(event) {
|
|
247
258
|
switch (event.type) {
|
|
248
259
|
case "agent_start":
|
|
249
260
|
return { kind: "agent_start", data: {} };
|
|
261
|
+
case "step_start":
|
|
262
|
+
case "step_end":
|
|
263
|
+
return {
|
|
264
|
+
kind: event.type,
|
|
265
|
+
data: {
|
|
266
|
+
step: Number(event.step ?? 1),
|
|
267
|
+
...(event.type === "step_end"
|
|
268
|
+
? { outcome: String(event.outcome ?? "completed") }
|
|
269
|
+
: {}),
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
case "model_retry":
|
|
273
|
+
{
|
|
274
|
+
const retryState = event.state === "completed" || event.state === "failed"
|
|
275
|
+
? event.state
|
|
276
|
+
: "scheduled";
|
|
277
|
+
return {
|
|
278
|
+
kind: "model_retry",
|
|
279
|
+
data: {
|
|
280
|
+
step: Number(event.step ?? 1),
|
|
281
|
+
attempt: Number(event.attempt ?? 1),
|
|
282
|
+
...(typeof event.maxAttempts === "number"
|
|
283
|
+
? { maxAttempts: event.maxAttempts }
|
|
284
|
+
: {}),
|
|
285
|
+
...(typeof event.delayMs === "number" ? { delayMs: event.delayMs } : {}),
|
|
286
|
+
...(typeof event.errorMessage === "string"
|
|
287
|
+
? { errorMessage: event.errorMessage }
|
|
288
|
+
: {}),
|
|
289
|
+
state: retryState,
|
|
290
|
+
...(typeof event.success === "boolean" ? { success: event.success } : {}),
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
case "turn_max_tokens":
|
|
295
|
+
return {
|
|
296
|
+
kind: "turn_max_tokens",
|
|
297
|
+
data: { step: Number(event.step ?? 1) },
|
|
298
|
+
};
|
|
299
|
+
case "turn_error":
|
|
300
|
+
return {
|
|
301
|
+
kind: "turn_error",
|
|
302
|
+
data: {
|
|
303
|
+
...(typeof event.step === "number" ? { step: event.step } : {}),
|
|
304
|
+
...(typeof event.code === "string" ? { code: event.code } : {}),
|
|
305
|
+
message: String(event.message ?? "模型请求失败"),
|
|
306
|
+
},
|
|
307
|
+
};
|
|
308
|
+
case "request_context":
|
|
309
|
+
return {
|
|
310
|
+
kind: "request_context",
|
|
311
|
+
data: {
|
|
312
|
+
requestId: String(event.requestId ?? ""),
|
|
313
|
+
step: Number(event.step ?? 1),
|
|
314
|
+
...(event.model && typeof event.model === "object"
|
|
315
|
+
? { model: event.model }
|
|
316
|
+
: {}),
|
|
317
|
+
...(typeof event.thinkingLevel === "string"
|
|
318
|
+
? { thinkingLevel: event.thinkingLevel }
|
|
319
|
+
: {}),
|
|
320
|
+
systemPromptHash: String(event.systemPromptHash ?? ""),
|
|
321
|
+
systemPromptChars: Number(event.systemPromptChars ?? 0),
|
|
322
|
+
activeTools: Array.isArray(event.activeTools) ? event.activeTools : [],
|
|
323
|
+
inputChars: Number(event.inputChars ?? 0),
|
|
324
|
+
imageCount: Number(event.imageCount ?? 0),
|
|
325
|
+
sources: Array.isArray(event.sources) ? event.sources : [],
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
case "command":
|
|
329
|
+
return {
|
|
330
|
+
kind: "command",
|
|
331
|
+
data: {
|
|
332
|
+
commandId: String(event.commandId ?? ""),
|
|
333
|
+
name: String(event.name ?? "unknown"),
|
|
334
|
+
...(typeof event.argsPreview === "string"
|
|
335
|
+
? { argsPreview: event.argsPreview }
|
|
336
|
+
: {}),
|
|
337
|
+
...(typeof event.action === "string" ? { action: event.action } : {}),
|
|
338
|
+
outcome: event.outcome === "failed" ? "failed" : "completed",
|
|
339
|
+
...(typeof event.message === "string" ? { message: event.message } : {}),
|
|
340
|
+
},
|
|
341
|
+
};
|
|
342
|
+
case "unknown":
|
|
343
|
+
return {
|
|
344
|
+
kind: "unknown",
|
|
345
|
+
data: projectUnknownChatEventPayload({
|
|
346
|
+
eventType: String(event.eventType ?? "unknown"),
|
|
347
|
+
value: event.value,
|
|
348
|
+
}),
|
|
349
|
+
};
|
|
250
350
|
case "message_update":
|
|
251
351
|
case "message_end": {
|
|
252
352
|
const content = parseAssistantContent(event.content);
|
|
@@ -291,6 +391,10 @@ function turnEventToStorePartial(event) {
|
|
|
291
391
|
event.messageId
|
|
292
392
|
? { messageId: event.messageId }
|
|
293
393
|
: {}),
|
|
394
|
+
...(typeof event.step === "number" ? { step: event.step } : {}),
|
|
395
|
+
...(typeof event.stopReason === "string"
|
|
396
|
+
? { stopReason: event.stopReason }
|
|
397
|
+
: {}),
|
|
294
398
|
},
|
|
295
399
|
};
|
|
296
400
|
}
|
|
@@ -304,6 +408,10 @@ function turnEventToStorePartial(event) {
|
|
|
304
408
|
toolCallId: String(event.toolCallId ?? ""),
|
|
305
409
|
toolName: String(event.toolName ?? ""),
|
|
306
410
|
value: event.args,
|
|
411
|
+
...(typeof event.step === "number" ? { step: event.step } : {}),
|
|
412
|
+
...(typeof event.parentToolCallId === "string"
|
|
413
|
+
? { parentToolCallId: event.parentToolCallId }
|
|
414
|
+
: {}),
|
|
307
415
|
}),
|
|
308
416
|
};
|
|
309
417
|
case "tool_result": {
|
|
@@ -318,6 +426,10 @@ function turnEventToStorePartial(event) {
|
|
|
318
426
|
toolName: String(event.toolName ?? ""),
|
|
319
427
|
value: event.result,
|
|
320
428
|
isError: Boolean(event.isError),
|
|
429
|
+
...(typeof event.step === "number" ? { step: event.step } : {}),
|
|
430
|
+
...(typeof event.parentToolCallId === "string"
|
|
431
|
+
? { parentToolCallId: event.parentToolCallId }
|
|
432
|
+
: {}),
|
|
321
433
|
...(resultOperationId ? { operationId: resultOperationId } : {}),
|
|
322
434
|
}),
|
|
323
435
|
};
|
|
@@ -1029,6 +1141,16 @@ export async function handleGetChatSession(_req, res, deps, sessionId) {
|
|
|
1029
1141
|
turnId: event.turnId,
|
|
1030
1142
|
data: event.data,
|
|
1031
1143
|
})),
|
|
1144
|
+
conversationEvents: snapshot.filter((event) => [
|
|
1145
|
+
"step_start",
|
|
1146
|
+
"step_end",
|
|
1147
|
+
"model_retry",
|
|
1148
|
+
"turn_error",
|
|
1149
|
+
"turn_max_tokens",
|
|
1150
|
+
"request_context",
|
|
1151
|
+
"command",
|
|
1152
|
+
"unknown",
|
|
1153
|
+
].includes(event.kind)),
|
|
1032
1154
|
lastEventId: lastEvent?.eventId ?? null,
|
|
1033
1155
|
lastEventSeq: lastEvent?.seq ?? 0,
|
|
1034
1156
|
});
|
|
@@ -2982,7 +3104,8 @@ async function handleSddBingo(req, res, deps, sessionId) {
|
|
|
2982
3104
|
throw new SddDataAlignmentError("SDD_INVALID_SKILL_NAME", "请求体只允许 skillName 字段", 400);
|
|
2983
3105
|
}
|
|
2984
3106
|
const result = await deps.sddDataAlignment.report(sessionId, body.skillName);
|
|
2985
|
-
|
|
3107
|
+
const turnId = deps.events.latestTurnId(sessionId) ?? `${sessionId}:operator-action`;
|
|
3108
|
+
deps.events.append(sessionId, turnId, {
|
|
2986
3109
|
kind: "operator-action",
|
|
2987
3110
|
data: {
|
|
2988
3111
|
schemaVersion: 1,
|
|
@@ -2991,6 +3114,17 @@ async function handleSddBingo(req, res, deps, sessionId) {
|
|
|
2991
3114
|
telemetrySessionId: result.telemetrySessionId,
|
|
2992
3115
|
},
|
|
2993
3116
|
});
|
|
3117
|
+
deps.events.append(sessionId, `${sessionId}:command:${result.telemetrySessionId}`, {
|
|
3118
|
+
kind: "command",
|
|
3119
|
+
data: {
|
|
3120
|
+
commandId: `sdd-bingo:${result.telemetrySessionId}`,
|
|
3121
|
+
name: "sdd-bingo",
|
|
3122
|
+
...(result.skillName ? { argsPreview: result.skillName } : {}),
|
|
3123
|
+
action: "sdd-bingo",
|
|
3124
|
+
outcome: "completed",
|
|
3125
|
+
message: `Session: ${result.telemetrySessionId}`,
|
|
3126
|
+
},
|
|
3127
|
+
});
|
|
2994
3128
|
sendJson(res, 200, {
|
|
2995
3129
|
ok: true,
|
|
2996
3130
|
skillName: result.skillName,
|
|
@@ -3075,6 +3209,73 @@ export async function handleRuntimeContext(res, deps, sessionId) {
|
|
|
3075
3209
|
}),
|
|
3076
3210
|
});
|
|
3077
3211
|
}
|
|
3212
|
+
/**
|
|
3213
|
+
* GET /sessions/:id/context-insights: dsh-context parity dashboard projection.
|
|
3214
|
+
* Folds the persisted event ring (works for idle/restored sessions) and, when
|
|
3215
|
+
* the Pi session is live, anchors the estimate with the runtime snapshot's
|
|
3216
|
+
* system-prompt size + active tool count. Read-only; never fabricates payload
|
|
3217
|
+
* text beyond the bounded previews already stored on the ring.
|
|
3218
|
+
*/
|
|
3219
|
+
export async function handleContextInsights(res, deps, sessionId) {
|
|
3220
|
+
const record = await deps.store.get(sessionId);
|
|
3221
|
+
if (!record) {
|
|
3222
|
+
sendJson(res, 404, {
|
|
3223
|
+
ok: false,
|
|
3224
|
+
error: { code: "NOT_FOUND", message: `chat session not found: ${sessionId}` },
|
|
3225
|
+
});
|
|
3226
|
+
return;
|
|
3227
|
+
}
|
|
3228
|
+
await deps.operationLinker.recoverSession(sessionId);
|
|
3229
|
+
const snapshot = deps.events.snapshot(sessionId);
|
|
3230
|
+
let systemPromptChars;
|
|
3231
|
+
let systemPromptPreview;
|
|
3232
|
+
let activeTools;
|
|
3233
|
+
let skillInjections;
|
|
3234
|
+
try {
|
|
3235
|
+
const runtimeSnapshot = await deps.runtime.getRuntimeSnapshot(sessionId, {
|
|
3236
|
+
includeRaw: true,
|
|
3237
|
+
});
|
|
3238
|
+
if (runtimeSnapshot) {
|
|
3239
|
+
systemPromptChars = runtimeSnapshot.systemPrompt.characters;
|
|
3240
|
+
const raw = runtimeSnapshot.systemPrompt.raw ??
|
|
3241
|
+
runtimeSnapshot.systemPrompt.text;
|
|
3242
|
+
if (typeof raw === "string" && raw) {
|
|
3243
|
+
systemPromptPreview = raw.slice(0, 120_000);
|
|
3244
|
+
}
|
|
3245
|
+
activeTools = runtimeSnapshot.activeTools;
|
|
3246
|
+
skillInjections = runtimeSnapshot.skills
|
|
3247
|
+
.slice(0, 50)
|
|
3248
|
+
.map((skill) => ({
|
|
3249
|
+
name: skill.name,
|
|
3250
|
+
tokens: estimateTokensFromText(skill.description ?? skill.name),
|
|
3251
|
+
}));
|
|
3252
|
+
}
|
|
3253
|
+
}
|
|
3254
|
+
catch {
|
|
3255
|
+
// Insights are derived from the durable ring; a live-snapshot miss only
|
|
3256
|
+
// drops the anchor figures / browser static categories, never the dashboard.
|
|
3257
|
+
}
|
|
3258
|
+
// Tool schemas: capabilities registry projection for whitelisted operator
|
|
3259
|
+
// actions, plus Pi builtins active on this session.
|
|
3260
|
+
const schemaTools = buildModelCallableToolSchemas().map((tool) => ({
|
|
3261
|
+
id: tool.toolId,
|
|
3262
|
+
description: tool.description,
|
|
3263
|
+
}));
|
|
3264
|
+
const activeSet = new Set((activeTools ?? []).map((t) => t.toLowerCase()));
|
|
3265
|
+
const builtinTools = (activeTools ?? [])
|
|
3266
|
+
.filter((name) => !schemaTools.some((t) => t.id === name))
|
|
3267
|
+
.map((name) => ({ id: name, description: "" }));
|
|
3268
|
+
const insights = deriveContextInsights(snapshot, {
|
|
3269
|
+
sessionId,
|
|
3270
|
+
...(systemPromptChars !== undefined ? { systemPromptChars } : {}),
|
|
3271
|
+
...(systemPromptPreview !== undefined
|
|
3272
|
+
? { systemPromptPreview }
|
|
3273
|
+
: {}),
|
|
3274
|
+
tools: [...schemaTools, ...builtinTools],
|
|
3275
|
+
...(skillInjections ? { skillInjections } : {}),
|
|
3276
|
+
});
|
|
3277
|
+
sendJson(res, 200, { ok: true, insights });
|
|
3278
|
+
}
|
|
3078
3279
|
// Exported for the direct handler-boundary tests (trace binding for
|
|
3079
3280
|
// vt-route-model-errors); router dispatch behavior is unchanged.
|
|
3080
3281
|
export async function handleModels(req, res, deps, sessionId) {
|
|
@@ -4594,7 +4795,7 @@ async function dispatchChatRequest(req, res, deps, pathname, workspaceScope) {
|
|
|
4594
4795
|
await handleSddBingo(req, res, deps, decodeURIComponent(sddBingo[1]));
|
|
4595
4796
|
return true;
|
|
4596
4797
|
}
|
|
4597
|
-
const m4Route = pathname.match(/^\/api\/operator\/v1\/chat\/sessions\/([^/]+)\/(draft|files|runtime-context|runtime-snapshot|models|model|reload|commands)$/);
|
|
4798
|
+
const m4Route = pathname.match(/^\/api\/operator\/v1\/chat\/sessions\/([^/]+)\/(draft|files|runtime-context|runtime-snapshot|context-insights|models|model|reload|commands)$/);
|
|
4598
4799
|
if (m4Route) {
|
|
4599
4800
|
const id = decodeURIComponent(m4Route[1]);
|
|
4600
4801
|
const route = m4Route[2];
|
|
@@ -4614,6 +4815,10 @@ async function dispatchChatRequest(req, res, deps, pathname, workspaceScope) {
|
|
|
4614
4815
|
await handleRuntimeSnapshot(req, res, deps, id);
|
|
4615
4816
|
return true;
|
|
4616
4817
|
}
|
|
4818
|
+
if (route === "context-insights" && method === "GET") {
|
|
4819
|
+
await handleContextInsights(res, deps, id);
|
|
4820
|
+
return true;
|
|
4821
|
+
}
|
|
4617
4822
|
if (route === "models" && method === "GET") {
|
|
4618
4823
|
await handleModels(req, res, deps, id);
|
|
4619
4824
|
return true;
|
|
@@ -42,6 +42,13 @@ export const SHORTCUTS = [
|
|
|
42
42
|
action: "reload",
|
|
43
43
|
source: "operator",
|
|
44
44
|
},
|
|
45
|
+
{
|
|
46
|
+
command: "/context",
|
|
47
|
+
label: "Context insights",
|
|
48
|
+
description: "打开上下文洞察仪表盘:构成、趋势、事件与文件活动",
|
|
49
|
+
action: "focus:context-insights",
|
|
50
|
+
source: "operator",
|
|
51
|
+
},
|
|
45
52
|
];
|
|
46
53
|
export const SDD_BINGO_SHORTCUT = {
|
|
47
54
|
command: "/sdd-bingo",
|
|
@@ -3,7 +3,89 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { getDisplayableAssistantBlocks, joinAssistantText, parseAssistantContent, splitFinalAssistantBlocks, } from "./assistant-content.js";
|
|
5
5
|
import { dagProgressActivityForTool, semanticActivityForTool, } from "./semantic-activity.js";
|
|
6
|
+
import { compareChatOrder } from "./turn-order.js";
|
|
6
7
|
import { ensureLinkedSubmissionOrder } from "./timeline-message-order.js";
|
|
8
|
+
function conversationNodeOrder(node) {
|
|
9
|
+
return { eventSeq: node.anchorSeq, createdAt: node.at };
|
|
10
|
+
}
|
|
11
|
+
function processItemOrder(item, group) {
|
|
12
|
+
const createdAt = item.createdAt ??
|
|
13
|
+
(item.kind === "tool" ? item.tool.createdAt : undefined) ??
|
|
14
|
+
group.assistants[0]?.createdAt ??
|
|
15
|
+
0;
|
|
16
|
+
const eventSeq = item.eventSeq ?? (item.kind === "tool" ? item.tool.eventSeq : undefined);
|
|
17
|
+
return eventSeq === undefined ? { createdAt } : { eventSeq, createdAt };
|
|
18
|
+
}
|
|
19
|
+
function compareFlowEntries(a, b) {
|
|
20
|
+
return compareChatOrder(a.order, b.order);
|
|
21
|
+
}
|
|
22
|
+
/** Base identity for a rendered process row. Content is deliberately excluded
|
|
23
|
+
* so streaming text updates keep the same React instance. */
|
|
24
|
+
function processItemKey(item, order) {
|
|
25
|
+
if (item.kind === "tool")
|
|
26
|
+
return `tool:${item.tool.id}`;
|
|
27
|
+
if (item.kind === "activity")
|
|
28
|
+
return `activity:${item.activity.id}`;
|
|
29
|
+
if (item.kind === "dag-progress")
|
|
30
|
+
return `dag-progress:${item.progress.id}`;
|
|
31
|
+
const anchor = order.eventSeq ?? order.createdAt;
|
|
32
|
+
return `${item.kind}:${anchor}`;
|
|
33
|
+
}
|
|
34
|
+
export function turnProcessItemKey(item, occurrence = 0) {
|
|
35
|
+
const order = {
|
|
36
|
+
...(item.eventSeq === undefined ? {} : { eventSeq: item.eventSeq }),
|
|
37
|
+
createdAt: item.createdAt ?? (item.kind === "tool" ? item.tool.createdAt : 0),
|
|
38
|
+
};
|
|
39
|
+
const base = processItemKey(item, order);
|
|
40
|
+
return occurrence === 0 ? base : `${base}:${occurrence}`;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Project one turn into the same ordered buckets used by the main timeline and
|
|
44
|
+
* the trajectory view. Only existing request/running-step nodes are prelude;
|
|
45
|
+
* retry and other lifecycle nodes stay in the collapsible process window.
|
|
46
|
+
*/
|
|
47
|
+
export function projectTurnFlow(group) {
|
|
48
|
+
const conversationItems = group.conversationItems ?? [];
|
|
49
|
+
const prelude = conversationItems
|
|
50
|
+
.filter((item) => item.kind === "request" ||
|
|
51
|
+
(item.kind === "step" && item.node.status === "running"))
|
|
52
|
+
.sort((a, b) => compareChatOrder(conversationNodeOrder(a.node), conversationNodeOrder(b.node)));
|
|
53
|
+
const postAnswer = conversationItems
|
|
54
|
+
.filter((item) => item.kind === "max-tokens")
|
|
55
|
+
.sort((a, b) => compareChatOrder(conversationNodeOrder(a.node), conversationNodeOrder(b.node)));
|
|
56
|
+
const preludeKeys = new Set(prelude.map((item) => item.node.key));
|
|
57
|
+
const postAnswerKeys = new Set(postAnswer.map((item) => item.node.key));
|
|
58
|
+
const process = [];
|
|
59
|
+
for (const item of group.processItems) {
|
|
60
|
+
process.push({
|
|
61
|
+
source: "process",
|
|
62
|
+
key: "",
|
|
63
|
+
item,
|
|
64
|
+
order: processItemOrder(item, group),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
for (const item of conversationItems) {
|
|
68
|
+
if (preludeKeys.has(item.node.key) || postAnswerKeys.has(item.node.key))
|
|
69
|
+
continue;
|
|
70
|
+
process.push({
|
|
71
|
+
source: "conversation",
|
|
72
|
+
key: `conversation:${item.node.key}`,
|
|
73
|
+
item,
|
|
74
|
+
order: conversationNodeOrder(item.node),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
process.sort(compareFlowEntries);
|
|
78
|
+
const occurrences = new Map();
|
|
79
|
+
for (const entry of process) {
|
|
80
|
+
const base = entry.source === "conversation"
|
|
81
|
+
? entry.key
|
|
82
|
+
: processItemKey(entry.item, entry.order);
|
|
83
|
+
const occurrence = occurrences.get(base) ?? 0;
|
|
84
|
+
occurrences.set(base, occurrence + 1);
|
|
85
|
+
entry.key = occurrence === 0 ? base : `${base}:${occurrence}`;
|
|
86
|
+
}
|
|
87
|
+
return { prelude, process, postAnswer };
|
|
88
|
+
}
|
|
7
89
|
function emptyGroup(key, turnId) {
|
|
8
90
|
return {
|
|
9
91
|
key,
|
|
@@ -11,6 +93,7 @@ function emptyGroup(key, turnId) {
|
|
|
11
93
|
assistants: [],
|
|
12
94
|
tools: [],
|
|
13
95
|
processItems: [],
|
|
96
|
+
conversationItems: [],
|
|
14
97
|
live: false,
|
|
15
98
|
};
|
|
16
99
|
}
|
|
@@ -92,6 +175,10 @@ export function hydrateSessionThread(raw) {
|
|
|
92
175
|
? finishedAtMs
|
|
93
176
|
: createdAt,
|
|
94
177
|
turnId: item.turnId ?? turnId,
|
|
178
|
+
...(item.step === undefined ? {} : { step: item.step }),
|
|
179
|
+
...(item.parentToolCallId
|
|
180
|
+
? { parentToolCallId: item.parentToolCallId }
|
|
181
|
+
: {}),
|
|
95
182
|
...(item.eventSeq === undefined ? {} : { eventSeq: item.eventSeq }),
|
|
96
183
|
...(item.finishedSeq === undefined
|
|
97
184
|
? {}
|
|
@@ -132,17 +219,21 @@ function flushToolBuffer(processItems, buffer) {
|
|
|
132
219
|
return;
|
|
133
220
|
const sorted = sortToolsStable(buffer);
|
|
134
221
|
for (const tool of sorted) {
|
|
222
|
+
const order = {
|
|
223
|
+
...(tool.eventSeq === undefined ? {} : { eventSeq: tool.eventSeq }),
|
|
224
|
+
createdAt: tool.createdAt,
|
|
225
|
+
};
|
|
135
226
|
const dagProgress = dagProgressActivityForTool(tool);
|
|
136
227
|
if (dagProgress) {
|
|
137
|
-
processItems.push({ kind: "dag-progress", progress: dagProgress });
|
|
228
|
+
processItems.push({ kind: "dag-progress", progress: dagProgress, ...order });
|
|
138
229
|
continue;
|
|
139
230
|
}
|
|
140
231
|
const activity = semanticActivityForTool(tool);
|
|
141
232
|
if (activity) {
|
|
142
|
-
processItems.push({ kind: "activity", activity });
|
|
233
|
+
processItems.push({ kind: "activity", activity, ...order });
|
|
143
234
|
}
|
|
144
235
|
else {
|
|
145
|
-
processItems.push({ kind: "tool", tool });
|
|
236
|
+
processItems.push({ kind: "tool", tool, ...order });
|
|
146
237
|
}
|
|
147
238
|
}
|
|
148
239
|
}
|
|
@@ -185,12 +276,23 @@ function fillProcessDetails(group) {
|
|
|
185
276
|
};
|
|
186
277
|
for (const block of blocks) {
|
|
187
278
|
if (block.type === "thinking") {
|
|
188
|
-
items.push({
|
|
279
|
+
items.push({
|
|
280
|
+
kind: "thinking",
|
|
281
|
+
thinking: block.thinking,
|
|
282
|
+
...(anchorSeq === undefined ? {} : { eventSeq: anchorSeq }),
|
|
283
|
+
createdAt: anchorAt,
|
|
284
|
+
});
|
|
189
285
|
continue;
|
|
190
286
|
}
|
|
191
287
|
if (block.type === "text") {
|
|
192
|
-
if (block.text.trim())
|
|
193
|
-
items.push({
|
|
288
|
+
if (block.text.trim()) {
|
|
289
|
+
items.push({
|
|
290
|
+
kind: "text",
|
|
291
|
+
text: block.text,
|
|
292
|
+
...(anchorSeq === undefined ? {} : { eventSeq: anchorSeq }),
|
|
293
|
+
createdAt: anchorAt,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
194
296
|
continue;
|
|
195
297
|
}
|
|
196
298
|
const tool = group.tools.find((entry) => entry.id === block.toolCallId);
|
|
@@ -213,7 +315,12 @@ function fillProcessDetails(group) {
|
|
|
213
315
|
anchorAt = tool.createdAt;
|
|
214
316
|
}
|
|
215
317
|
if (includeProviderError && assistant.providerError) {
|
|
216
|
-
items.push({
|
|
318
|
+
items.push({
|
|
319
|
+
kind: "provider-error",
|
|
320
|
+
error: assistant.providerError,
|
|
321
|
+
...(anchorSeq === undefined ? {} : { eventSeq: anchorSeq }),
|
|
322
|
+
createdAt: anchorAt,
|
|
323
|
+
});
|
|
217
324
|
}
|
|
218
325
|
flushItems();
|
|
219
326
|
// Preserve the old-data fallback after this stage. Sequenced unmatched
|
|
@@ -401,6 +508,14 @@ export function buildTurnProcessGroups(input) {
|
|
|
401
508
|
assigned.add(tool.id);
|
|
402
509
|
}
|
|
403
510
|
}
|
|
511
|
+
for (const node of input.conversationNodes ?? []) {
|
|
512
|
+
if (node.location.kind === "session")
|
|
513
|
+
continue;
|
|
514
|
+
const turnId = node.location.turnId;
|
|
515
|
+
if (!groups.some((group) => group.turnId === turnId)) {
|
|
516
|
+
startGroup(`turn-${turnId}`, turnId);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
404
519
|
for (const group of groups) {
|
|
405
520
|
group.tools.sort((a, b) => {
|
|
406
521
|
if (a.eventSeq !== undefined && b.eventSeq !== undefined) {
|
|
@@ -413,6 +528,12 @@ export function buildTurnProcessGroups(input) {
|
|
|
413
528
|
input.activeAssistantId !== null &&
|
|
414
529
|
group.assistants.some((a) => a.id === input.activeAssistantId);
|
|
415
530
|
fillProcessDetails(group);
|
|
531
|
+
group.conversationItems = (input.conversationNodes ?? [])
|
|
532
|
+
.filter((node) => node.location.kind !== "session" && node.location.turnId === group.turnId)
|
|
533
|
+
.map((node) => ({ kind: node.kind, node }));
|
|
534
|
+
if (group.conversationItems.some((item) => item.kind === "turn-error")) {
|
|
535
|
+
group.processItems = group.processItems.filter((item) => item.kind !== "provider-error");
|
|
536
|
+
}
|
|
416
537
|
}
|
|
417
538
|
return groups;
|
|
418
539
|
}
|
|
@@ -128,6 +128,9 @@ export function parseEngineeringBoundaryFromParams(p) {
|
|
|
128
128
|
forbidden: Array.isArray(capabilityBoundaryRaw.forbidden)
|
|
129
129
|
? capabilityBoundaryRaw.forbidden.filter((x) => typeof x === "string" && x.trim().length > 0)
|
|
130
130
|
: undefined,
|
|
131
|
+
requiredClauses: Array.isArray(capabilityBoundaryRaw.requiredClauses)
|
|
132
|
+
? capabilityBoundaryRaw.requiredClauses.filter((x) => typeof x === "string" && x.trim().length > 0)
|
|
133
|
+
: undefined,
|
|
131
134
|
}
|
|
132
135
|
: undefined;
|
|
133
136
|
const interactionIds = asList(p.interactionIds ?? p.interactionId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-
|
|
1
|
+
import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-ClMg8xmV.js";import{p as f}from"./chunk-JWPE2WC7-CDdO-jPJ.js";import{_ as n,l as o}from"./mermaid.core-BdAMrTf7.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-B8u1_FtM.js";import"./index-wKEJUaP5.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-
|
|
1
|
+
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-BdAMrTf7.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
|