@ynhcj/xiaoyi-channel 0.0.175-beta → 0.0.177-beta
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,51 @@ 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 must pass validateSessionId regex /^[a-z0-9][a-z0-9._-]{0,127}$/i
|
|
202
|
+
// route.sessionKey like "agent:main:direct:xxx" contains colons which are invalid.
|
|
203
|
+
// Use parsed.sessionId (raw UUID from A2A) which is always safe.
|
|
204
|
+
sessionId: parsed.sessionId,
|
|
205
|
+
updatedAt: Date.now(),
|
|
206
|
+
providerOverride: "xiaoyiprovider",
|
|
207
|
+
modelOverride: modelName,
|
|
208
|
+
modelOverrideSource: "user",
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
log.log(`[BOT] Created session entry with model override: xiaoyiprovider/${modelName}`);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
log.log(`[BOT] Patched session store model override: xiaoyiprovider/${modelName}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
catch (patchErr) {
|
|
219
|
+
log.error(`[BOT] Failed to patch session model override:`, patchErr);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
176
222
|
// 🔑 发送初始状态更新
|
|
177
223
|
log.log(`[BOT] Sending initial status update`);
|
|
178
224
|
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
|
|
@@ -570,12 +596,6 @@ export const xiaoyiProvider = {
|
|
|
570
596
|
const deviceSection = `\n\n## Current User Device Context\nThe current user is using the following device: ${displayDevice}\nYou need to be aware of the user's current device and provide guidance accordingly. If the response involves device-related tools or actions, you must tailor the reply based on the user's current device, using device-specific references such as "saved to the Notes/Calendar on your {deviceType}.\n"`;
|
|
571
597
|
context.systemPrompt = (context.systemPrompt ?? "") + deviceSection;
|
|
572
598
|
}
|
|
573
|
-
// Append current LLM model to systemPrompt
|
|
574
|
-
const currentModelName = getCurrentSessionContext()?.modelName;
|
|
575
|
-
if (currentModelName && currentModelName.trim() !== "" && currentModelName.toLowerCase() !== "none") {
|
|
576
|
-
const modelSection = `\n\n## Current LLM MODEL\n${currentModelName}`;
|
|
577
|
-
context.systemPrompt = (context.systemPrompt ?? "") + modelSection;
|
|
578
|
-
}
|
|
579
599
|
// ── Trim user message metadata ──────────────────────
|
|
580
600
|
if (context.messages) {
|
|
581
601
|
for (const msg of context.messages) {
|
|
@@ -17,10 +17,6 @@ import { createGetCollectionToolSchemaTool } from "./get-collection-tool-schema.
|
|
|
17
17
|
// import { createGetEmailToolSchemaTool } from "./get-email-tool-schema.js";
|
|
18
18
|
import { createLoginTokenTool } from "./login-token-tool.js";
|
|
19
19
|
import { createAgentAsSkillTool } from "./agent-as-skill-tool.js";
|
|
20
|
-
import { createDiscoverCrossDevicesTool } from "./discover-cross-devices-tool.js";
|
|
21
|
-
import { createSendCrossDeviceTaskTool } from "./send-cross-device-task-tool.js";
|
|
22
|
-
import { createDisplayA2UICardTool } from "./display-a2ui-card-tool.js";
|
|
23
|
-
import { createCheckPluginPrivilegeTool } from "./check-plugin-privilege-tool.js";
|
|
24
20
|
import { logger } from "../utils/logger.js";
|
|
25
21
|
/**
|
|
26
22
|
* Create all XY channel tools for the given session context.
|
|
@@ -36,9 +32,9 @@ export function createAllTools(ctx) {
|
|
|
36
32
|
logger.log(`[CREATE-ALL-TOOLS] creating tools`);
|
|
37
33
|
return [
|
|
38
34
|
createLocationTool(ctx),
|
|
39
|
-
createDiscoverCrossDevicesTool(ctx),
|
|
40
|
-
createSendCrossDeviceTaskTool(ctx),
|
|
41
|
-
createDisplayA2UICardTool(ctx),
|
|
35
|
+
// createDiscoverCrossDevicesTool(ctx),
|
|
36
|
+
// createSendCrossDeviceTaskTool(ctx),
|
|
37
|
+
// createDisplayA2UICardTool(ctx),
|
|
42
38
|
createCallDeviceTool(ctx),
|
|
43
39
|
createGetNoteToolSchemaTool(ctx),
|
|
44
40
|
createGetCalendarToolSchemaTool(ctx),
|
|
@@ -57,6 +53,6 @@ export function createAllTools(ctx) {
|
|
|
57
53
|
createSaveSelfEvolutionSkillTool(ctx),
|
|
58
54
|
createLoginTokenTool(ctx),
|
|
59
55
|
createAgentAsSkillTool(ctx),
|
|
60
|
-
createCheckPluginPrivilegeTool(ctx),
|
|
56
|
+
// createCheckPluginPrivilegeTool(ctx),
|
|
61
57
|
];
|
|
62
58
|
}
|
|
@@ -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: {
|