@opentiny/next-sdk 0.2.7 → 0.2.8
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/agent/AgentModelProvider.ts +22 -10
- package/dist/agent/AgentModelProvider.d.ts +3 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.es.dev.js +389 -20
- package/dist/index.es.js +11135 -10850
- package/dist/index.js +1998 -1713
- package/dist/index.umd.dev.js +389 -20
- package/dist/index.umd.js +217 -49
- package/dist/{page-tool-bridge.d.ts → page-tools/bridge.d.ts} +11 -42
- package/dist/page-tools/effects.d.ts +36 -0
- package/dist/remoter/createRemoter.d.ts +2 -0
- package/dist/skills/index.d.ts +2 -1
- package/dist/webagent.dev.js +31 -7
- package/dist/webagent.es.dev.js +31 -7
- package/dist/webagent.es.js +33 -17
- package/dist/webagent.js +3 -3
- package/index.ts +1 -1
- package/package.json +1 -1
- package/{page-tool-bridge.ts → page-tools/bridge.ts} +36 -95
- package/page-tools/effects.ts +343 -0
- package/remoter/createRemoter.ts +25 -11
- package/skills/index.ts +109 -12
package/dist/index.umd.dev.js
CHANGED
|
@@ -27762,6 +27762,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
27762
27762
|
this.dropdownMenu.parentNode.removeChild(this.dropdownMenu);
|
|
27763
27763
|
}
|
|
27764
27764
|
}
|
|
27765
|
+
// 隐藏组件
|
|
27766
|
+
hide() {
|
|
27767
|
+
if (this.floatingBlock) {
|
|
27768
|
+
this.floatingBlock.style.display = "none";
|
|
27769
|
+
}
|
|
27770
|
+
this.closeDropdown();
|
|
27771
|
+
}
|
|
27772
|
+
// 显示组件
|
|
27773
|
+
show() {
|
|
27774
|
+
if (this.floatingBlock) {
|
|
27775
|
+
this.floatingBlock.style.display = "flex";
|
|
27776
|
+
}
|
|
27777
|
+
}
|
|
27765
27778
|
}
|
|
27766
27779
|
const createRemoter = (options = {}) => {
|
|
27767
27780
|
return new FloatingBlock(options);
|
|
@@ -50165,15 +50178,24 @@ Thought: 用户想要获取今天的日期,我需要调用日期相关的工
|
|
|
50165
50178
|
}
|
|
50166
50179
|
this.onUpdatedTools?.();
|
|
50167
50180
|
}
|
|
50168
|
-
/** 创建临时允许调用的tools
|
|
50169
|
-
_tempMergeTools(extraTool = {}) {
|
|
50170
|
-
const toolsResult = Object.values(this.mcpTools).reduce(
|
|
50181
|
+
/** 创建临时允许调用的 tools 集合,合并 mcpTools 与 extraTool */
|
|
50182
|
+
_tempMergeTools(extraTool = {}, deleteIgnored = true) {
|
|
50183
|
+
const toolsResult = Object.values(this.mcpTools).reduce(
|
|
50184
|
+
(acc, curr) => ({ ...acc, ...curr }),
|
|
50185
|
+
{}
|
|
50186
|
+
);
|
|
50171
50187
|
Object.assign(toolsResult, extraTool);
|
|
50172
|
-
|
|
50173
|
-
|
|
50174
|
-
|
|
50188
|
+
if (deleteIgnored) {
|
|
50189
|
+
this.ignoreToolnames.forEach((name16) => {
|
|
50190
|
+
delete toolsResult[name16];
|
|
50191
|
+
});
|
|
50192
|
+
}
|
|
50175
50193
|
return toolsResult;
|
|
50176
50194
|
}
|
|
50195
|
+
/** 获取当前激活的 tools 名称列表(过滤 ignoreToolnames) */
|
|
50196
|
+
_getActiveToolNames(tools) {
|
|
50197
|
+
return Object.keys(tools).filter((name16) => !this.ignoreToolnames.includes(name16));
|
|
50198
|
+
}
|
|
50177
50199
|
/** 生成 ReAct 模式的系统提示词(包含工具描述) */
|
|
50178
50200
|
_generateReActSystemPrompt(tools, modelName, baseSystemPrompt) {
|
|
50179
50201
|
const toolsPrompt = generateReActToolsPrompt(tools);
|
|
@@ -50517,12 +50539,14 @@ ${observationText}
|
|
|
50517
50539
|
throw new Error("LLM is not initialized");
|
|
50518
50540
|
}
|
|
50519
50541
|
await this.initClientsAndTools();
|
|
50542
|
+
const allTools = this._tempMergeTools(options.tools, false);
|
|
50520
50543
|
const chatOptions = {
|
|
50521
50544
|
// @ts-ignore ProviderV2 是所有llm的父类, 在每一个具体的llm 类都有一个选择model的函数用法
|
|
50522
50545
|
model: this.llm(model),
|
|
50523
50546
|
stopWhen: stepCountIs(maxSteps),
|
|
50524
50547
|
...options,
|
|
50525
|
-
tools:
|
|
50548
|
+
tools: allTools,
|
|
50549
|
+
activeTools: this._getActiveToolNames(allTools)
|
|
50526
50550
|
};
|
|
50527
50551
|
let lastUserMessage = null;
|
|
50528
50552
|
if (options.message && !options.messages) {
|
|
@@ -50552,6 +50576,282 @@ ${observationText}
|
|
|
50552
50576
|
return this._chat(streamText, options);
|
|
50553
50577
|
}
|
|
50554
50578
|
}
|
|
50579
|
+
let overlayElement = null;
|
|
50580
|
+
let labelElement = null;
|
|
50581
|
+
let styleElement = null;
|
|
50582
|
+
let activeCount = 0;
|
|
50583
|
+
const BODY_GLOW_CLASS = "next-sdk-tool-body-glow";
|
|
50584
|
+
function ensureDomReady() {
|
|
50585
|
+
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
50586
|
+
}
|
|
50587
|
+
function ensureStyleElement() {
|
|
50588
|
+
if (!ensureDomReady()) return;
|
|
50589
|
+
if (styleElement) return;
|
|
50590
|
+
const style = document.createElement("style");
|
|
50591
|
+
style.textContent = `
|
|
50592
|
+
.${BODY_GLOW_CLASS} {
|
|
50593
|
+
position: relative;
|
|
50594
|
+
}
|
|
50595
|
+
|
|
50596
|
+
.next-sdk-tool-overlay {
|
|
50597
|
+
position: fixed;
|
|
50598
|
+
inset: 0;
|
|
50599
|
+
z-index: 999999;
|
|
50600
|
+
pointer-events: none;
|
|
50601
|
+
display: flex;
|
|
50602
|
+
align-items: flex-end;
|
|
50603
|
+
justify-content: flex-start;
|
|
50604
|
+
padding: 0 0 18px 18px;
|
|
50605
|
+
background: transparent;
|
|
50606
|
+
animation: next-sdk-overlay-fade-in 260ms ease-out;
|
|
50607
|
+
}
|
|
50608
|
+
|
|
50609
|
+
.next-sdk-tool-overlay--exit {
|
|
50610
|
+
animation: next-sdk-overlay-fade-out 220ms ease-in forwards;
|
|
50611
|
+
}
|
|
50612
|
+
|
|
50613
|
+
.next-sdk-tool-overlay__glow-ring {
|
|
50614
|
+
display: none;
|
|
50615
|
+
}
|
|
50616
|
+
|
|
50617
|
+
.next-sdk-tool-overlay__panel {
|
|
50618
|
+
position: relative;
|
|
50619
|
+
min-width: min(320px, 78vw);
|
|
50620
|
+
max-width: min(420px, 82vw);
|
|
50621
|
+
padding: 10px 14px;
|
|
50622
|
+
border-radius: 999px;
|
|
50623
|
+
background:
|
|
50624
|
+
linear-gradient(135deg, rgba(15, 23, 42, 0.9), rgba(17, 24, 39, 0.9)),
|
|
50625
|
+
radial-gradient(circle at top left, rgba(96, 165, 250, 0.25), transparent 55%),
|
|
50626
|
+
radial-gradient(circle at bottom right, rgba(45, 212, 191, 0.22), transparent 60%);
|
|
50627
|
+
box-shadow:
|
|
50628
|
+
0 12px 28px rgba(15, 23, 42, 0.78),
|
|
50629
|
+
0 0 0 1px rgba(148, 163, 184, 0.26);
|
|
50630
|
+
display: flex;
|
|
50631
|
+
align-items: center;
|
|
50632
|
+
gap: 10px;
|
|
50633
|
+
pointer-events: none;
|
|
50634
|
+
transform-origin: center;
|
|
50635
|
+
animation: next-sdk-panel-pop-in 260ms cubic-bezier(0.18, 0.89, 0.32, 1.28);
|
|
50636
|
+
color: #e5e7eb;
|
|
50637
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
|
|
50638
|
+
}
|
|
50639
|
+
|
|
50640
|
+
.next-sdk-tool-overlay__indicator {
|
|
50641
|
+
width: 26px;
|
|
50642
|
+
height: 26px;
|
|
50643
|
+
border-radius: 999px;
|
|
50644
|
+
background: radial-gradient(circle at 30% 10%, #f9fafb, #93c5fd);
|
|
50645
|
+
box-shadow:
|
|
50646
|
+
0 0 0 1px rgba(191, 219, 254, 0.6),
|
|
50647
|
+
0 8px 18px rgba(37, 99, 235, 0.8),
|
|
50648
|
+
0 0 28px rgba(56, 189, 248, 0.9);
|
|
50649
|
+
position: relative;
|
|
50650
|
+
flex-shrink: 0;
|
|
50651
|
+
display: flex;
|
|
50652
|
+
align-items: center;
|
|
50653
|
+
justify-content: center;
|
|
50654
|
+
overflow: hidden;
|
|
50655
|
+
}
|
|
50656
|
+
|
|
50657
|
+
.next-sdk-tool-overlay__indicator-orbit {
|
|
50658
|
+
position: absolute;
|
|
50659
|
+
inset: 2px;
|
|
50660
|
+
border-radius: inherit;
|
|
50661
|
+
border: 1px solid rgba(248, 250, 252, 0.6);
|
|
50662
|
+
box-sizing: border-box;
|
|
50663
|
+
opacity: 0.9;
|
|
50664
|
+
}
|
|
50665
|
+
|
|
50666
|
+
.next-sdk-tool-overlay__indicator-orbit::before {
|
|
50667
|
+
content: '';
|
|
50668
|
+
position: absolute;
|
|
50669
|
+
width: 6px;
|
|
50670
|
+
height: 6px;
|
|
50671
|
+
border-radius: 999px;
|
|
50672
|
+
background: #f9fafb;
|
|
50673
|
+
box-shadow:
|
|
50674
|
+
0 0 12px rgba(248, 250, 252, 0.9),
|
|
50675
|
+
0 0 24px rgba(250, 249, 246, 0.9);
|
|
50676
|
+
top: 0;
|
|
50677
|
+
left: 50%;
|
|
50678
|
+
transform: translate(-50%, -50%);
|
|
50679
|
+
transform-origin: 50% 18px;
|
|
50680
|
+
animation: next-sdk-indicator-orbit 1.4s linear infinite;
|
|
50681
|
+
}
|
|
50682
|
+
|
|
50683
|
+
.next-sdk-tool-overlay__indicator-core {
|
|
50684
|
+
width: 14px;
|
|
50685
|
+
height: 14px;
|
|
50686
|
+
border-radius: inherit;
|
|
50687
|
+
background: radial-gradient(circle at 30% 20%, #f9fafb, #bfdbfe);
|
|
50688
|
+
box-shadow:
|
|
50689
|
+
0 0 12px rgba(248, 250, 252, 0.9),
|
|
50690
|
+
0 0 32px rgba(191, 219, 254, 0.8);
|
|
50691
|
+
opacity: 0.96;
|
|
50692
|
+
}
|
|
50693
|
+
|
|
50694
|
+
.next-sdk-tool-overlay__content {
|
|
50695
|
+
display: flex;
|
|
50696
|
+
flex-direction: column;
|
|
50697
|
+
gap: 1px;
|
|
50698
|
+
min-width: 0;
|
|
50699
|
+
}
|
|
50700
|
+
|
|
50701
|
+
.next-sdk-tool-overlay__title {
|
|
50702
|
+
font-size: 11px;
|
|
50703
|
+
letter-spacing: 0.08em;
|
|
50704
|
+
text-transform: uppercase;
|
|
50705
|
+
color: rgba(156, 163, 175, 0.96);
|
|
50706
|
+
display: flex;
|
|
50707
|
+
align-items: center;
|
|
50708
|
+
gap: 6px;
|
|
50709
|
+
}
|
|
50710
|
+
|
|
50711
|
+
.next-sdk-tool-overlay__title-dot {
|
|
50712
|
+
width: 6px;
|
|
50713
|
+
height: 6px;
|
|
50714
|
+
border-radius: 999px;
|
|
50715
|
+
background: #22c55e;
|
|
50716
|
+
box-shadow:
|
|
50717
|
+
0 0 8px rgba(34, 197, 94, 0.9),
|
|
50718
|
+
0 0 14px rgba(22, 163, 74, 0.9);
|
|
50719
|
+
}
|
|
50720
|
+
|
|
50721
|
+
.next-sdk-tool-overlay__label {
|
|
50722
|
+
font-size: 12px;
|
|
50723
|
+
font-weight: 500;
|
|
50724
|
+
color: #e5e7eb;
|
|
50725
|
+
white-space: nowrap;
|
|
50726
|
+
text-overflow: ellipsis;
|
|
50727
|
+
overflow: hidden;
|
|
50728
|
+
}
|
|
50729
|
+
|
|
50730
|
+
@keyframes next-sdk-overlay-fade-in {
|
|
50731
|
+
from { opacity: 0; }
|
|
50732
|
+
to { opacity: 1; }
|
|
50733
|
+
}
|
|
50734
|
+
|
|
50735
|
+
@keyframes next-sdk-overlay-fade-out {
|
|
50736
|
+
from { opacity: 1; }
|
|
50737
|
+
to { opacity: 0; }
|
|
50738
|
+
}
|
|
50739
|
+
|
|
50740
|
+
@keyframes next-sdk-indicator-orbit {
|
|
50741
|
+
from {
|
|
50742
|
+
transform: translate(-50%, -50%) rotate(0deg) translateY(0);
|
|
50743
|
+
}
|
|
50744
|
+
to {
|
|
50745
|
+
transform: translate(-50%, -50%) rotate(360deg) translateY(0);
|
|
50746
|
+
}
|
|
50747
|
+
}
|
|
50748
|
+
|
|
50749
|
+
@keyframes next-sdk-panel-pop-in {
|
|
50750
|
+
0% {
|
|
50751
|
+
opacity: 0;
|
|
50752
|
+
transform: scale(0.92) translateY(10px);
|
|
50753
|
+
}
|
|
50754
|
+
100% {
|
|
50755
|
+
opacity: 1;
|
|
50756
|
+
transform: scale(1) translateY(0);
|
|
50757
|
+
}
|
|
50758
|
+
}
|
|
50759
|
+
`;
|
|
50760
|
+
document.head.appendChild(style);
|
|
50761
|
+
styleElement = style;
|
|
50762
|
+
}
|
|
50763
|
+
function ensureOverlayElement() {
|
|
50764
|
+
if (!ensureDomReady()) return;
|
|
50765
|
+
if (overlayElement) return;
|
|
50766
|
+
ensureStyleElement();
|
|
50767
|
+
const overlay = document.createElement("div");
|
|
50768
|
+
overlay.className = "next-sdk-tool-overlay";
|
|
50769
|
+
const glowRing = document.createElement("div");
|
|
50770
|
+
glowRing.className = "next-sdk-tool-overlay__glow-ring";
|
|
50771
|
+
const panel = document.createElement("div");
|
|
50772
|
+
panel.className = "next-sdk-tool-overlay__panel";
|
|
50773
|
+
const indicator = document.createElement("div");
|
|
50774
|
+
indicator.className = "next-sdk-tool-overlay__indicator";
|
|
50775
|
+
const indicatorOrbit = document.createElement("div");
|
|
50776
|
+
indicatorOrbit.className = "next-sdk-tool-overlay__indicator-orbit";
|
|
50777
|
+
const indicatorCore = document.createElement("div");
|
|
50778
|
+
indicatorCore.className = "next-sdk-tool-overlay__indicator-core";
|
|
50779
|
+
const content = document.createElement("div");
|
|
50780
|
+
content.className = "next-sdk-tool-overlay__content";
|
|
50781
|
+
const titleRow = document.createElement("div");
|
|
50782
|
+
titleRow.className = "next-sdk-tool-overlay__title";
|
|
50783
|
+
titleRow.textContent = "AI 正在调用页面工具";
|
|
50784
|
+
const titleDot = document.createElement("span");
|
|
50785
|
+
titleDot.className = "next-sdk-tool-overlay__title-dot";
|
|
50786
|
+
const label = document.createElement("div");
|
|
50787
|
+
label.className = "next-sdk-tool-overlay__label";
|
|
50788
|
+
titleRow.prepend(titleDot);
|
|
50789
|
+
content.appendChild(titleRow);
|
|
50790
|
+
content.appendChild(label);
|
|
50791
|
+
indicator.appendChild(indicatorOrbit);
|
|
50792
|
+
indicator.appendChild(indicatorCore);
|
|
50793
|
+
panel.appendChild(indicator);
|
|
50794
|
+
panel.appendChild(content);
|
|
50795
|
+
overlay.appendChild(glowRing);
|
|
50796
|
+
overlay.appendChild(panel);
|
|
50797
|
+
document.body.appendChild(overlay);
|
|
50798
|
+
overlayElement = overlay;
|
|
50799
|
+
labelElement = label;
|
|
50800
|
+
}
|
|
50801
|
+
function updateOverlay(config2) {
|
|
50802
|
+
if (!ensureDomReady()) return;
|
|
50803
|
+
ensureOverlayElement();
|
|
50804
|
+
if (!overlayElement || !labelElement) return;
|
|
50805
|
+
overlayElement.classList.remove("next-sdk-tool-overlay--exit");
|
|
50806
|
+
labelElement.textContent = config2.label;
|
|
50807
|
+
}
|
|
50808
|
+
function removeOverlayWithAnimation() {
|
|
50809
|
+
if (!overlayElement) return;
|
|
50810
|
+
overlayElement.classList.add("next-sdk-tool-overlay--exit");
|
|
50811
|
+
const localOverlay = overlayElement;
|
|
50812
|
+
let handled = false;
|
|
50813
|
+
let timerId;
|
|
50814
|
+
const handle = () => {
|
|
50815
|
+
if (handled) return;
|
|
50816
|
+
handled = true;
|
|
50817
|
+
if (timerId !== void 0) {
|
|
50818
|
+
clearTimeout(timerId);
|
|
50819
|
+
timerId = void 0;
|
|
50820
|
+
}
|
|
50821
|
+
if (localOverlay.parentNode) {
|
|
50822
|
+
localOverlay.parentNode.removeChild(localOverlay);
|
|
50823
|
+
}
|
|
50824
|
+
if (overlayElement === localOverlay) {
|
|
50825
|
+
overlayElement = null;
|
|
50826
|
+
labelElement = null;
|
|
50827
|
+
}
|
|
50828
|
+
localOverlay.removeEventListener("animationend", handle);
|
|
50829
|
+
};
|
|
50830
|
+
localOverlay.addEventListener("animationend", handle);
|
|
50831
|
+
timerId = setTimeout(handle, 500);
|
|
50832
|
+
}
|
|
50833
|
+
function showToolInvokeEffect(config2) {
|
|
50834
|
+
if (!ensureDomReady()) return;
|
|
50835
|
+
activeCount += 1;
|
|
50836
|
+
updateOverlay(config2);
|
|
50837
|
+
}
|
|
50838
|
+
function hideToolInvokeEffect() {
|
|
50839
|
+
if (!ensureDomReady() || activeCount <= 0) return;
|
|
50840
|
+
activeCount -= 1;
|
|
50841
|
+
if (activeCount === 0) {
|
|
50842
|
+
removeOverlayWithAnimation();
|
|
50843
|
+
}
|
|
50844
|
+
}
|
|
50845
|
+
function resolveRuntimeEffectConfig(toolName, toolTitle, value) {
|
|
50846
|
+
if (!value) return void 0;
|
|
50847
|
+
const baseLabel = toolTitle || toolName;
|
|
50848
|
+
if (typeof value === "boolean") {
|
|
50849
|
+
return value ? { label: baseLabel } : void 0;
|
|
50850
|
+
}
|
|
50851
|
+
return {
|
|
50852
|
+
label: value.label || baseLabel
|
|
50853
|
+
};
|
|
50854
|
+
}
|
|
50555
50855
|
const MSG_TOOL_CALL = "next-sdk:tool-call";
|
|
50556
50856
|
const MSG_TOOL_RESPONSE = "next-sdk:tool-response";
|
|
50557
50857
|
const MSG_PAGE_READY = "next-sdk:page-ready";
|
|
@@ -50605,7 +50905,7 @@ ${observationText}
|
|
|
50605
50905
|
function setNavigator(fn) {
|
|
50606
50906
|
_navigator = fn;
|
|
50607
50907
|
}
|
|
50608
|
-
function buildPageHandler(name16, route, timeout = 3e4) {
|
|
50908
|
+
function buildPageHandler(name16, route, timeout = 3e4, effectConfig) {
|
|
50609
50909
|
return (input) => {
|
|
50610
50910
|
const callId = randomUUID();
|
|
50611
50911
|
return new Promise((resolve2, reject) => {
|
|
@@ -50617,6 +50917,9 @@ ${observationText}
|
|
|
50617
50917
|
if (readyHandler) {
|
|
50618
50918
|
window.removeEventListener("message", readyHandler);
|
|
50619
50919
|
}
|
|
50920
|
+
if (effectConfig) {
|
|
50921
|
+
hideToolInvokeEffect();
|
|
50922
|
+
}
|
|
50620
50923
|
};
|
|
50621
50924
|
timer = setTimeout(() => {
|
|
50622
50925
|
cleanup();
|
|
@@ -50640,6 +50943,9 @@ ${observationText}
|
|
|
50640
50943
|
};
|
|
50641
50944
|
const run = async () => {
|
|
50642
50945
|
try {
|
|
50946
|
+
if (effectConfig) {
|
|
50947
|
+
showToolInvokeEffect(effectConfig);
|
|
50948
|
+
}
|
|
50643
50949
|
if (activePages.get(route)) {
|
|
50644
50950
|
sendCallOnce();
|
|
50645
50951
|
return;
|
|
@@ -50676,9 +50982,10 @@ ${observationText}
|
|
|
50676
50982
|
if (typeof handlerOrRoute === "function") {
|
|
50677
50983
|
return rawRegister(name16, config2, handlerOrRoute);
|
|
50678
50984
|
}
|
|
50679
|
-
const { route, timeout } = handlerOrRoute;
|
|
50985
|
+
const { route, timeout, invokeEffect } = handlerOrRoute;
|
|
50680
50986
|
toolRouteMap.set(name16, route);
|
|
50681
|
-
|
|
50987
|
+
const effectConfig = resolveRuntimeEffectConfig(name16, config2?.title, invokeEffect);
|
|
50988
|
+
return rawRegister(name16, config2, buildPageHandler(name16, route, timeout, effectConfig));
|
|
50682
50989
|
};
|
|
50683
50990
|
}
|
|
50684
50991
|
return Reflect.get(target, prop, receiver);
|
|
@@ -50776,33 +51083,95 @@ ${lines.join("\n")}
|
|
|
50776
51083
|
}
|
|
50777
51084
|
function getSkillMdContent(modules, path) {
|
|
50778
51085
|
const normalized = normalizeSkillModuleKeys(modules);
|
|
50779
|
-
|
|
51086
|
+
const exactMatch = normalized[path];
|
|
51087
|
+
if (exactMatch) return exactMatch;
|
|
51088
|
+
const suffix = path.replace(/^\.?\//, "/");
|
|
51089
|
+
const matchingKey = Object.keys(normalized).find((key) => key.endsWith(suffix));
|
|
51090
|
+
return matchingKey ? normalized[matchingKey] : void 0;
|
|
50780
51091
|
}
|
|
50781
51092
|
function getMainSkillPathByName(modules, name16) {
|
|
50782
|
-
|
|
51093
|
+
const normalizedModules = normalizeSkillModuleKeys(modules);
|
|
51094
|
+
const paths = getMainSkillPaths(normalizedModules);
|
|
51095
|
+
const dirMatch = paths.find((p) => p.startsWith(`./${name16}/SKILL.md`));
|
|
51096
|
+
if (dirMatch) return dirMatch;
|
|
51097
|
+
for (const p of paths) {
|
|
51098
|
+
const content = normalizedModules[p];
|
|
51099
|
+
if (content) {
|
|
51100
|
+
const parsed = parseSkillFrontMatter(content);
|
|
51101
|
+
if (parsed && parsed.name === name16) {
|
|
51102
|
+
return p;
|
|
51103
|
+
}
|
|
51104
|
+
}
|
|
51105
|
+
}
|
|
51106
|
+
return void 0;
|
|
50783
51107
|
}
|
|
50784
51108
|
const SKILL_INPUT_SCHEMA = objectType({
|
|
50785
|
-
skillName: stringType().optional().describe(
|
|
50786
|
-
|
|
51109
|
+
skillName: stringType().optional().describe(
|
|
51110
|
+
'进入某个技能的主入口名称。优先匹配技能的目录名(如 ecommerce),或者技能的中文名称(如"客户价保单创建及审核")。'
|
|
51111
|
+
),
|
|
51112
|
+
path: stringType().optional().describe("你想查阅的文档的路径。如 ./calculator/SKILL.md 或从其他文档里看到的相对路径 ./reference/inventory.md。"),
|
|
51113
|
+
currentPath: stringType().optional().describe(
|
|
51114
|
+
"你当前正在阅读的文档路径(如果有)。比如你刚刚读取了 ./ecommerce/SKILL.md,请把这个路径原样传回来,这样系统才能根据你的相对路径准确找到下一份文件。"
|
|
51115
|
+
)
|
|
50787
51116
|
});
|
|
50788
51117
|
function createSkillTools(modules) {
|
|
50789
51118
|
const normalizedModules = normalizeSkillModuleKeys(modules);
|
|
50790
51119
|
const getSkillContent = tool({
|
|
50791
|
-
description: "
|
|
51120
|
+
description: "根据技能名称或文档路径获取该技能的完整文档内容。如果你想根据相对路径查阅文件,请务必同时提供你当前所在的文件路径 currentPath。",
|
|
50792
51121
|
inputSchema: SKILL_INPUT_SCHEMA,
|
|
50793
51122
|
execute: (args) => {
|
|
50794
|
-
const { skillName, path: pathArg } = args;
|
|
51123
|
+
const { skillName, path: pathArg, currentPath: currentPathArg } = args;
|
|
50795
51124
|
let content;
|
|
51125
|
+
let resolvedPath = "";
|
|
50796
51126
|
if (pathArg) {
|
|
50797
|
-
|
|
51127
|
+
let basePathContext = ".";
|
|
51128
|
+
if (currentPathArg) {
|
|
51129
|
+
const lastSlashIndex = currentPathArg.lastIndexOf("/");
|
|
51130
|
+
if (lastSlashIndex >= 0) {
|
|
51131
|
+
basePathContext = currentPathArg.slice(0, lastSlashIndex);
|
|
51132
|
+
}
|
|
51133
|
+
}
|
|
51134
|
+
const dummyBase = `http://localhost/${basePathContext}/`;
|
|
51135
|
+
const url2 = new URL(pathArg, dummyBase);
|
|
51136
|
+
resolvedPath = "." + url2.pathname;
|
|
51137
|
+
content = getSkillMdContent(normalizedModules, resolvedPath);
|
|
51138
|
+
if (content === void 0 && (pathArg.startsWith("./") || pathArg.startsWith("../")) && currentPathArg) {
|
|
51139
|
+
const baseParts = currentPathArg.split("/");
|
|
51140
|
+
if (baseParts.length >= 2) {
|
|
51141
|
+
const skillRoot = baseParts[1];
|
|
51142
|
+
const fallbackDummyBase = `http://localhost/${skillRoot}/`;
|
|
51143
|
+
const fallbackUrl = new URL(pathArg, fallbackDummyBase);
|
|
51144
|
+
const fallbackPath = "." + fallbackUrl.pathname;
|
|
51145
|
+
content = getSkillMdContent(normalizedModules, fallbackPath);
|
|
51146
|
+
if (content) {
|
|
51147
|
+
resolvedPath = fallbackPath;
|
|
51148
|
+
}
|
|
51149
|
+
}
|
|
51150
|
+
}
|
|
51151
|
+
if (content && !normalizedModules[resolvedPath]) {
|
|
51152
|
+
const suffix = resolvedPath.replace(/^\.?\//, "/");
|
|
51153
|
+
const matchingKey = Object.keys(normalizedModules).find((key) => key.endsWith(suffix));
|
|
51154
|
+
if (matchingKey) {
|
|
51155
|
+
resolvedPath = matchingKey;
|
|
51156
|
+
}
|
|
51157
|
+
}
|
|
50798
51158
|
} else if (skillName) {
|
|
50799
51159
|
const mainPath = getMainSkillPathByName(normalizedModules, skillName);
|
|
50800
|
-
|
|
51160
|
+
if (mainPath) {
|
|
51161
|
+
resolvedPath = mainPath;
|
|
51162
|
+
content = getSkillMdContent(normalizedModules, mainPath);
|
|
51163
|
+
}
|
|
50801
51164
|
}
|
|
50802
51165
|
if (content === void 0) {
|
|
50803
|
-
return {
|
|
51166
|
+
return {
|
|
51167
|
+
error: "未找到对应技能文档",
|
|
51168
|
+
skillName,
|
|
51169
|
+
path: pathArg,
|
|
51170
|
+
providedCurrentPath: currentPathArg,
|
|
51171
|
+
attemptedPath: resolvedPath
|
|
51172
|
+
};
|
|
50804
51173
|
}
|
|
50805
|
-
return { content, path:
|
|
51174
|
+
return { content, path: resolvedPath };
|
|
50806
51175
|
}
|
|
50807
51176
|
});
|
|
50808
51177
|
return {
|