tencent-edu-assistant-connector 0.3.0 → 0.3.1

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/internal.js CHANGED
@@ -62,7 +62,10 @@ const noArgs = z.object({});
62
62
  /** 工具白名单:名称 → 参数校验与调用 */
63
63
  const TOOL_BINDERS = new Map([
64
64
  ['getPageContext', bindTool(noArgs, (backend) => backend.getPageContext())],
65
- ['getPendingTasks', bindTool(noArgs, (backend) => backend.getPendingTasks())],
65
+ [
66
+ 'getPendingTasks',
67
+ bindTool(z.object({ requestId: z.string().min(1).max(128).optional() }), (backend, args) => backend.getPendingTasks(args.requestId)),
68
+ ],
66
69
  ['getActiveExpert', bindTool(noArgs, (backend) => backend.getActiveExpert())],
67
70
  [
68
71
  'getTopicDetail',
@@ -298,7 +301,7 @@ export function createForwardingToolBackend(options) {
298
301
  const deliverTimeoutMs = options.deliverTimeoutMs ?? DEFAULT_DELIVER_TIMEOUT_MS;
299
302
  return {
300
303
  getPageContext: async () => (await call('getPageContext', {}, timeoutMs)),
301
- getPendingTasks: async () => (await call('getPendingTasks', {}, timeoutMs)),
304
+ getPendingTasks: async (requestId) => (await call('getPendingTasks', requestId === undefined ? {} : { requestId }, timeoutMs)),
302
305
  getActiveExpert: async () => (await call('getActiveExpert', {}, timeoutMs)),
303
306
  getTopicDetail: (topicId) => call('getTopicDetail', topicId === undefined ? {} : { topicId }, timeoutMs),
304
307
  listTopicMenu: () => call('listTopicMenu', {}, timeoutMs),
package/dist/stdio.js CHANGED
@@ -130,7 +130,7 @@ function createUnavailableBackend(message) {
130
130
  function createDynamicBackend(current) {
131
131
  return {
132
132
  getPageContext: () => current().getPageContext(),
133
- getPendingTasks: () => current().getPendingTasks(),
133
+ getPendingTasks: (requestId) => current().getPendingTasks(requestId),
134
134
  getActiveExpert: () => current().getActiveExpert(),
135
135
  getTopicDetail: (topicId) => current().getTopicDetail(topicId),
136
136
  listTopicMenu: () => current().listTopicMenu(),
package/dist/tools.js CHANGED
@@ -323,10 +323,16 @@ export function createLocalToolBackend(deps = {}) {
323
323
  const resolved = resolveDeps(deps);
324
324
  return {
325
325
  getPageContext: async () => resolved.contextStore.getPublic(),
326
- getPendingTasks: async () => {
326
+ getPendingTasks: async (requestId) => {
327
327
  const ctx = resolved.contextStore.getPublic();
328
328
  const store = resolved.generationStore;
329
329
  const tasks = [...(ctx ? store.listPending(ctx.topicId) : []), ...store.listPending(NEW_TOPIC_SCOPE)];
330
+ if (requestId !== undefined && !tasks.some((task) => task.requestId === requestId)) {
331
+ // 上下文 TTL(3 分钟)远短于任务 TTL(30 分钟):页面心跳中断后任务仍有效,按 requestId 补回
332
+ const task = store.getByRequestId(requestId);
333
+ if (task && isUnfinishedStatus(task.status))
334
+ tasks.push(task);
335
+ }
330
336
  return tasks.map(toPublicTask);
331
337
  },
332
338
  getActiveExpert: async () => {
@@ -417,7 +423,28 @@ async function runTool(tool, run) {
417
423
  function renderPageContext(ctx, tasks) {
418
424
  if (!ctx && tasks.length === 0)
419
425
  return noContextToolText('get_page_context');
420
- return buildHookText({ context: ctx, pendingTasks: tasks, maxChars: Number.MAX_SAFE_INTEGER });
426
+ const text = buildHookText({ context: ctx, pendingTasks: tasks, maxChars: Number.MAX_SAFE_INTEGER });
427
+ const note = detachedTaskNote(ctx, tasks);
428
+ return note ? `${note}\n\n${text}` : text;
429
+ }
430
+ /**
431
+ * 「任务所属专题不是当前已连接专题」的提示:按 requestId 补回的任务读不到其专题资料,
432
+ * 防止模型凭空生成或误用其他专题的资料。无此类任务时返回空串。
433
+ * @param ctx 当前上下文;`null` 表示页面未连接
434
+ * @param tasks 待完成任务
435
+ */
436
+ function detachedTaskNote(ctx, tasks) {
437
+ const detached = tasks.filter((task) => task.topicId !== NEW_TOPIC_SCOPE && task.topicId !== ctx?.topicId);
438
+ if (detached.length === 0)
439
+ return '';
440
+ const ids = detached.map((task) => oneLine(task.requestId)).join('、');
441
+ const reason = ctx ? '不是当前打开的专题' : '当前未连接(页面上下文已过期)';
442
+ return [
443
+ `[注意] 任务 ${ids} 所属的专题页面${reason},读不到该专题的资料清单。`,
444
+ `若本会话此前已生成该任务的产物,直接按「交付要求」调用 ${DELIVER_TOOL_NAME} 补交;`,
445
+ '否则请用户回到该专题详情页(1~2 秒内自动重连)后再调用 get_page_context 获取资料,',
446
+ '不要在没有资料的情况下凭空生成,也不要使用其他专题的资料。',
447
+ ].join('');
421
448
  }
422
449
  /**
423
450
  * 渲染专家文本。
@@ -612,7 +639,7 @@ function registerContextTools(server, backend) {
612
639
  // 只影响该 requestId,未传时不改变任何状态(正常对话零影响)。
613
640
  if (requestId !== undefined)
614
641
  await backend.markPromptSent(requestId, extra?.sessionId).catch(() => false);
615
- const [ctx, tasks] = await Promise.all([backend.getPageContext(), backend.getPendingTasks()]);
642
+ const [ctx, tasks] = await Promise.all([backend.getPageContext(), backend.getPendingTasks(requestId)]);
616
643
  return renderPageContext(ctx, tasks);
617
644
  }));
618
645
  server.registerTool('get_active_expert', {
@@ -642,7 +669,7 @@ function registerQueryTools(server, backend) {
642
669
  }, ({ topicId }) => runTool('get_topic_detail', async () => `专题详情:\n${formatJson(await backend.getTopicDetail(topicId))}`));
643
670
  server.registerTool('list_topic_menu', {
644
671
  title: '查询专题功能入口',
645
- description: '查询专题详情页的功能入口列表(资料精读 / 视频学习 / AI 生课等),用于回答「这个专题能做什么」。' +
672
+ description: '查询当前专题详情页的功能入口列表(以本工具返回为准,不要自行补充入口名称),用于回答「这个专题能做什么」。' +
646
673
  `使用页面上报的登录态,${PAGE_REQUIRED_NOTE}`,
647
674
  }, () => runTool('list_topic_menu', async () => {
648
675
  const list = await backend.listTopicMenu();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tencent-edu-assistant-connector",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "description": "腾讯教育学习助手 · 专题 MCP Server:为 WorkBuddy 会话提供专题页面上下文、业务查询与产物落库能力",
6
6
  "bin": {
@@ -6,7 +6,7 @@
6
6
  "name": "tencent-edu-assistant",
7
7
  "source": "./plugins/tencent-edu-assistant",
8
8
  "description": "把学习空间专题页的专题 / 资料 / 阅读位置 / 专家上下文提供给 WorkBuddy 会话,并支持生成产物回填专题",
9
- "version": "0.3.0"
9
+ "version": "0.3.1"
10
10
  }
11
11
  ]
12
12
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tencent-edu-assistant",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "把学习空间专题页的专题 / 资料 / 阅读位置 / 专家上下文提供给 WorkBuddy 会话,并支持生成产物回填专题",
5
5
  "author": {
6
6
  "name": "tencent"