@aipanel/dsh-plugin 1.2.8 → 1.2.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/dist/index.js +113 -62
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -3,8 +3,10 @@ import fs2 from "node:fs";
|
|
|
3
3
|
import path2 from "node:path";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
5
|
|
|
6
|
-
// ../../core/es/constants.mjs
|
|
6
|
+
// ../../core/es/common/constants.mjs
|
|
7
7
|
var LOG_PREFIX = "[vite-plugin-aipanel]";
|
|
8
|
+
var CONTEXT_API_PATH = "/__aipanel_context__";
|
|
9
|
+
var HOST_EVENTS_API_PATH = "/__aipanel_host_events__";
|
|
8
10
|
var EXT_BROADCAST = {
|
|
9
11
|
PAGE_CONTEXT: "PAGE_CONTEXT",
|
|
10
12
|
THEME_CHANGE: "THEME_CHANGE",
|
|
@@ -18,12 +20,14 @@ var EXT_MSG = {
|
|
|
18
20
|
REQUEST_PAGE_CONTEXT: "REQUEST_PAGE_CONTEXT",
|
|
19
21
|
SELECTION_START: "SELECTION_START",
|
|
20
22
|
SELECTION_STOP: "SELECTION_STOP",
|
|
21
|
-
CS_QUERY_WINDOW: "__CS_QUERY_WINDOW__"
|
|
23
|
+
CS_QUERY_WINDOW: "__CS_QUERY_WINDOW__",
|
|
24
|
+
/** Side Panel → Background:立即轮询一次并回传当前服务信息 */
|
|
25
|
+
FORCE_POLL: "FORCE_POLL"
|
|
22
26
|
};
|
|
23
27
|
var SEVERITY_ERROR = 1;
|
|
24
28
|
var SEVERITY_WARN = 2;
|
|
25
29
|
|
|
26
|
-
// ../../core/es/logger-core.mjs
|
|
30
|
+
// ../../core/es/common/logger-core.mjs
|
|
27
31
|
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
28
32
|
LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
|
|
29
33
|
LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
|
|
@@ -92,7 +96,7 @@ function formatContext(context) {
|
|
|
92
96
|
return parts.join(" ");
|
|
93
97
|
}
|
|
94
98
|
|
|
95
|
-
// ../../core/es/node-logger.mjs
|
|
99
|
+
// ../../core/es/node/node-logger.mjs
|
|
96
100
|
var __defProp = Object.defineProperty;
|
|
97
101
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
98
102
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -504,20 +508,16 @@ async function runProjectDiagnostics(workspace) {
|
|
|
504
508
|
|
|
505
509
|
// dsh-plugin/src/events-relay.ts
|
|
506
510
|
var log3 = createNodeLogger("DshEventRelay");
|
|
507
|
-
var DEFAULT_EVENTS_API_PATH = "/__aipanel_host_events__";
|
|
508
511
|
var FLUSH_DELAY_MS = 120;
|
|
509
|
-
|
|
510
|
-
function transitionOf(type) {
|
|
512
|
+
function thinkingOf(type) {
|
|
511
513
|
switch (type) {
|
|
512
514
|
case "turn/start":
|
|
513
|
-
return { running: true, thinking: true };
|
|
514
515
|
case "step/start":
|
|
515
516
|
case "assistant/chunk":
|
|
516
|
-
return
|
|
517
|
+
return true;
|
|
517
518
|
case "assistant/message":
|
|
518
|
-
return { thinking: false };
|
|
519
519
|
case "turn/end":
|
|
520
|
-
return
|
|
520
|
+
return false;
|
|
521
521
|
default:
|
|
522
522
|
return null;
|
|
523
523
|
}
|
|
@@ -526,13 +526,12 @@ function setupEventRelay(ctx, config) {
|
|
|
526
526
|
const vitePort = config.vitePort ?? 0;
|
|
527
527
|
const token = config.eventsToken;
|
|
528
528
|
if (!token || vitePort <= 0) return;
|
|
529
|
-
const eventsPath = config.eventsPath ??
|
|
529
|
+
const eventsPath = config.eventsPath ?? HOST_EVENTS_API_PATH;
|
|
530
530
|
const eventsUrl = `http://127.0.0.1:${vitePort}${eventsPath}`;
|
|
531
531
|
const states = /* @__PURE__ */ new Map();
|
|
532
532
|
const lastSent = /* @__PURE__ */ new Map();
|
|
533
533
|
const lastTitles = /* @__PURE__ */ new Map();
|
|
534
534
|
const dirty = /* @__PURE__ */ new Set();
|
|
535
|
-
const idleTimers = /* @__PURE__ */ new Map();
|
|
536
535
|
let flushTimer = null;
|
|
537
536
|
let lastPostErrorAt = 0;
|
|
538
537
|
const scheduleFlush = () => {
|
|
@@ -547,61 +546,51 @@ function setupEventRelay(ctx, config) {
|
|
|
547
546
|
dirty.add(sessionId);
|
|
548
547
|
scheduleFlush();
|
|
549
548
|
};
|
|
550
|
-
const
|
|
551
|
-
|
|
552
|
-
if (
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
549
|
+
const ensureState = (sessionId) => {
|
|
550
|
+
let s = states.get(sessionId);
|
|
551
|
+
if (s === void 0) {
|
|
552
|
+
s = { running: false, thinking: false };
|
|
553
|
+
states.set(sessionId, s);
|
|
554
|
+
}
|
|
555
|
+
return s;
|
|
556
|
+
};
|
|
557
|
+
const handleAgentStatus = ({ agent, status }) => {
|
|
558
|
+
const sessionId = String(agent.session.id);
|
|
559
|
+
if (!sessionId) return;
|
|
560
|
+
const running = status === "running";
|
|
561
|
+
const s = ensureState(sessionId);
|
|
562
|
+
if (s.running === running) return;
|
|
563
|
+
s.running = running;
|
|
564
|
+
if (!running) s.thinking = false;
|
|
565
|
+
markDirty(sessionId);
|
|
563
566
|
};
|
|
564
567
|
const handleSessionEvent = (session, event) => {
|
|
565
|
-
const sessionId = session?.id;
|
|
566
|
-
if (!sessionId
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
const
|
|
568
|
+
const sessionId = String(session?.id ?? "");
|
|
569
|
+
if (!sessionId) return;
|
|
570
|
+
const type = typeof event?.type === "string" ? event.type : "";
|
|
571
|
+
if (type === "session/title") {
|
|
572
|
+
const titleData = event.data;
|
|
573
|
+
const title = typeof titleData?.title === "string" ? titleData.title.trim() : "";
|
|
570
574
|
if (title.length > 0 && title !== lastTitles.get(sessionId)) {
|
|
571
575
|
lastTitles.set(sessionId, title);
|
|
576
|
+
const ts = event.time;
|
|
572
577
|
post({
|
|
573
578
|
type: "session.updated",
|
|
574
579
|
session: {
|
|
575
580
|
id: sessionId,
|
|
576
581
|
title,
|
|
577
|
-
|
|
578
|
-
updatedAt: typeof event.time === "number" ? event.time : Date.now()
|
|
582
|
+
updatedAt: typeof ts === "number" ? ts : Date.now()
|
|
579
583
|
}
|
|
580
584
|
});
|
|
581
585
|
}
|
|
582
586
|
return;
|
|
583
587
|
}
|
|
584
|
-
const
|
|
585
|
-
if (
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
if (tr === null) return;
|
|
591
|
-
let s = states.get(sessionId);
|
|
592
|
-
if (s === void 0) {
|
|
593
|
-
s = { running: false, thinking: false };
|
|
594
|
-
states.set(sessionId, s);
|
|
595
|
-
}
|
|
596
|
-
const next = {
|
|
597
|
-
running: tr.running !== void 0 ? tr.running : s.running,
|
|
598
|
-
thinking: tr.thinking !== void 0 ? tr.thinking : s.thinking
|
|
599
|
-
};
|
|
600
|
-
const changed = next.running !== s.running || next.thinking !== s.thinking;
|
|
601
|
-
s.running = next.running;
|
|
602
|
-
s.thinking = next.thinking;
|
|
603
|
-
if (event.type === "turn/end") scheduleIdleCheck(sessionId);
|
|
604
|
-
if (changed) markDirty(sessionId);
|
|
588
|
+
const thinking = thinkingOf(type);
|
|
589
|
+
if (thinking === null) return;
|
|
590
|
+
const s = ensureState(sessionId);
|
|
591
|
+
if (s.thinking === thinking) return;
|
|
592
|
+
s.thinking = thinking;
|
|
593
|
+
markDirty(sessionId);
|
|
605
594
|
};
|
|
606
595
|
const flush = () => {
|
|
607
596
|
const pending = [...dirty];
|
|
@@ -648,15 +637,15 @@ function setupEventRelay(ctx, config) {
|
|
|
648
637
|
}
|
|
649
638
|
});
|
|
650
639
|
};
|
|
651
|
-
|
|
652
|
-
|
|
640
|
+
ctx.on("agent/status", handleAgentStatus);
|
|
641
|
+
ctx.on("session/event", handleSessionEvent, { global: true });
|
|
653
642
|
}
|
|
654
643
|
|
|
655
644
|
// dsh-plugin/src/index.ts
|
|
656
645
|
var name = "aipanel";
|
|
657
646
|
var inject = ["tools"];
|
|
647
|
+
var log4 = createNodeLogger("DshPlugin");
|
|
658
648
|
var MUTATING_TOOLS = /* @__PURE__ */ new Set(["write", "edit", "apply_patch"]);
|
|
659
|
-
var DEFAULT_CONTEXT_API_PATH = "/__aipanel_context__";
|
|
660
649
|
function collectNodeIds(text) {
|
|
661
650
|
const ids = [];
|
|
662
651
|
const re = new RegExp("@\u8282\u70B9\\[(n[0-9a-z]+)\\]", "g");
|
|
@@ -666,13 +655,11 @@ function collectNodeIds(text) {
|
|
|
666
655
|
}
|
|
667
656
|
function buildNodeContext(e) {
|
|
668
657
|
const lines = [`\u8282\u70B9 ID\uFF1A${e.id ?? ""}`];
|
|
669
|
-
|
|
670
|
-
if (e.
|
|
671
|
-
if (e.column) lines.push(`\u4EE3\u7801\u6240\u5728\u5217\u53F7\uFF1A${e.column}`);
|
|
658
|
+
const loc = e.line ? e.column ? `:${e.line}:${e.column}` : `:${e.line}` : "";
|
|
659
|
+
if (e.filePath) lines.push(`\u6E90\u7801\u6587\u4EF6\u8DEF\u5F84\uFF1A${e.filePath}${loc}`);
|
|
672
660
|
if (e.description) lines.push(`DOM \u5143\u7D20\u9009\u62E9\u5668\uFF1A${e.description}`);
|
|
673
661
|
if (e.innerText) lines.push(`DOM \u5143\u7D20\u5185\u90E8\u6587\u672C\uFF1A${e.innerText.slice(0, 200)}`);
|
|
674
662
|
if (e.previewPageUrl) lines.push(`\u7528\u6237\u9009\u4E2D\u8282\u70B9\u65F6\u7684\u9875\u9762 URL\uFF1A${e.previewPageUrl}`);
|
|
675
|
-
if (e.previewPageTitle) lines.push(`\u9875\u9762\u6807\u9898\uFF1A${e.previewPageTitle}`);
|
|
676
663
|
return lines.join("\n");
|
|
677
664
|
}
|
|
678
665
|
function toDiagnosticEntries(items) {
|
|
@@ -705,12 +692,74 @@ ${s.text}`).join("\n\n");
|
|
|
705
692
|
|
|
706
693
|
${body}` : value.title;
|
|
707
694
|
}
|
|
695
|
+
function applyProviderSettings(ctx, config) {
|
|
696
|
+
const pending = [];
|
|
697
|
+
if (typeof config.agentPreset === "string" && config.agentPreset) {
|
|
698
|
+
pending.push({ ns: "agent-presets", patch: { default: config.agentPreset } });
|
|
699
|
+
}
|
|
700
|
+
if (typeof config.permissionPreset === "string" && config.permissionPreset) {
|
|
701
|
+
pending.push({ ns: "permission", patch: { defaultPreset: config.permissionPreset } });
|
|
702
|
+
}
|
|
703
|
+
if (typeof config.busyEnter === "string" && config.busyEnter) {
|
|
704
|
+
pending.push({ ns: "ui-conversation", patch: { busyEnter: config.busyEnter } });
|
|
705
|
+
}
|
|
706
|
+
if (pending.length === 0) return;
|
|
707
|
+
const settings = ctx.get("settings");
|
|
708
|
+
if (!settings) {
|
|
709
|
+
log4.warn("settings service unavailable; provider settings not applied via plugin");
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
const registered = (ns) => settings.describe()?.some((d) => String(d.ns) === ns) ?? false;
|
|
713
|
+
const APPLY_TIMEOUT_MS = 12e3;
|
|
714
|
+
const APPLY_INTERVAL_MS = 300;
|
|
715
|
+
const deadline = Date.now() + APPLY_TIMEOUT_MS;
|
|
716
|
+
let timer = null;
|
|
717
|
+
const applied = /* @__PURE__ */ new Set();
|
|
718
|
+
const tick = () => {
|
|
719
|
+
timer = null;
|
|
720
|
+
let stillPending = false;
|
|
721
|
+
for (let i = 0; i < pending.length; i++) {
|
|
722
|
+
if (applied.has(i)) continue;
|
|
723
|
+
const entry = pending[i];
|
|
724
|
+
if (!registered(entry.ns)) {
|
|
725
|
+
stillPending = true;
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
728
|
+
void settings.update(entry.ns, entry.patch).then(() => {
|
|
729
|
+
applied.add(i);
|
|
730
|
+
log4.debug("applied provider setting via plugin", { ns: entry.ns });
|
|
731
|
+
}).catch((err) => {
|
|
732
|
+
log4.warn("failed to apply provider setting via plugin", {
|
|
733
|
+
ns: entry.ns,
|
|
734
|
+
error: err instanceof Error ? err.message : String(err)
|
|
735
|
+
});
|
|
736
|
+
applied.add(i);
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
if (!stillPending && applied.size === pending.length) return;
|
|
740
|
+
if (Date.now() < deadline) {
|
|
741
|
+
timer = setTimeout(tick, APPLY_INTERVAL_MS);
|
|
742
|
+
timer.unref?.();
|
|
743
|
+
} else if (stillPending) {
|
|
744
|
+
log4.warn("provider settings not fully applied: namespace registration timed out", {
|
|
745
|
+
pending: pending.filter((_, i) => !applied.has(i)).map((p) => p.ns)
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
};
|
|
749
|
+
tick();
|
|
750
|
+
ctx.effect(
|
|
751
|
+
() => () => {
|
|
752
|
+
if (timer) clearTimeout(timer);
|
|
753
|
+
},
|
|
754
|
+
"aipanel: settings apply timer"
|
|
755
|
+
);
|
|
756
|
+
}
|
|
708
757
|
function apply(ctx, config = {}) {
|
|
709
758
|
const cwd = config.cwd ?? process.cwd();
|
|
710
759
|
const enableDiagnostics = config.enableDiagnostics ?? false;
|
|
711
760
|
const autoDiagnose = config.autoDiagnose ?? process.env.OPENCODE_ENABLE_LINT === "1";
|
|
712
761
|
const vitePort = config.vitePort ?? 0;
|
|
713
|
-
const contextApiPath = config.contextApiPath ??
|
|
762
|
+
const contextApiPath = config.contextApiPath ?? CONTEXT_API_PATH;
|
|
714
763
|
const tools = ctx.tools;
|
|
715
764
|
if (enableDiagnostics) {
|
|
716
765
|
const diagnosticsTool = {
|
|
@@ -883,9 +932,11 @@ ${contextText}`
|
|
|
883
932
|
eventsPath: config.eventsPath,
|
|
884
933
|
eventsToken: config.eventsToken
|
|
885
934
|
});
|
|
935
|
+
applyProviderSettings(ctx, config);
|
|
886
936
|
}
|
|
887
937
|
export {
|
|
888
938
|
apply,
|
|
939
|
+
applyProviderSettings,
|
|
889
940
|
inject,
|
|
890
941
|
name
|
|
891
942
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aipanel/dsh-plugin",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AIPanel for DeepSeek Harness (dsh):注入审查工具 run_diagnostics、编辑后自动诊断。",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -16,12 +16,14 @@
|
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
19
|
+
"@deepseek-ai/dsh-settings": "^0.1.2-rc.1",
|
|
19
20
|
"@deepseek-ai/dsh-agent": "^0.1.2-rc.1",
|
|
20
21
|
"@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
|
|
21
22
|
"@deepseek-ai/dsh-tools": "^0.1.2-rc.1",
|
|
22
23
|
"@deepseek-ai/dsh-util-values": "^0.1.2-rc.1",
|
|
24
|
+
"@deepseek-ai/dsh-session": "^0.1.2-rc.1",
|
|
23
25
|
"esbuild": "^0.25.0",
|
|
24
|
-
"@aipanel/core": "1.2.
|
|
26
|
+
"@aipanel/core": "1.2.9"
|
|
25
27
|
},
|
|
26
28
|
"scripts": {
|
|
27
29
|
"build": "esbuild src/index.ts --bundle --outfile=dist/index.js --platform=node --format=esm --target=node18 --external:@deepseek-ai/* --external:node:* --external:vue-tsc",
|