@aipanel/dsh-plugin 1.2.8 → 1.2.10
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 +195 -90
- 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,25 @@ 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;
|
|
29
|
+
var MUTATING_TOOLS = /* @__PURE__ */ new Set(["write", "edit", "apply_patch"]);
|
|
30
|
+
var OPENCODE_ENV = {
|
|
31
|
+
CONFIG_DIR: "OPENCODE_CONFIG_DIR",
|
|
32
|
+
CONTEXT_API_URL: "OPENCODE_CONTEXT_API_URL",
|
|
33
|
+
VITE_LOGS_API_URL: "OPENCODE_VITE_LOGS_API_URL",
|
|
34
|
+
LOG_FILES_JSON: "OPENCODE_LOG_FILES_JSON",
|
|
35
|
+
VERBOSE: "OPENCODE_VERBOSE",
|
|
36
|
+
ENABLE_LINT: "OPENCODE_ENABLE_LINT",
|
|
37
|
+
VUE_DEVTOOLS_API_URL: "OPENCODE_VUE_DEVTOOLS_API_URL",
|
|
38
|
+
WORKSPACE: "OPENCODE_WORKSPACE"
|
|
39
|
+
};
|
|
25
40
|
|
|
26
|
-
// ../../core/es/logger-core.mjs
|
|
41
|
+
// ../../core/es/common/logger-core.mjs
|
|
27
42
|
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
28
43
|
LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
|
|
29
44
|
LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
|
|
@@ -32,6 +47,28 @@ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
|
32
47
|
LogLevel2[LogLevel2["NONE"] = 4] = "NONE";
|
|
33
48
|
return LogLevel2;
|
|
34
49
|
})(LogLevel || {});
|
|
50
|
+
var LEVEL_NAMES = {
|
|
51
|
+
[
|
|
52
|
+
0
|
|
53
|
+
/* DEBUG */
|
|
54
|
+
]: "DEBUG",
|
|
55
|
+
[
|
|
56
|
+
1
|
|
57
|
+
/* INFO */
|
|
58
|
+
]: "INFO",
|
|
59
|
+
[
|
|
60
|
+
2
|
|
61
|
+
/* WARN */
|
|
62
|
+
]: "WARN",
|
|
63
|
+
[
|
|
64
|
+
3
|
|
65
|
+
/* ERROR */
|
|
66
|
+
]: "ERROR",
|
|
67
|
+
[
|
|
68
|
+
4
|
|
69
|
+
/* NONE */
|
|
70
|
+
]: "NONE"
|
|
71
|
+
};
|
|
35
72
|
var globalConfig = {
|
|
36
73
|
verbose: false,
|
|
37
74
|
level: 1,
|
|
@@ -43,6 +80,14 @@ var globalConfig = {
|
|
|
43
80
|
function getConfig() {
|
|
44
81
|
return globalConfig;
|
|
45
82
|
}
|
|
83
|
+
function getTimestamp() {
|
|
84
|
+
const now = /* @__PURE__ */ new Date();
|
|
85
|
+
const hours = String(now.getHours()).padStart(2, "0");
|
|
86
|
+
const minutes = String(now.getMinutes()).padStart(2, "0");
|
|
87
|
+
const seconds = String(now.getSeconds()).padStart(2, "0");
|
|
88
|
+
const ms = String(now.getMilliseconds()).padStart(3, "0");
|
|
89
|
+
return `${hours}:${minutes}:${seconds}.${ms}`;
|
|
90
|
+
}
|
|
46
91
|
function formatValue(value, depth = 0) {
|
|
47
92
|
if (depth > 3) return "...";
|
|
48
93
|
if (value === null) return "null";
|
|
@@ -92,7 +137,7 @@ function formatContext(context) {
|
|
|
92
137
|
return parts.join(" ");
|
|
93
138
|
}
|
|
94
139
|
|
|
95
|
-
// ../../core/es/node-logger.mjs
|
|
140
|
+
// ../../core/es/node/node-logger.mjs
|
|
96
141
|
var __defProp = Object.defineProperty;
|
|
97
142
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
98
143
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -115,21 +160,6 @@ var LEVEL_COLORS = {
|
|
|
115
160
|
[LogLevel.ERROR]: COLORS.red,
|
|
116
161
|
[LogLevel.NONE]: COLORS.reset
|
|
117
162
|
};
|
|
118
|
-
var LEVEL_NAMES = {
|
|
119
|
-
[LogLevel.DEBUG]: "DEBUG",
|
|
120
|
-
[LogLevel.INFO]: "INFO",
|
|
121
|
-
[LogLevel.WARN]: "WARN",
|
|
122
|
-
[LogLevel.ERROR]: "ERROR",
|
|
123
|
-
[LogLevel.NONE]: "NONE"
|
|
124
|
-
};
|
|
125
|
-
function getTimestamp() {
|
|
126
|
-
const now = /* @__PURE__ */ new Date();
|
|
127
|
-
const hours = String(now.getHours()).padStart(2, "0");
|
|
128
|
-
const minutes = String(now.getMinutes()).padStart(2, "0");
|
|
129
|
-
const seconds = String(now.getSeconds()).padStart(2, "0");
|
|
130
|
-
const ms = String(now.getMilliseconds()).padStart(3, "0");
|
|
131
|
-
return `${hours}:${minutes}:${seconds}.${ms}`;
|
|
132
|
-
}
|
|
133
163
|
function getCallerInfo(depth = 3) {
|
|
134
164
|
const stack = new Error().stack;
|
|
135
165
|
if (!stack) return "";
|
|
@@ -275,6 +305,19 @@ var JS_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
275
305
|
function isJsFile(filePath) {
|
|
276
306
|
return JS_EXTENSIONS.has(path.extname(filePath));
|
|
277
307
|
}
|
|
308
|
+
var DIAGNOSTICS_TOOL_DESCRIPTION = [
|
|
309
|
+
"\u8FD0\u884C ESLint \u4E0E TypeScript \u7C7B\u578B\u8BCA\u65AD\uFF0C\u8FD4\u56DE\u8BCA\u65AD\u7ED3\u679C\u3002",
|
|
310
|
+
"",
|
|
311
|
+
"**\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B**\uFF1A",
|
|
312
|
+
`- ESLint\uFF1AJavaScript / TypeScript / Vue \u6E90\u7801\uFF08${[...JS_EXTENSIONS].map((e) => `*${e}`).join(" ")}\uFF09`,
|
|
313
|
+
"- TypeScript \u7C7B\u578B\u68C0\u67E5\uFF1A*.ts *.tsx *.vue",
|
|
314
|
+
"",
|
|
315
|
+
"**\u4F55\u65F6\u4F7F\u7528\u6B64\u5DE5\u5177**\uFF1A",
|
|
316
|
+
"- \u521A\u5B8C\u6210\u4EE3\u7801\u4FEE\u6539\uFF0C\u60F3\u9A8C\u8BC1\u662F\u5426\u6709 ESLint \u9519\u8BEF\u6216\u7C7B\u578B\u9519\u8BEF",
|
|
317
|
+
"- \u5728\u63D0\u4EA4\u4EE3\u7801\u524D\u8FDB\u884C\u8D28\u91CF\u68C0\u67E5",
|
|
318
|
+
"- \u6392\u67E5\u7F16\u8F91\u5668\u672A\u663E\u793A\u4F46\u5B9E\u9645\u5B58\u5728\u7684\u7C7B\u578B\u95EE\u9898",
|
|
319
|
+
"- \u4E0D\u4F20\u53C2\u6570\u53EF\u5168\u91CF\u8BCA\u65AD\u6574\u4E2A\u9879\u76EE"
|
|
320
|
+
].join("\n");
|
|
278
321
|
var ESLintClass;
|
|
279
322
|
function loadESLint(workspace) {
|
|
280
323
|
if (ESLintClass) return;
|
|
@@ -290,7 +333,12 @@ function loadESLint(workspace) {
|
|
|
290
333
|
}
|
|
291
334
|
async function lintFiles(pattern, cwd, warnLimit = 5) {
|
|
292
335
|
loadESLint(cwd);
|
|
293
|
-
if (!ESLintClass)
|
|
336
|
+
if (!ESLintClass) {
|
|
337
|
+
return {
|
|
338
|
+
text: `[ESLint] \u672A\u8FD0\u884C\uFF1A\u65E0\u6CD5\u5728 workspace "${cwd}" \u89E3\u6790\u5230 eslint\uFF08\u4EC5\u663E\u793A TypeScript \u8BCA\u65AD\uFF09`,
|
|
339
|
+
diagnostics: []
|
|
340
|
+
};
|
|
341
|
+
}
|
|
294
342
|
try {
|
|
295
343
|
const eslint = new ESLintClass({ cwd });
|
|
296
344
|
const results = await eslint.lintFiles(pattern);
|
|
@@ -338,7 +386,10 @@ async function lintFiles(pattern, cwd, warnLimit = 5) {
|
|
|
338
386
|
return { text: lines.length > 0 ? lines.join("\n") : void 0, diagnostics };
|
|
339
387
|
} catch (err) {
|
|
340
388
|
log2.warn("ESLint failed", { pattern, error: err.message });
|
|
341
|
-
return {
|
|
389
|
+
return {
|
|
390
|
+
text: `[ESLint] \u8FD0\u884C\u5931\u8D25\uFF1A${err.message}\uFF08\u4EC5\u663E\u793A TypeScript \u8BCA\u65AD\uFF09`,
|
|
391
|
+
diagnostics: []
|
|
392
|
+
};
|
|
342
393
|
}
|
|
343
394
|
}
|
|
344
395
|
var _vueTscBin;
|
|
@@ -502,22 +553,33 @@ async function runProjectDiagnostics(workspace) {
|
|
|
502
553
|
return { eslintOutput, tscOutput: mergedTsc };
|
|
503
554
|
}
|
|
504
555
|
|
|
556
|
+
// ../../core/es/common/utils.mjs
|
|
557
|
+
var NODE_MENTION_RE = /@节点\[(n[0-9a-z]+)\]/g;
|
|
558
|
+
function parseNodeMentions(text) {
|
|
559
|
+
const out = [];
|
|
560
|
+
const seen = /* @__PURE__ */ new Set();
|
|
561
|
+
for (const m of text.matchAll(NODE_MENTION_RE)) {
|
|
562
|
+
const id = m[1];
|
|
563
|
+
if (!seen.has(id)) {
|
|
564
|
+
seen.add(id);
|
|
565
|
+
out.push(id);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return out;
|
|
569
|
+
}
|
|
570
|
+
|
|
505
571
|
// dsh-plugin/src/events-relay.ts
|
|
506
572
|
var log3 = createNodeLogger("DshEventRelay");
|
|
507
|
-
var DEFAULT_EVENTS_API_PATH = "/__aipanel_host_events__";
|
|
508
573
|
var FLUSH_DELAY_MS = 120;
|
|
509
|
-
|
|
510
|
-
function transitionOf(type) {
|
|
574
|
+
function thinkingOf(type) {
|
|
511
575
|
switch (type) {
|
|
512
576
|
case "turn/start":
|
|
513
|
-
return { running: true, thinking: true };
|
|
514
577
|
case "step/start":
|
|
515
578
|
case "assistant/chunk":
|
|
516
|
-
return
|
|
579
|
+
return true;
|
|
517
580
|
case "assistant/message":
|
|
518
|
-
return { thinking: false };
|
|
519
581
|
case "turn/end":
|
|
520
|
-
return
|
|
582
|
+
return false;
|
|
521
583
|
default:
|
|
522
584
|
return null;
|
|
523
585
|
}
|
|
@@ -526,13 +588,12 @@ function setupEventRelay(ctx, config) {
|
|
|
526
588
|
const vitePort = config.vitePort ?? 0;
|
|
527
589
|
const token = config.eventsToken;
|
|
528
590
|
if (!token || vitePort <= 0) return;
|
|
529
|
-
const eventsPath = config.eventsPath ??
|
|
591
|
+
const eventsPath = config.eventsPath ?? HOST_EVENTS_API_PATH;
|
|
530
592
|
const eventsUrl = `http://127.0.0.1:${vitePort}${eventsPath}`;
|
|
531
593
|
const states = /* @__PURE__ */ new Map();
|
|
532
594
|
const lastSent = /* @__PURE__ */ new Map();
|
|
533
595
|
const lastTitles = /* @__PURE__ */ new Map();
|
|
534
596
|
const dirty = /* @__PURE__ */ new Set();
|
|
535
|
-
const idleTimers = /* @__PURE__ */ new Map();
|
|
536
597
|
let flushTimer = null;
|
|
537
598
|
let lastPostErrorAt = 0;
|
|
538
599
|
const scheduleFlush = () => {
|
|
@@ -547,61 +608,51 @@ function setupEventRelay(ctx, config) {
|
|
|
547
608
|
dirty.add(sessionId);
|
|
548
609
|
scheduleFlush();
|
|
549
610
|
};
|
|
550
|
-
const
|
|
551
|
-
|
|
552
|
-
if (
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
611
|
+
const ensureState = (sessionId) => {
|
|
612
|
+
let s = states.get(sessionId);
|
|
613
|
+
if (s === void 0) {
|
|
614
|
+
s = { running: false, thinking: false };
|
|
615
|
+
states.set(sessionId, s);
|
|
616
|
+
}
|
|
617
|
+
return s;
|
|
618
|
+
};
|
|
619
|
+
const handleAgentStatus = ({ agent, status }) => {
|
|
620
|
+
const sessionId = String(agent.session.id);
|
|
621
|
+
if (!sessionId) return;
|
|
622
|
+
const running = status === "running";
|
|
623
|
+
const s = ensureState(sessionId);
|
|
624
|
+
if (s.running === running) return;
|
|
625
|
+
s.running = running;
|
|
626
|
+
if (!running) s.thinking = false;
|
|
627
|
+
markDirty(sessionId);
|
|
563
628
|
};
|
|
564
629
|
const handleSessionEvent = (session, event) => {
|
|
565
|
-
const sessionId = session?.id;
|
|
566
|
-
if (!sessionId
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
const
|
|
630
|
+
const sessionId = String(session?.id ?? "");
|
|
631
|
+
if (!sessionId) return;
|
|
632
|
+
const type = typeof event?.type === "string" ? event.type : "";
|
|
633
|
+
if (type === "session/title") {
|
|
634
|
+
const titleData = event.data;
|
|
635
|
+
const title = typeof titleData?.title === "string" ? titleData.title.trim() : "";
|
|
570
636
|
if (title.length > 0 && title !== lastTitles.get(sessionId)) {
|
|
571
637
|
lastTitles.set(sessionId, title);
|
|
638
|
+
const ts = event.time;
|
|
572
639
|
post({
|
|
573
640
|
type: "session.updated",
|
|
574
641
|
session: {
|
|
575
642
|
id: sessionId,
|
|
576
643
|
title,
|
|
577
|
-
|
|
578
|
-
updatedAt: typeof event.time === "number" ? event.time : Date.now()
|
|
644
|
+
updatedAt: typeof ts === "number" ? ts : Date.now()
|
|
579
645
|
}
|
|
580
646
|
});
|
|
581
647
|
}
|
|
582
648
|
return;
|
|
583
649
|
}
|
|
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);
|
|
650
|
+
const thinking = thinkingOf(type);
|
|
651
|
+
if (thinking === null) return;
|
|
652
|
+
const s = ensureState(sessionId);
|
|
653
|
+
if (s.thinking === thinking) return;
|
|
654
|
+
s.thinking = thinking;
|
|
655
|
+
markDirty(sessionId);
|
|
605
656
|
};
|
|
606
657
|
const flush = () => {
|
|
607
658
|
const pending = [...dirty];
|
|
@@ -648,31 +699,21 @@ function setupEventRelay(ctx, config) {
|
|
|
648
699
|
}
|
|
649
700
|
});
|
|
650
701
|
};
|
|
651
|
-
|
|
652
|
-
|
|
702
|
+
ctx.on("agent/status", handleAgentStatus);
|
|
703
|
+
ctx.on("session/event", handleSessionEvent, { global: true });
|
|
653
704
|
}
|
|
654
705
|
|
|
655
706
|
// dsh-plugin/src/index.ts
|
|
656
707
|
var name = "aipanel";
|
|
657
708
|
var inject = ["tools"];
|
|
658
|
-
var
|
|
659
|
-
var DEFAULT_CONTEXT_API_PATH = "/__aipanel_context__";
|
|
660
|
-
function collectNodeIds(text) {
|
|
661
|
-
const ids = [];
|
|
662
|
-
const re = new RegExp("@\u8282\u70B9\\[(n[0-9a-z]+)\\]", "g");
|
|
663
|
-
let m;
|
|
664
|
-
while ((m = re.exec(text)) !== null) ids.push(m[1]);
|
|
665
|
-
return ids;
|
|
666
|
-
}
|
|
709
|
+
var log4 = createNodeLogger("DshPlugin");
|
|
667
710
|
function buildNodeContext(e) {
|
|
668
711
|
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}`);
|
|
712
|
+
const loc = e.line ? e.column ? `:${e.line}:${e.column}` : `:${e.line}` : "";
|
|
713
|
+
if (e.filePath) lines.push(`\u6E90\u7801\u6587\u4EF6\u8DEF\u5F84\uFF1A${e.filePath}${loc}`);
|
|
672
714
|
if (e.description) lines.push(`DOM \u5143\u7D20\u9009\u62E9\u5668\uFF1A${e.description}`);
|
|
673
715
|
if (e.innerText) lines.push(`DOM \u5143\u7D20\u5185\u90E8\u6587\u672C\uFF1A${e.innerText.slice(0, 200)}`);
|
|
674
716
|
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
717
|
return lines.join("\n");
|
|
677
718
|
}
|
|
678
719
|
function toDiagnosticEntries(items) {
|
|
@@ -705,17 +746,79 @@ ${s.text}`).join("\n\n");
|
|
|
705
746
|
|
|
706
747
|
${body}` : value.title;
|
|
707
748
|
}
|
|
749
|
+
function applyProviderSettings(ctx, config) {
|
|
750
|
+
const pending = [];
|
|
751
|
+
if (typeof config.agentPreset === "string" && config.agentPreset) {
|
|
752
|
+
pending.push({ ns: "agent-presets", patch: { default: config.agentPreset } });
|
|
753
|
+
}
|
|
754
|
+
if (typeof config.permissionPreset === "string" && config.permissionPreset) {
|
|
755
|
+
pending.push({ ns: "permission", patch: { defaultPreset: config.permissionPreset } });
|
|
756
|
+
}
|
|
757
|
+
if (typeof config.busyEnter === "string" && config.busyEnter) {
|
|
758
|
+
pending.push({ ns: "ui-conversation", patch: { busyEnter: config.busyEnter } });
|
|
759
|
+
}
|
|
760
|
+
if (pending.length === 0) return;
|
|
761
|
+
const settings = ctx.get("settings");
|
|
762
|
+
if (!settings) {
|
|
763
|
+
log4.warn("settings service unavailable; provider settings not applied via plugin");
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
const registered = (ns) => settings.describe()?.some((d) => String(d.ns) === ns) ?? false;
|
|
767
|
+
const APPLY_TIMEOUT_MS = 12e3;
|
|
768
|
+
const APPLY_INTERVAL_MS = 300;
|
|
769
|
+
const deadline = Date.now() + APPLY_TIMEOUT_MS;
|
|
770
|
+
let timer = null;
|
|
771
|
+
const applied = /* @__PURE__ */ new Set();
|
|
772
|
+
const tick = () => {
|
|
773
|
+
timer = null;
|
|
774
|
+
let stillPending = false;
|
|
775
|
+
for (let i = 0; i < pending.length; i++) {
|
|
776
|
+
if (applied.has(i)) continue;
|
|
777
|
+
const entry = pending[i];
|
|
778
|
+
if (!registered(entry.ns)) {
|
|
779
|
+
stillPending = true;
|
|
780
|
+
continue;
|
|
781
|
+
}
|
|
782
|
+
void settings.update(entry.ns, entry.patch).then(() => {
|
|
783
|
+
applied.add(i);
|
|
784
|
+
log4.debug("applied provider setting via plugin", { ns: entry.ns });
|
|
785
|
+
}).catch((err) => {
|
|
786
|
+
log4.warn("failed to apply provider setting via plugin", {
|
|
787
|
+
ns: entry.ns,
|
|
788
|
+
error: err instanceof Error ? err.message : String(err)
|
|
789
|
+
});
|
|
790
|
+
applied.add(i);
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
if (!stillPending && applied.size === pending.length) return;
|
|
794
|
+
if (Date.now() < deadline) {
|
|
795
|
+
timer = setTimeout(tick, APPLY_INTERVAL_MS);
|
|
796
|
+
timer.unref?.();
|
|
797
|
+
} else if (stillPending) {
|
|
798
|
+
log4.warn("provider settings not fully applied: namespace registration timed out", {
|
|
799
|
+
pending: pending.filter((_, i) => !applied.has(i)).map((p) => p.ns)
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
tick();
|
|
804
|
+
ctx.effect(
|
|
805
|
+
() => () => {
|
|
806
|
+
if (timer) clearTimeout(timer);
|
|
807
|
+
},
|
|
808
|
+
"aipanel: settings apply timer"
|
|
809
|
+
);
|
|
810
|
+
}
|
|
708
811
|
function apply(ctx, config = {}) {
|
|
709
812
|
const cwd = config.cwd ?? process.cwd();
|
|
710
813
|
const enableDiagnostics = config.enableDiagnostics ?? false;
|
|
711
|
-
const autoDiagnose = config.autoDiagnose ?? process.env.
|
|
814
|
+
const autoDiagnose = config.autoDiagnose ?? process.env[OPENCODE_ENV.ENABLE_LINT] === "1";
|
|
712
815
|
const vitePort = config.vitePort ?? 0;
|
|
713
|
-
const contextApiPath = config.contextApiPath ??
|
|
816
|
+
const contextApiPath = config.contextApiPath ?? CONTEXT_API_PATH;
|
|
714
817
|
const tools = ctx.tools;
|
|
715
818
|
if (enableDiagnostics) {
|
|
716
819
|
const diagnosticsTool = {
|
|
717
820
|
name: "run_diagnostics",
|
|
718
|
-
description:
|
|
821
|
+
description: DIAGNOSTICS_TOOL_DESCRIPTION,
|
|
719
822
|
parameters: {
|
|
720
823
|
type: "object",
|
|
721
824
|
additionalProperties: false,
|
|
@@ -836,7 +939,7 @@ ${diagText}` }]
|
|
|
836
939
|
if (message.source.kind !== "user") continue;
|
|
837
940
|
for (const block of message.content) {
|
|
838
941
|
if (block.type !== "text") continue;
|
|
839
|
-
for (const id of
|
|
942
|
+
for (const id of parseNodeMentions(block.text)) ids.add(id);
|
|
840
943
|
}
|
|
841
944
|
}
|
|
842
945
|
if (ids.size === 0) return decision;
|
|
@@ -883,9 +986,11 @@ ${contextText}`
|
|
|
883
986
|
eventsPath: config.eventsPath,
|
|
884
987
|
eventsToken: config.eventsToken
|
|
885
988
|
});
|
|
989
|
+
applyProviderSettings(ctx, config);
|
|
886
990
|
}
|
|
887
991
|
export {
|
|
888
992
|
apply,
|
|
993
|
+
applyProviderSettings,
|
|
889
994
|
inject,
|
|
890
995
|
name
|
|
891
996
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aipanel/dsh-plugin",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.10",
|
|
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.10"
|
|
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",
|