@ynhcj/xiaoyi-channel 0.0.157-next → 0.0.158-next
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/src/bot.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { updateSessionStoreEntry, updateSessionStore, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
1
2
|
import { getXYRuntime } from "./runtime.js";
|
|
2
3
|
import { createXYReplyDispatcher } from "./reply-dispatcher.js";
|
|
3
4
|
import { parseA2AMessage, extractTextFromParts, extractFileParts, extractPushId, extractDeviceType, extractModelName, extractTriggerData, extractRunCrossTaskContext } from "./parser.js";
|
|
@@ -173,6 +174,48 @@ export async function handleXYMessage(params) {
|
|
|
173
174
|
modelName,
|
|
174
175
|
runCrossTaskContext: runCrossTaskContext ?? undefined,
|
|
175
176
|
});
|
|
177
|
+
// 🔑 Sync A2A modelName to OpenClaw session store so that session_status
|
|
178
|
+
// reports the correct model. Without this, session_status returns the
|
|
179
|
+
// configured default model instead of the A2A-specified one.
|
|
180
|
+
if (modelName && modelName.trim() !== "" && modelName.toLowerCase() !== "none") {
|
|
181
|
+
try {
|
|
182
|
+
const storePath = resolveStorePath();
|
|
183
|
+
const result = await updateSessionStoreEntry({
|
|
184
|
+
storePath,
|
|
185
|
+
sessionKey: route.sessionKey,
|
|
186
|
+
update: async () => ({
|
|
187
|
+
providerOverride: "xiaoyiprovider",
|
|
188
|
+
modelOverride: modelName,
|
|
189
|
+
modelOverrideSource: "user",
|
|
190
|
+
model: "",
|
|
191
|
+
modelProvider: "",
|
|
192
|
+
}),
|
|
193
|
+
});
|
|
194
|
+
if (!result) {
|
|
195
|
+
// Session entry doesn't exist yet (first message, xy_channel
|
|
196
|
+
// bypasses the standard turn kernel). Create a minimal entry
|
|
197
|
+
// with the override via updateSessionStore.
|
|
198
|
+
await updateSessionStore(storePath, (store) => {
|
|
199
|
+
if (!store[route.sessionKey]) {
|
|
200
|
+
store[route.sessionKey] = {
|
|
201
|
+
sessionId: route.sessionKey,
|
|
202
|
+
updatedAt: Date.now(),
|
|
203
|
+
providerOverride: "xiaoyiprovider",
|
|
204
|
+
modelOverride: modelName,
|
|
205
|
+
modelOverrideSource: "user",
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
log.log(`[BOT] Created session entry with model override: xiaoyiprovider/${modelName}`);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
log.log(`[BOT] Patched session store model override: xiaoyiprovider/${modelName}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
catch (patchErr) {
|
|
216
|
+
log.error(`[BOT] Failed to patch session model override:`, patchErr);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
176
219
|
// 🔑 发送初始状态更新
|
|
177
220
|
log.log(`[BOT] Sending initial status update`);
|
|
178
221
|
void sendStatusUpdate({
|
package/dist/src/formatter.js
CHANGED
|
@@ -217,12 +217,11 @@ export async function sendCommand(params) {
|
|
|
217
217
|
if (commands.length === 0) {
|
|
218
218
|
throw new Error("sendCommand requires command or commands.");
|
|
219
219
|
}
|
|
220
|
-
// ── Cron mode:
|
|
221
|
-
//
|
|
222
|
-
//
|
|
220
|
+
// ── Cron mode: disabled ────────────────────────────────────────
|
|
221
|
+
// sendCommandViaPush is disabled in this version. Cron-triggered
|
|
222
|
+
// tool calls that try to send commands will be rejected.
|
|
223
223
|
if (sessionId.startsWith("cron-") || isCronToolCall(toolCallId)) {
|
|
224
|
-
|
|
225
|
-
return sendCommandViaPush({ config, command: commands[0] });
|
|
224
|
+
throw new Error("sendCommandViaPush is disabled in this version");
|
|
226
225
|
}
|
|
227
226
|
// ── Normal mode: WebSocket ─────────────────────────────────────
|
|
228
227
|
// Dynamic lookup: use latest taskId/messageId from task-manager (handles steer/interrupt),
|
package/dist/src/provider.js
CHANGED
|
@@ -417,6 +417,32 @@ export const xiaoyiProvider = {
|
|
|
417
417
|
docsPath: "/providers/models",
|
|
418
418
|
auth: [],
|
|
419
419
|
isCacheTtlEligible: () => true,
|
|
420
|
+
/**
|
|
421
|
+
* Dynamic model resolution for A2A-specified model names.
|
|
422
|
+
* A2A messages carry a dynamic modelName that isn't in any static catalog.
|
|
423
|
+
* This hook lets OpenClaw's resolveModelAsync accept any model ID under
|
|
424
|
+
* xiaoyiprovider as long as the provider has a configured baseUrl.
|
|
425
|
+
*/
|
|
426
|
+
resolveDynamicModel: (ctx) => {
|
|
427
|
+
const baseUrl = ctx.providerConfig?.baseUrl;
|
|
428
|
+
if (!baseUrl || typeof baseUrl !== "string")
|
|
429
|
+
return null;
|
|
430
|
+
return {
|
|
431
|
+
id: ctx.modelId,
|
|
432
|
+
name: ctx.modelId,
|
|
433
|
+
api: ctx.providerConfig?.api ?? "openai-completions",
|
|
434
|
+
provider: "xiaoyiprovider",
|
|
435
|
+
baseUrl,
|
|
436
|
+
reasoning: false,
|
|
437
|
+
input: ["text"],
|
|
438
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
439
|
+
contextWindow: 128_000,
|
|
440
|
+
maxTokens: 8192,
|
|
441
|
+
...(ctx.providerConfig?.headers && typeof ctx.providerConfig.headers === "object"
|
|
442
|
+
? { headers: ctx.providerConfig.headers }
|
|
443
|
+
: {}),
|
|
444
|
+
};
|
|
445
|
+
},
|
|
420
446
|
/**
|
|
421
447
|
* Store uid-based fallback prefix for lazy timestamp generation in wrapStreamFn.
|
|
422
448
|
* Session-level headers (traceId / sessionId / interactionId) are resolved
|
|
@@ -452,7 +452,6 @@ export function createXYReplyDispatcher(params) {
|
|
|
452
452
|
if (isNewRound) {
|
|
453
453
|
// 将上一轮回复追加到历史
|
|
454
454
|
accumulatedReplyHistory += (accumulatedReplyHistory ? "\n\n" : "") + lastReplyText;
|
|
455
|
-
scopedLog().log(`[onPartialReply] new round detected, lastReplyText: ${lastReplyText.substring(0, 100)}, text: ${text.substring(0, 100)}`);
|
|
456
455
|
}
|
|
457
456
|
// 更新当前轮最后一次text
|
|
458
457
|
lastReplyText = text;
|
|
@@ -12,7 +12,7 @@ export function createSendHtmlCardTool(ctx) {
|
|
|
12
12
|
return {
|
|
13
13
|
name: "send_html_card",
|
|
14
14
|
label: "Send HTML Card",
|
|
15
|
-
description:
|
|
15
|
+
description: `工具能力描述:支持以H5卡片的形式展示HTML页面内容,用户可以直接在卡片中查看。
|
|
16
16
|
|
|
17
17
|
工具参数说明:
|
|
18
18
|
a. htmlUrl 和 htmlLocal 至少填写一个
|
|
@@ -22,8 +22,7 @@ c. htmlLocal 是本地HTML文件路径,会先上传获取预览链接再以卡
|
|
|
22
22
|
注意事项:
|
|
23
23
|
a. 操作超时时间为2分钟(120秒),请勿重复调用此工具,如果超时或失败,最多重试一次
|
|
24
24
|
b. 最后要把最终的html的公网地址作为工具执行结果返回回去,要以markdown超链接的形式返回给用户,必须严格保留完整的url,包含url的鉴权鉴权信息,返回给用户的url必须是完整的
|
|
25
|
-
c.
|
|
26
|
-
d. 如果使用这个工具把html文件回传,则生成的html要尽可能适配用户的设备,如果用户使用的是手机,则尽可能生成竖屏的html的预览效果`,
|
|
25
|
+
c. 仅当用户或者skill中显示说明使用send_html_card工具时才调用此工具`,
|
|
27
26
|
parameters: {
|
|
28
27
|
type: "object",
|
|
29
28
|
properties: {
|
|
@@ -90,8 +89,7 @@ d. 如果使用这个工具把html文件回传,则生成的html要尽可能适
|
|
|
90
89
|
type: "text",
|
|
91
90
|
text: JSON.stringify({
|
|
92
91
|
success: true,
|
|
93
|
-
url
|
|
94
|
-
message: "HTML卡片发送成功",
|
|
92
|
+
message: `HTML卡片发送成功,html的在线链接如下,生成markdown超链接时与此url需保持完整一致 ${url}`,
|
|
95
93
|
}),
|
|
96
94
|
},
|
|
97
95
|
],
|