dsh-cloudq 0.1.7 → 0.1.9
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/lib/client.js +51 -6
- package/lib/index.js +10 -3
- package/package.json +1 -1
- package/skills/cloudq/scripts/tcloud_sse_api.py +2 -3
package/lib/client.js
CHANGED
|
@@ -599,14 +599,17 @@ linear-gradient(-30deg, transparent 49.5%, #2c2c31 49.5%, #2c2c31 50.5%, transpa
|
|
|
599
599
|
return !!sessionId && cloudqSessions.has(sessionId);
|
|
600
600
|
}
|
|
601
601
|
let cloudqHistorySync = null;
|
|
602
|
+
let reconcileQueued = false;
|
|
602
603
|
function reconcileCloudqSessionsFromHost() {
|
|
603
|
-
if (cloudqHistorySync)
|
|
604
|
+
if (cloudqHistorySync) {
|
|
605
|
+
reconcileQueued = true;
|
|
606
|
+
return cloudqHistorySync;
|
|
607
|
+
}
|
|
604
608
|
cloudqHistorySync = cloudqRequest(API_CLOUDQ_SESSIONS, void 0, 6e4).then((response) => {
|
|
605
609
|
const detected = new Set(Array.isArray(response?.sessionIds) ? response.sessionIds : []);
|
|
606
|
-
const
|
|
607
|
-
|
|
608
|
-
const
|
|
609
|
-
if (summary && !summary.blank && !detected.has(sessionId)) cloudqSessions.delete(sessionId);
|
|
610
|
+
const known = new Set(Array.isArray(response?.knownIds) ? response.knownIds : []);
|
|
611
|
+
if (known.size > 0) {
|
|
612
|
+
for (const sessionId of Array.from(cloudqSessions)) if (!known.has(sessionId)) cloudqSessions.delete(sessionId);
|
|
610
613
|
}
|
|
611
614
|
for (const sessionId of detected) cloudqSessions.add(sessionId);
|
|
612
615
|
saveCloudqSessions(cloudqSessions);
|
|
@@ -614,6 +617,10 @@ linear-gradient(-30deg, transparent 49.5%, #2c2c31 49.5%, #2c2c31 50.5%, transpa
|
|
|
614
617
|
return detected;
|
|
615
618
|
}).catch(() => /* @__PURE__ */ new Set()).finally(() => {
|
|
616
619
|
cloudqHistorySync = null;
|
|
620
|
+
if (reconcileQueued) {
|
|
621
|
+
reconcileQueued = false;
|
|
622
|
+
reconcileCloudqSessionsFromHost();
|
|
623
|
+
}
|
|
617
624
|
});
|
|
618
625
|
return cloudqHistorySync;
|
|
619
626
|
}
|
|
@@ -792,6 +799,17 @@ linear-gradient(-30deg, transparent 49.5%, #2c2c31 49.5%, #2c2c31 50.5%, transpa
|
|
|
792
799
|
* order (manual and recent-order variants). Only if a collapsed/search
|
|
793
800
|
* view prevents an exact sequence match do we fall back to title matching.
|
|
794
801
|
*/
|
|
802
|
+
function rowSessionId(row) {
|
|
803
|
+
const fiberKey = Object.keys(row).find((key) => key.startsWith("__reactFiber$"));
|
|
804
|
+
if (!fiberKey) return void 0;
|
|
805
|
+
let fiber = row[fiberKey];
|
|
806
|
+
for (let depth = 0; fiber && depth < 12; depth += 1) {
|
|
807
|
+
const props = fiber.memoizedProps;
|
|
808
|
+
const id = props?.node?.id ?? props?.sessionId;
|
|
809
|
+
if (typeof id === "string" && id.startsWith("session-")) return id;
|
|
810
|
+
fiber = fiber.return;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
795
813
|
function installSessionBadges() {
|
|
796
814
|
let disposed = false;
|
|
797
815
|
let frame = 0;
|
|
@@ -821,7 +839,8 @@ linear-gradient(-30deg, transparent 49.5%, #2c2c31 49.5%, #2c2c31 50.5%, transpa
|
|
|
821
839
|
const exact = exactOrder?.[index] ?? (selected ? snapshot.byId?.[snapshot.current] : void 0);
|
|
822
840
|
const candidates = exact ? [exact] : byTitle.get(title) ?? [];
|
|
823
841
|
const states = new Set(candidates.map((summary) => isCloudqSession(summary.id)));
|
|
824
|
-
const
|
|
842
|
+
const fiberId = rowSessionId(row);
|
|
843
|
+
const cloudq = fiberId !== void 0 ? isCloudqSession(fiberId) : candidates.length > 0 && states.size === 1 && states.has(true);
|
|
825
844
|
const existing = row.querySelector("[data-cloudq-session-badge=\"true\"]");
|
|
826
845
|
if (!cloudq) {
|
|
827
846
|
existing?.remove();
|
|
@@ -3615,12 +3634,38 @@ display: none;
|
|
|
3615
3634
|
window.dispatchEvent(new CustomEvent("dsh-cloudq:sessions-changed"));
|
|
3616
3635
|
};
|
|
3617
3636
|
window.addEventListener("storage", onStorage);
|
|
3637
|
+
const backstop = window.setInterval(() => {
|
|
3638
|
+
if (!disposed) reconcileCloudqSessionsFromHost();
|
|
3639
|
+
}, 3e4);
|
|
3618
3640
|
syncHistory();
|
|
3619
3641
|
return () => {
|
|
3620
3642
|
disposed = true;
|
|
3643
|
+
window.clearInterval(backstop);
|
|
3621
3644
|
window.removeEventListener("storage", onStorage);
|
|
3622
3645
|
};
|
|
3623
3646
|
}, "dsh-cloudq: reconcile durable session identities");
|
|
3647
|
+
ctx.effect(() => {
|
|
3648
|
+
const markIfCloudqClaim = () => {
|
|
3649
|
+
const textarea = document.querySelector("textarea[class*=input]");
|
|
3650
|
+
const draft = typeof textarea?.value === "string" ? textarea.value : "";
|
|
3651
|
+
if (!/^\s*\/cloudq(?:\s|$)/i.test(draft)) return;
|
|
3652
|
+
const sessionId = cloudqCtx?.sessions?.selection?.getSnapshot?.()?.sessionId ?? cloudqCtx?.sessions?.list?.getSnapshot?.()?.current;
|
|
3653
|
+
if (sessionId) markCloudqSession(sessionId);
|
|
3654
|
+
};
|
|
3655
|
+
const onKeyDown = (event) => {
|
|
3656
|
+
if (event.key !== "Enter" || event.shiftKey || event.isComposing) return;
|
|
3657
|
+
if (event.target instanceof HTMLTextAreaElement) markIfCloudqClaim();
|
|
3658
|
+
};
|
|
3659
|
+
const onClick = (event) => {
|
|
3660
|
+
if (event.target?.closest?.("button[class*=primary]")) markIfCloudqClaim();
|
|
3661
|
+
};
|
|
3662
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
3663
|
+
document.addEventListener("click", onClick, true);
|
|
3664
|
+
return () => {
|
|
3665
|
+
document.removeEventListener("keydown", onKeyDown, true);
|
|
3666
|
+
document.removeEventListener("click", onClick, true);
|
|
3667
|
+
};
|
|
3668
|
+
}, "dsh-cloudq: mark session on claim submit");
|
|
3624
3669
|
ctx.effect(installStyles, "dsh-cloudq: styles");
|
|
3625
3670
|
ctx.effect(() => {
|
|
3626
3671
|
const slots = ctx.slots;
|
package/lib/index.js
CHANGED
|
@@ -589,18 +589,23 @@ async function detectCloudqSessionIds(ctx) {
|
|
|
589
589
|
if (query === void 0) throw new HttpError(503, "session-query-unavailable", "当前 DSH 未启用会话查询服务。");
|
|
590
590
|
const records = await query.listSessions();
|
|
591
591
|
const ids = [];
|
|
592
|
+
const knownIds = [];
|
|
592
593
|
const queue = [...records];
|
|
593
594
|
const worker = async () => {
|
|
594
595
|
while (queue.length > 0) {
|
|
595
596
|
const sessionId = queue.shift()?.header?.id;
|
|
596
597
|
if (!sessionId) continue;
|
|
598
|
+
knownIds.push(sessionId);
|
|
597
599
|
try {
|
|
598
600
|
if (hasCloudqEvidence((await query.readSession(sessionId))?.events)) ids.push(sessionId);
|
|
599
601
|
} catch {}
|
|
600
602
|
}
|
|
601
603
|
};
|
|
602
604
|
await Promise.all(Array.from({ length: Math.min(6, queue.length) }, () => worker()));
|
|
603
|
-
return
|
|
605
|
+
return {
|
|
606
|
+
ids,
|
|
607
|
+
knownIds
|
|
608
|
+
};
|
|
604
609
|
}
|
|
605
610
|
/** Settings namespace for the browser card (must equal client card `key`). */
|
|
606
611
|
const SETTINGS_NAMESPACE = "dsh-cloudq";
|
|
@@ -627,7 +632,7 @@ function apply(ctx) {
|
|
|
627
632
|
name: "cloudq",
|
|
628
633
|
description: "用户咨询腾讯云产品资源、AWS、阿里云等多云资源时,查看智能顾问架构图、架构目录、架构详情、架构评估结果、绘制架构图、开通智能顾问时、AI智能巡检、AI容量监测、AI混沌演练、AI云诊断、主动预警、架构健康度、云运维问答、云资源查询、云成本优化、安全合规、云资源盘点、闲置资源检查、云产品最佳实践等AIOps、ChatOps、CloudOps操作时使用。",
|
|
629
634
|
whenToUse: "用户要求进入 CloudQ 模式、使用 CloudQ、咨询云上架构/资源/成本/巡检/诊断等多云或腾讯云运维问题,或点击输入栏 CloudQ 按钮时使用;也适用于架构图查看/评估、AI 巡检、容量监测、混沌演练、云诊断等场景。",
|
|
630
|
-
source: "
|
|
635
|
+
source: "bundled",
|
|
631
636
|
resourceBase: {
|
|
632
637
|
kind: "directory",
|
|
633
638
|
path: skillDirectory()
|
|
@@ -825,9 +830,11 @@ function apply(ctx) {
|
|
|
825
830
|
handler: async (request, response) => {
|
|
826
831
|
try {
|
|
827
832
|
assertSafeRequest(request, "GET");
|
|
833
|
+
const { ids, knownIds } = await detectCloudqSessionIds(ctx);
|
|
828
834
|
sendJson(response, 200, {
|
|
829
835
|
ok: true,
|
|
830
|
-
sessionIds:
|
|
836
|
+
sessionIds: ids,
|
|
837
|
+
knownIds
|
|
831
838
|
});
|
|
832
839
|
} catch (error) {
|
|
833
840
|
sendError(response, error);
|
package/package.json
CHANGED
|
@@ -280,9 +280,8 @@ def call_sse_api(question: str, session_id: str,
|
|
|
280
280
|
# OAuth / Connector 模式下需要标记使用 CloudQ 控制台凭证
|
|
281
281
|
if cred_source in ("oauth", "connector"):
|
|
282
282
|
payload["UseCloudQCredential"] = True
|
|
283
|
-
# Source
|
|
284
|
-
|
|
285
|
-
payload["Source"] = source
|
|
283
|
+
# Source 字段统一发送且固定为 dsh(CloudQChatCompletions 三种鉴权方式均支持)
|
|
284
|
+
payload["Source"] = "dsh"
|
|
286
285
|
payload_str = json.dumps(payload, separators=(",", ":"))
|
|
287
286
|
|
|
288
287
|
# ---- TC3-HMAC-SHA256 签名 ----
|