@opentiny/next-sdk 0.2.7 → 0.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/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 +476 -23
- package/dist/index.es.js +6622 -6273
- package/dist/index.js +2120 -1771
- package/dist/index.umd.dev.js +476 -23
- package/dist/index.umd.js +217 -49
- package/dist/{page-tool-bridge.d.ts → page-tools/bridge.d.ts} +34 -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} +170 -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";
|
|
@@ -50559,6 +50859,7 @@ ${observationText}
|
|
|
50559
50859
|
const MSG_REMOTER_READY = "next-sdk:remoter-ready";
|
|
50560
50860
|
const MSG_ROUTE_STATE_INITIAL = "next-sdk:route-state-initial";
|
|
50561
50861
|
const activePages = /* @__PURE__ */ new Map();
|
|
50862
|
+
const normalizeRoute = (value) => value.replace(/\/+$/, "") || "/";
|
|
50562
50863
|
const broadcastTargets = /* @__PURE__ */ new Set();
|
|
50563
50864
|
function initBroadcastTargets() {
|
|
50564
50865
|
if (typeof window !== "undefined") {
|
|
@@ -50605,7 +50906,89 @@ ${observationText}
|
|
|
50605
50906
|
function setNavigator(fn) {
|
|
50606
50907
|
_navigator = fn;
|
|
50607
50908
|
}
|
|
50608
|
-
function
|
|
50909
|
+
function waitForPageReady(path, timeoutMs = 1500) {
|
|
50910
|
+
if (typeof window === "undefined") {
|
|
50911
|
+
return Promise.resolve();
|
|
50912
|
+
}
|
|
50913
|
+
const target = normalizeRoute(path);
|
|
50914
|
+
return new Promise((resolve2) => {
|
|
50915
|
+
let done = false;
|
|
50916
|
+
const cleanup = () => {
|
|
50917
|
+
if (done) return;
|
|
50918
|
+
done = true;
|
|
50919
|
+
window.removeEventListener("message", handleMessage);
|
|
50920
|
+
resolve2();
|
|
50921
|
+
};
|
|
50922
|
+
const handleMessage = (event) => {
|
|
50923
|
+
if (event.source !== window || event.data?.type !== MSG_PAGE_READY) return;
|
|
50924
|
+
const route = normalizeRoute(String(event.data.route ?? ""));
|
|
50925
|
+
if (route === target) {
|
|
50926
|
+
cleanup();
|
|
50927
|
+
}
|
|
50928
|
+
};
|
|
50929
|
+
window.addEventListener("message", handleMessage);
|
|
50930
|
+
setTimeout(cleanup, timeoutMs);
|
|
50931
|
+
});
|
|
50932
|
+
}
|
|
50933
|
+
function registerNavigateTool(server, options) {
|
|
50934
|
+
const name16 = options?.name ?? "navigate_to_page";
|
|
50935
|
+
const title2 = options?.title ?? "页面跳转";
|
|
50936
|
+
const description2 = options?.description ?? '当需要的工具在当前页面不可用时,使用此工具跳转到特定页面。例如:要查询订单时跳转到 "/orders",要创建价保时跳转到 "/price-protection"。';
|
|
50937
|
+
const timeoutMs = options?.timeoutMs ?? 1500;
|
|
50938
|
+
return server.registerTool(
|
|
50939
|
+
name16,
|
|
50940
|
+
{
|
|
50941
|
+
title: title2,
|
|
50942
|
+
description: description2,
|
|
50943
|
+
inputSchema: {
|
|
50944
|
+
path: stringType().describe('目标页面的路由地址,例如 "/orders"、"/inventory"、"/price-protection" 等。')
|
|
50945
|
+
}
|
|
50946
|
+
},
|
|
50947
|
+
async ({ path }) => {
|
|
50948
|
+
if (typeof window === "undefined") {
|
|
50949
|
+
return {
|
|
50950
|
+
content: [{ type: "text", text: "当前环境不支持页面跳转(window 不存在)。" }]
|
|
50951
|
+
};
|
|
50952
|
+
}
|
|
50953
|
+
if (!_navigator) {
|
|
50954
|
+
return {
|
|
50955
|
+
content: [
|
|
50956
|
+
{
|
|
50957
|
+
type: "text",
|
|
50958
|
+
text: "页面跳转失败:尚未在应用入口调用 setNavigator 注册导航函数,无法执行路由跳转。"
|
|
50959
|
+
}
|
|
50960
|
+
]
|
|
50961
|
+
};
|
|
50962
|
+
}
|
|
50963
|
+
try {
|
|
50964
|
+
const target = normalizeRoute(path);
|
|
50965
|
+
const current = normalizeRoute(window.location.pathname);
|
|
50966
|
+
const isAlreadyOnTarget = current === target || current.endsWith(target) && (current.length === target.length || current[current.lastIndexOf(target) - 1] === "/");
|
|
50967
|
+
if (isAlreadyOnTarget) {
|
|
50968
|
+
return {
|
|
50969
|
+
content: [{ type: "text", text: `当前已在页面:${path}。请继续你的下一步操作。` }]
|
|
50970
|
+
};
|
|
50971
|
+
}
|
|
50972
|
+
const readyPromise = waitForPageReady(path, timeoutMs);
|
|
50973
|
+
await _navigator(path);
|
|
50974
|
+
await readyPromise;
|
|
50975
|
+
return {
|
|
50976
|
+
content: [{ type: "text", text: `已成功跳转至页面:${path}。请继续你的下一步操作。` }]
|
|
50977
|
+
};
|
|
50978
|
+
} catch (err) {
|
|
50979
|
+
return {
|
|
50980
|
+
content: [
|
|
50981
|
+
{
|
|
50982
|
+
type: "text",
|
|
50983
|
+
text: `页面跳转失败:${err instanceof Error ? err.message : String(err)}。`
|
|
50984
|
+
}
|
|
50985
|
+
]
|
|
50986
|
+
};
|
|
50987
|
+
}
|
|
50988
|
+
}
|
|
50989
|
+
);
|
|
50990
|
+
}
|
|
50991
|
+
function buildPageHandler(name16, route, timeout = 3e4, effectConfig) {
|
|
50609
50992
|
return (input) => {
|
|
50610
50993
|
const callId = randomUUID();
|
|
50611
50994
|
return new Promise((resolve2, reject) => {
|
|
@@ -50617,6 +51000,9 @@ ${observationText}
|
|
|
50617
51000
|
if (readyHandler) {
|
|
50618
51001
|
window.removeEventListener("message", readyHandler);
|
|
50619
51002
|
}
|
|
51003
|
+
if (effectConfig) {
|
|
51004
|
+
hideToolInvokeEffect();
|
|
51005
|
+
}
|
|
50620
51006
|
};
|
|
50621
51007
|
timer = setTimeout(() => {
|
|
50622
51008
|
cleanup();
|
|
@@ -50640,6 +51026,9 @@ ${observationText}
|
|
|
50640
51026
|
};
|
|
50641
51027
|
const run = async () => {
|
|
50642
51028
|
try {
|
|
51029
|
+
if (effectConfig) {
|
|
51030
|
+
showToolInvokeEffect(effectConfig);
|
|
51031
|
+
}
|
|
50643
51032
|
if (activePages.get(route)) {
|
|
50644
51033
|
sendCallOnce();
|
|
50645
51034
|
return;
|
|
@@ -50676,9 +51065,10 @@ ${observationText}
|
|
|
50676
51065
|
if (typeof handlerOrRoute === "function") {
|
|
50677
51066
|
return rawRegister(name16, config2, handlerOrRoute);
|
|
50678
51067
|
}
|
|
50679
|
-
const { route, timeout } = handlerOrRoute;
|
|
51068
|
+
const { route, timeout, invokeEffect } = handlerOrRoute;
|
|
50680
51069
|
toolRouteMap.set(name16, route);
|
|
50681
|
-
|
|
51070
|
+
const effectConfig = resolveRuntimeEffectConfig(name16, config2?.title, invokeEffect);
|
|
51071
|
+
return rawRegister(name16, config2, buildPageHandler(name16, route, timeout, effectConfig));
|
|
50682
51072
|
};
|
|
50683
51073
|
}
|
|
50684
51074
|
return Reflect.get(target, prop, receiver);
|
|
@@ -50687,10 +51077,10 @@ ${observationText}
|
|
|
50687
51077
|
}
|
|
50688
51078
|
function registerPageTool(options) {
|
|
50689
51079
|
const { route: routeOption, handlers } = options;
|
|
50690
|
-
const
|
|
50691
|
-
const route =
|
|
51080
|
+
const normalizeRoute2 = (value) => value.replace(/\/+$/, "") || "/";
|
|
51081
|
+
const route = normalizeRoute2(routeOption ?? window.location.pathname);
|
|
50692
51082
|
const handleMessage = async (event) => {
|
|
50693
|
-
if (event.source !== window || event.data?.type !== MSG_TOOL_CALL ||
|
|
51083
|
+
if (event.source !== window || event.data?.type !== MSG_TOOL_CALL || normalizeRoute2(String(event.data?.route ?? "")) !== route || !(event.data.toolName in handlers)) {
|
|
50694
51084
|
return;
|
|
50695
51085
|
}
|
|
50696
51086
|
const { callId, toolName, input } = event.data;
|
|
@@ -50776,33 +51166,95 @@ ${lines.join("\n")}
|
|
|
50776
51166
|
}
|
|
50777
51167
|
function getSkillMdContent(modules, path) {
|
|
50778
51168
|
const normalized = normalizeSkillModuleKeys(modules);
|
|
50779
|
-
|
|
51169
|
+
const exactMatch = normalized[path];
|
|
51170
|
+
if (exactMatch) return exactMatch;
|
|
51171
|
+
const suffix = path.replace(/^\.?\//, "/");
|
|
51172
|
+
const matchingKey = Object.keys(normalized).find((key) => key.endsWith(suffix));
|
|
51173
|
+
return matchingKey ? normalized[matchingKey] : void 0;
|
|
50780
51174
|
}
|
|
50781
51175
|
function getMainSkillPathByName(modules, name16) {
|
|
50782
|
-
|
|
51176
|
+
const normalizedModules = normalizeSkillModuleKeys(modules);
|
|
51177
|
+
const paths = getMainSkillPaths(normalizedModules);
|
|
51178
|
+
const dirMatch = paths.find((p) => p.startsWith(`./${name16}/SKILL.md`));
|
|
51179
|
+
if (dirMatch) return dirMatch;
|
|
51180
|
+
for (const p of paths) {
|
|
51181
|
+
const content = normalizedModules[p];
|
|
51182
|
+
if (content) {
|
|
51183
|
+
const parsed = parseSkillFrontMatter(content);
|
|
51184
|
+
if (parsed && parsed.name === name16) {
|
|
51185
|
+
return p;
|
|
51186
|
+
}
|
|
51187
|
+
}
|
|
51188
|
+
}
|
|
51189
|
+
return void 0;
|
|
50783
51190
|
}
|
|
50784
51191
|
const SKILL_INPUT_SCHEMA = objectType({
|
|
50785
|
-
skillName: stringType().optional().describe(
|
|
50786
|
-
|
|
51192
|
+
skillName: stringType().optional().describe(
|
|
51193
|
+
'进入某个技能的主入口名称。优先匹配技能的目录名(如 ecommerce),或者技能的中文名称(如"客户价保单创建及审核")。'
|
|
51194
|
+
),
|
|
51195
|
+
path: stringType().optional().describe("你想查阅的文档的路径。如 ./calculator/SKILL.md 或从其他文档里看到的相对路径 ./reference/inventory.md。"),
|
|
51196
|
+
currentPath: stringType().optional().describe(
|
|
51197
|
+
"你当前正在阅读的文档路径(如果有)。比如你刚刚读取了 ./ecommerce/SKILL.md,请把这个路径原样传回来,这样系统才能根据你的相对路径准确找到下一份文件。"
|
|
51198
|
+
)
|
|
50787
51199
|
});
|
|
50788
51200
|
function createSkillTools(modules) {
|
|
50789
51201
|
const normalizedModules = normalizeSkillModuleKeys(modules);
|
|
50790
51202
|
const getSkillContent = tool({
|
|
50791
|
-
description: "
|
|
51203
|
+
description: "根据技能名称或文档路径获取该技能的完整文档内容。如果你想根据相对路径查阅文件,请务必同时提供你当前所在的文件路径 currentPath。",
|
|
50792
51204
|
inputSchema: SKILL_INPUT_SCHEMA,
|
|
50793
51205
|
execute: (args) => {
|
|
50794
|
-
const { skillName, path: pathArg } = args;
|
|
51206
|
+
const { skillName, path: pathArg, currentPath: currentPathArg } = args;
|
|
50795
51207
|
let content;
|
|
51208
|
+
let resolvedPath = "";
|
|
50796
51209
|
if (pathArg) {
|
|
50797
|
-
|
|
51210
|
+
let basePathContext = ".";
|
|
51211
|
+
if (currentPathArg) {
|
|
51212
|
+
const lastSlashIndex = currentPathArg.lastIndexOf("/");
|
|
51213
|
+
if (lastSlashIndex >= 0) {
|
|
51214
|
+
basePathContext = currentPathArg.slice(0, lastSlashIndex);
|
|
51215
|
+
}
|
|
51216
|
+
}
|
|
51217
|
+
const dummyBase = `http://localhost/${basePathContext}/`;
|
|
51218
|
+
const url2 = new URL(pathArg, dummyBase);
|
|
51219
|
+
resolvedPath = "." + url2.pathname;
|
|
51220
|
+
content = getSkillMdContent(normalizedModules, resolvedPath);
|
|
51221
|
+
if (content === void 0 && (pathArg.startsWith("./") || pathArg.startsWith("../")) && currentPathArg) {
|
|
51222
|
+
const baseParts = currentPathArg.split("/");
|
|
51223
|
+
if (baseParts.length >= 2) {
|
|
51224
|
+
const skillRoot = baseParts[1];
|
|
51225
|
+
const fallbackDummyBase = `http://localhost/${skillRoot}/`;
|
|
51226
|
+
const fallbackUrl = new URL(pathArg, fallbackDummyBase);
|
|
51227
|
+
const fallbackPath = "." + fallbackUrl.pathname;
|
|
51228
|
+
content = getSkillMdContent(normalizedModules, fallbackPath);
|
|
51229
|
+
if (content) {
|
|
51230
|
+
resolvedPath = fallbackPath;
|
|
51231
|
+
}
|
|
51232
|
+
}
|
|
51233
|
+
}
|
|
51234
|
+
if (content && !normalizedModules[resolvedPath]) {
|
|
51235
|
+
const suffix = resolvedPath.replace(/^\.?\//, "/");
|
|
51236
|
+
const matchingKey = Object.keys(normalizedModules).find((key) => key.endsWith(suffix));
|
|
51237
|
+
if (matchingKey) {
|
|
51238
|
+
resolvedPath = matchingKey;
|
|
51239
|
+
}
|
|
51240
|
+
}
|
|
50798
51241
|
} else if (skillName) {
|
|
50799
51242
|
const mainPath = getMainSkillPathByName(normalizedModules, skillName);
|
|
50800
|
-
|
|
51243
|
+
if (mainPath) {
|
|
51244
|
+
resolvedPath = mainPath;
|
|
51245
|
+
content = getSkillMdContent(normalizedModules, mainPath);
|
|
51246
|
+
}
|
|
50801
51247
|
}
|
|
50802
51248
|
if (content === void 0) {
|
|
50803
|
-
return {
|
|
51249
|
+
return {
|
|
51250
|
+
error: "未找到对应技能文档",
|
|
51251
|
+
skillName,
|
|
51252
|
+
path: pathArg,
|
|
51253
|
+
providedCurrentPath: currentPathArg,
|
|
51254
|
+
attemptedPath: resolvedPath
|
|
51255
|
+
};
|
|
50804
51256
|
}
|
|
50805
|
-
return { content, path:
|
|
51257
|
+
return { content, path: resolvedPath };
|
|
50806
51258
|
}
|
|
50807
51259
|
});
|
|
50808
51260
|
return {
|
|
@@ -50849,6 +51301,7 @@ ${lines.join("\n")}
|
|
|
50849
51301
|
exports2.isSSEClientTransport = isSSEClientTransport;
|
|
50850
51302
|
exports2.isStreamableHTTPClientTransport = isStreamableHTTPClientTransport;
|
|
50851
51303
|
exports2.parseSkillFrontMatter = parseSkillFrontMatter;
|
|
51304
|
+
exports2.registerNavigateTool = registerNavigateTool;
|
|
50852
51305
|
exports2.registerPageTool = registerPageTool;
|
|
50853
51306
|
exports2.setNavigator = setNavigator;
|
|
50854
51307
|
exports2.withPageTools = withPageTools;
|