@web-ppt/agent-mcp 0.8.0-beta.2 → 0.8.0

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/CHANGELOG.md CHANGED
@@ -2,6 +2,33 @@
2
2
 
3
3
  本文件记录对使用者可见的变化。版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
4
4
 
5
+ ## 0.8.0 - 2026-11-06
6
+
7
+ 0.8.0 稳定版:`0.8.0-beta.3` 的全部内容转正到 `latest`,包括 Agent 命令工具面、本机 MCP server 与 Agent Skill(`@web-ppt/agent-mcp` 首个稳定版)、模板填充 `@web-ppt/edit-core/fill`、编辑器 WebMCP 与 Agent 配对评测工具。相对 0.6.0 的逐项变化见下方 `0.8.0-beta.1` 至 `0.8.0-beta.3` 条目。本版另含:
8
+
9
+ - 新增导入安全上限:`parse()` 在解压前检查 EOCD、中央目录、条目名称、声明大小与压缩比,解压时再核对实际输出;默认上限为 4096 个条目、单条目 128 MiB、总量 512 MiB、压缩比 1000,可通过 `zip` 选项逐项覆盖,`parseInWorker` 使用同一配置。核心解析、Worker、保存原包、OLE 与内嵌工作簿共用这套边界;重复名称、路径穿越、伪造大小和超限输入抛出 `ZipSafetyError`(`reason` 为稳定的 `zip-*` 代码),ZIP64 以 `zip64-unsupported` 明确拒绝。
10
+ - 修复保存产物的 OOXML 结构:图表数据编辑与图表设计把轴标题写到 `numFmt` 之后(schema 规定标题在数字格式之前);非折线 / 散点图系列残留 `c:smooth`;生成式文字的字符与段落属性(`ln`、填充、字体、项目符号尺寸等)按 schema 顺序写入。
11
+ - 修复形状悬停超链接的保存:目标页删除后悬空引用未清理;给仅有悬停链接的形状新增点击链接时,`hlinkClick` 误写到 `hlinkHover` 之后(cNvPr 的 schema 顺序要求其在前)。
12
+
13
+ 破坏性变更核对:无 API 撤除;超出默认 ZIP 上限或结构异常的输入改为抛出 `ZipSafetyError`,需要更大文件时通过 `zip` 选项放宽。
14
+
15
+ 安装:无版本号安装即得 0.8.0,九包必须同版本;`@next` 标签留给 0.9 线。原计划随 0.8.0 交付的新建图表与图表细节渲染(桌面 002 / 003)顺延到 0.9.0。
16
+
17
+ `@web-ppt/collab` 发布入口为 12.20KB gzip;排除 peer 的完整测试薄包为 14,333B gzip,两种口径分别核对。
18
+
19
+ Windows PowerPoint 真机验收继续延后,未记为通过;0.8.0 先行转正,四项自动门禁、OOXML 合法性门禁(ECMA-376 XSD 与 Open XML SDK 双通道)与 LibreOffice 外部打开清单全部通过。
20
+
21
+ ## 0.8.0-beta.3 - 2026-11-04
22
+
23
+ 九包已实际通过 GitHub OIDC 发布到 npm `next`。官方 registry 的匿名下载、实际 SRI、隔离安装、SDK / fill Schema 和 MCP `beta.3` 握手及十工具均通过,Node 20 / 24 均已复验。
24
+
25
+ - MCP 初始化的 `serverInfo.version` 唯一读取自身公开包清单,源码、独立构建和隔离安装均报告实际软件版本。
26
+ - MCP 源码与发布产物回归均验证真实 stdio 握手版本,避免后续发版遗漏手写常量。
27
+
28
+ `@web-ppt/collab` 发布入口为 12.20KB gzip;排除 peer 的完整测试薄包为 14,333B gzip。
29
+
30
+ Windows PowerPoint 真机验收继续延后,未记为通过。
31
+
5
32
  ## 0.8.0-beta.2 - 2026-11-04
6
33
 
7
34
  - 新增仓库 Agent 配对评测工具:复用生产 MCP 比较自动 lint 反馈,保存全部尝试和真实产物;`npm run eval:agent` 可离线重判已提交证据,真实模型调用使用独立显式命令。评测结果不作为发布门禁,不增加 SDK 运行时依赖。
@@ -9,7 +36,7 @@
9
36
  - 模板二进制边界改为审计 npm 实际发布文件清单,覆盖全部发布包;仓库私有评测文稿可保留,SDK 包夹带二进制模板仍会被拒绝。
10
37
  - 官网语言回归隔离后台字体完成回调,保留视图、页码、内容和下载断言;触屏回归使用实际设备能力仿真,并在场景结束恢复原输入状态与原生字体方法。
11
38
 
12
- 九包继续使用同一 beta 版本,SDK 编辑行为与 `0.8.0-beta.1` 保持一致。GitHub 发布链路以 MCP 包的真实 OIDC 新版本发布作为首次激活验收。
39
+ 九包已通过 GitHub OIDC 发布,MCP Trusted Publisher 已完成首次成功发布激活。隔离安装发现此版 MCP 握手仍报告 `beta.1`,修正在 `beta.3`;SDK 编辑行为与 `0.8.0-beta.1` 一致。
13
40
 
14
41
  `@web-ppt/collab` 发布入口为 12.20KB gzip;排除 peer 的完整测试薄包为 14,333B gzip。
15
42
 
package/dist/agent-mcp.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as a, a as c, c as n } from "./server-IR4Cfdfl.js";
1
+ import { A as a, a as c, c as n } from "./server-B4X8aoUM.js";
2
2
  export {
3
3
  a as AgentMcpError,
4
4
  c as AgentMcpSessionManager,
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import { readFile as c } from "node:fs/promises";
3
3
  import { dirname as a, resolve as p } from "node:path";
4
4
  import { pathToFileURL as f } from "node:url";
5
5
  import { StdioServerTransport as w } from "@modelcontextprotocol/sdk/server/stdio.js";
6
- import { c as l, l as s } from "./server-IR4Cfdfl.js";
6
+ import { c as l, l as s } from "./server-B4X8aoUM.js";
7
7
  async function i(r, e, o) {
8
8
  if (e === void 0) return;
9
9
  if (typeof e != "string" || !e) throw new Error(`${o} 模块路径必须是非空字符串`);
@@ -0,0 +1,225 @@
1
+ import { createRequire as v } from "node:module";
2
+ import { Server as b } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { ListToolsRequestSchema as S, CallToolRequestSchema as k } from "@modelcontextprotocol/sdk/types.js";
4
+ import { openAgentSession as $, listAgentTools as q } from "@web-ppt/edit-core/agent";
5
+ import { open as E, rename as A, rm as I, readFile as x } from "node:fs/promises";
6
+ import { disposeOpcPackage as P } from "@web-ppt/edit-core/opc";
7
+ import { serializeEditDoc as _ } from "@web-ppt/edit-core/save";
8
+ import { resolve as M, dirname as R, basename as j } from "node:path";
9
+ class c extends Error {
10
+ constructor(e, t) {
11
+ super(t), this.reason = e, this.name = "AgentMcpError";
12
+ }
13
+ }
14
+ let N = 0;
15
+ function w(s) {
16
+ if (typeof s != "string" || !s.trim())
17
+ throw new c("invalid-path", "文件路径必须是非空字符串");
18
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(s))
19
+ throw new c("invalid-path", `只接受本地文件路径,收到 URL:${s}`);
20
+ return M(s);
21
+ }
22
+ async function g(s, e) {
23
+ const t = `${R(s)}/.${j(s)}.web-ppt-${process.pid}-${++N}.tmp`;
24
+ let r;
25
+ try {
26
+ r = await E(t, "wx"), await r.writeFile(e), await r.sync(), await r.close(), r = void 0, await A(t, s);
27
+ } catch (o) {
28
+ throw r && await r.close().catch(() => {
29
+ }), await I(t, { force: !0 }).catch(() => {
30
+ }), new c("save-failed", `写入 ${s} 失败:${o instanceof Error ? o.message : String(o)}`);
31
+ }
32
+ }
33
+ class O {
34
+ constructor(e = {}) {
35
+ this.options = e, this.sessions = /* @__PURE__ */ new Map(), this.sequence = 0, this.active = !0;
36
+ }
37
+ async open(e) {
38
+ this.assertActive();
39
+ const t = w(e);
40
+ let r;
41
+ try {
42
+ r = await x(t);
43
+ } catch (i) {
44
+ throw new c("open-failed", `读取 ${t} 失败:${i instanceof Error ? i.message : String(i)}`);
45
+ }
46
+ const o = `session-${++this.sequence}`, p = new AbortController();
47
+ let n;
48
+ try {
49
+ n = await $(r, {
50
+ ...this.options,
51
+ idPrefix: `mcp-${o}-`,
52
+ lint: { ...this.options.lint, signal: p.signal }
53
+ });
54
+ } catch (i) {
55
+ throw new c("open-failed", `打开 ${t} 失败:${i instanceof Error ? i.message : String(i)}`);
56
+ }
57
+ if (!this.active)
58
+ throw n.dispose(), new c("session-disposed", "会话管理器已经释放");
59
+ return this.sessions.set(o, { session: n, controller: p, queue: Promise.resolve(), closing: !1 }), { sessionId: o, path: t };
60
+ }
61
+ async call(e, t, r) {
62
+ return this.run(e, (o) => o.call(t, r));
63
+ }
64
+ async save(e, t) {
65
+ const r = w(t);
66
+ return this.run(e, async (o) => {
67
+ const { editor: p, doc: n } = o, i = p.captureSavepoint(), l = n.package && !n.package.disposed ? "patch" : "generated", a = await _(n);
68
+ return a.package !== n.package && P(a.package), await g(r, a.bytes), i(), { ok: !0, value: {
69
+ bytes: Buffer.from(a.bytes).toString("base64"),
70
+ path: r,
71
+ saveMode: l,
72
+ packageMode: a.mode,
73
+ fallbackReason: a.fallbackReason,
74
+ preservedEntries: a.preservedEntries,
75
+ rewrittenEntries: a.rewrittenEntries
76
+ } };
77
+ });
78
+ }
79
+ async render(e, t, r) {
80
+ const o = r === void 0 ? void 0 : w(r);
81
+ return this.run(e, async (p) => {
82
+ const n = await p.call("render", t);
83
+ if (!n.ok || o === void 0) return n;
84
+ const i = n.value.format === "svg" ? new TextEncoder().encode(n.value.data) : Buffer.from(n.value.data, "base64");
85
+ return await g(o, i), { ok: !0, value: { ...n.value, path: o } };
86
+ });
87
+ }
88
+ async close(e) {
89
+ const t = this.entry(e);
90
+ t.closing = !0, t.controller.abort();
91
+ const r = t.queue.then(() => (t.session.dispose(), this.sessions.delete(e), { closed: !0 }));
92
+ return t.queue = r.then(() => {
93
+ }, () => {
94
+ }), r;
95
+ }
96
+ async dispose() {
97
+ if (!this.active) return;
98
+ this.active = !1;
99
+ const e = [...this.sessions.values()];
100
+ for (const t of e)
101
+ t.closing = !0, t.controller.abort();
102
+ await Promise.allSettled(e.map((t) => t.queue));
103
+ for (const t of e) t.session.dispose();
104
+ this.sessions.clear();
105
+ }
106
+ entry(e) {
107
+ this.assertActive();
108
+ const t = this.sessions.get(e);
109
+ if (!t || t.closing) throw new c("target-not-found", `找不到打开的会话:${e}`);
110
+ return t;
111
+ }
112
+ run(e, t) {
113
+ const r = this.entry(e), o = r.queue.then(() => {
114
+ if (!this.active || r.closing) throw new c("session-disposed", `会话已经关闭:${e}`);
115
+ return t(r.session);
116
+ });
117
+ return r.queue = o.then(() => {
118
+ }, () => {
119
+ }), o;
120
+ }
121
+ assertActive() {
122
+ if (!this.active) throw new c("session-disposed", "会话管理器已经释放");
123
+ }
124
+ }
125
+ function y(s, e) {
126
+ let t = s;
127
+ for (; typeof t.$ref == "string"; )
128
+ t = t.$ref.split("/").slice(1).reduce((n, i) => n[i], s);
129
+ const r = { ...t.properties, sessionId: { type: "string" } };
130
+ (e === "save" || e === "render") && (r.path = { type: "string" });
131
+ const o = /* @__PURE__ */ new Set([...t.required ?? [], "sessionId"]);
132
+ return e === "save" && o.add("path"), {
133
+ ...t,
134
+ type: "object",
135
+ properties: r,
136
+ required: [...o],
137
+ ...s.definitions ? { definitions: s.definitions } : {}
138
+ };
139
+ }
140
+ function T() {
141
+ const s = [{
142
+ name: "ppt_open",
143
+ description: "打开本地 PPTX / PPT 并创建编辑会话",
144
+ inputSchema: {
145
+ type: "object",
146
+ properties: { path: { type: "string" } },
147
+ required: ["path"],
148
+ additionalProperties: !1
149
+ }
150
+ }];
151
+ for (const e of q()) {
152
+ const t = e.name === "save" ? "save" : e.name === "render" ? "render" : "call";
153
+ s.push({
154
+ name: `ppt_${e.name}`,
155
+ description: e.description,
156
+ inputSchema: y(e.inputSchema, t)
157
+ });
158
+ }
159
+ return s.push({
160
+ name: "ppt_close",
161
+ description: "关闭会话并释放文档资源",
162
+ inputSchema: y({ type: "object", additionalProperties: !1 }, "close")
163
+ }), s;
164
+ }
165
+ function f(s) {
166
+ const e = s;
167
+ return {
168
+ isError: !0,
169
+ content: [{ type: "text", text: JSON.stringify({
170
+ ok: !1,
171
+ error: {
172
+ reason: typeof e?.reason == "string" ? e.reason : "tool-failed",
173
+ message: typeof e?.message == "string" ? e.message : String(s),
174
+ commandIndex: typeof e?.commandIndex == "number" ? e.commandIndex : null,
175
+ elementId: typeof e?.elementId == "string" ? e.elementId : null,
176
+ slideNumber: typeof e?.slideNumber == "number" ? e.slideNumber : null
177
+ }
178
+ }) }]
179
+ };
180
+ }
181
+ function z(s) {
182
+ if (!s || typeof s != "object" || Array.isArray(s)) throw new c("invalid-input", "工具参数必须是对象");
183
+ return s;
184
+ }
185
+ function m(s) {
186
+ if (typeof s.sessionId != "string" || !s.sessionId) throw new c("invalid-input", "sessionId 必须是非空字符串");
187
+ return s.sessionId;
188
+ }
189
+ function U(s = {}) {
190
+ const e = v(import.meta.url)("@web-ppt/agent-mcp/package.json").version;
191
+ if (typeof e != "string" || !e)
192
+ throw new Error(`@web-ppt/agent-mcp/package.json version 必须为非空字符串,实际:${JSON.stringify(e)}`);
193
+ const t = new O(s), r = new b({ name: "web-ppt-agent", version: e }, { capabilities: { tools: {} } }), o = T();
194
+ return r.setRequestHandler(S, async () => ({ tools: o })), r.setRequestHandler(k, async (p) => {
195
+ try {
196
+ const n = p.params.name, i = z(p.params.arguments ?? {});
197
+ let l;
198
+ if (n === "ppt_open") l = await t.open(i.path);
199
+ else if (n === "ppt_close") l = await t.close(m(i));
200
+ else if (n === "ppt_save") {
201
+ const a = await t.save(m(i), i.path);
202
+ if (!a.ok) return f(a.error);
203
+ const { bytes: h, ...d } = a.value;
204
+ l = d;
205
+ } else if (n === "ppt_render") {
206
+ const { sessionId: a, path: h, ...d } = i, u = await t.render(m(i), d, h);
207
+ if (!u.ok) return f(u.error);
208
+ l = u.value;
209
+ } else if (n.startsWith("ppt_")) {
210
+ const a = n.slice(4), { sessionId: h, ...d } = i, u = await t.call(m(i), a, d);
211
+ if (!u.ok) return f(u.error);
212
+ l = u.value;
213
+ } else throw new c("target-not-found", `未知工具:${n}`);
214
+ return { content: [{ type: "text", text: JSON.stringify({ ok: !0, value: l }) }] };
215
+ } catch (n) {
216
+ return f(n);
217
+ }
218
+ }), { server: r, manager: t };
219
+ }
220
+ export {
221
+ c as A,
222
+ O as a,
223
+ U as c,
224
+ w as l
225
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@web-ppt/agent-mcp",
3
- "version": "0.8.0-beta.2",
3
+ "version": "0.8.0",
4
4
  "description": "Local-only MCP stdio server and Agent Skill for deterministic PPT reading, editing, rendering and saving.",
5
5
  "keywords": [
6
6
  "pptx",
@@ -48,8 +48,8 @@
48
48
  "prepack": "node ../../tooling/sync-package-docs.mjs"
49
49
  },
50
50
  "peerDependencies": {
51
- "@web-ppt/core": "^0.8.0-beta.2",
52
- "@web-ppt/edit-core": "^0.8.0-beta.2"
51
+ "@web-ppt/core": "^0.8.0",
52
+ "@web-ppt/edit-core": "^0.8.0"
53
53
  },
54
54
  "dependencies": {
55
55
  "@cfworker/json-schema": "^4.1.1",
@@ -1,221 +0,0 @@
1
- import { Server as g } from "@modelcontextprotocol/sdk/server/index.js";
2
- import { ListToolsRequestSchema as v, CallToolRequestSchema as b } from "@modelcontextprotocol/sdk/types.js";
3
- import { openAgentSession as S, listAgentTools as $ } from "@web-ppt/edit-core/agent";
4
- import { open as k, rename as q, rm as A, readFile as E } from "node:fs/promises";
5
- import { disposeOpcPackage as I } from "@web-ppt/edit-core/opc";
6
- import { serializeEditDoc as x } from "@web-ppt/edit-core/save";
7
- import { resolve as P, dirname as _, basename as M } from "node:path";
8
- class l extends Error {
9
- constructor(e, t) {
10
- super(t), this.reason = e, this.name = "AgentMcpError";
11
- }
12
- }
13
- let R = 0;
14
- function h(s) {
15
- if (typeof s != "string" || !s.trim())
16
- throw new l("invalid-path", "文件路径必须是非空字符串");
17
- if (/^[a-z][a-z0-9+.-]*:\/\//i.test(s))
18
- throw new l("invalid-path", `只接受本地文件路径,收到 URL:${s}`);
19
- return P(s);
20
- }
21
- async function w(s, e) {
22
- const t = `${_(s)}/.${M(s)}.web-ppt-${process.pid}-${++R}.tmp`;
23
- let n;
24
- try {
25
- n = await k(t, "wx"), await n.writeFile(e), await n.sync(), await n.close(), n = void 0, await q(t, s);
26
- } catch (o) {
27
- throw n && await n.close().catch(() => {
28
- }), await A(t, { force: !0 }).catch(() => {
29
- }), new l("save-failed", `写入 ${s} 失败:${o instanceof Error ? o.message : String(o)}`);
30
- }
31
- }
32
- class T {
33
- constructor(e = {}) {
34
- this.options = e, this.sessions = /* @__PURE__ */ new Map(), this.sequence = 0, this.active = !0;
35
- }
36
- async open(e) {
37
- this.assertActive();
38
- const t = h(e);
39
- let n;
40
- try {
41
- n = await E(t);
42
- } catch (i) {
43
- throw new l("open-failed", `读取 ${t} 失败:${i instanceof Error ? i.message : String(i)}`);
44
- }
45
- const o = `session-${++this.sequence}`, a = new AbortController();
46
- let r;
47
- try {
48
- r = await S(n, {
49
- ...this.options,
50
- idPrefix: `mcp-${o}-`,
51
- lint: { ...this.options.lint, signal: a.signal }
52
- });
53
- } catch (i) {
54
- throw new l("open-failed", `打开 ${t} 失败:${i instanceof Error ? i.message : String(i)}`);
55
- }
56
- if (!this.active)
57
- throw r.dispose(), new l("session-disposed", "会话管理器已经释放");
58
- return this.sessions.set(o, { session: r, controller: a, queue: Promise.resolve(), closing: !1 }), { sessionId: o, path: t };
59
- }
60
- async call(e, t, n) {
61
- return this.run(e, (o) => o.call(t, n));
62
- }
63
- async save(e, t) {
64
- const n = h(t);
65
- return this.run(e, async (o) => {
66
- const { editor: a, doc: r } = o, i = a.captureSavepoint(), p = r.package && !r.package.disposed ? "patch" : "generated", c = await x(r);
67
- return c.package !== r.package && I(c.package), await w(n, c.bytes), i(), { ok: !0, value: {
68
- bytes: Buffer.from(c.bytes).toString("base64"),
69
- path: n,
70
- saveMode: p,
71
- packageMode: c.mode,
72
- fallbackReason: c.fallbackReason,
73
- preservedEntries: c.preservedEntries,
74
- rewrittenEntries: c.rewrittenEntries
75
- } };
76
- });
77
- }
78
- async render(e, t, n) {
79
- const o = n === void 0 ? void 0 : h(n);
80
- return this.run(e, async (a) => {
81
- const r = await a.call("render", t);
82
- if (!r.ok || o === void 0) return r;
83
- const i = r.value.format === "svg" ? new TextEncoder().encode(r.value.data) : Buffer.from(r.value.data, "base64");
84
- return await w(o, i), { ok: !0, value: { ...r.value, path: o } };
85
- });
86
- }
87
- async close(e) {
88
- const t = this.entry(e);
89
- t.closing = !0, t.controller.abort();
90
- const n = t.queue.then(() => (t.session.dispose(), this.sessions.delete(e), { closed: !0 }));
91
- return t.queue = n.then(() => {
92
- }, () => {
93
- }), n;
94
- }
95
- async dispose() {
96
- if (!this.active) return;
97
- this.active = !1;
98
- const e = [...this.sessions.values()];
99
- for (const t of e)
100
- t.closing = !0, t.controller.abort();
101
- await Promise.allSettled(e.map((t) => t.queue));
102
- for (const t of e) t.session.dispose();
103
- this.sessions.clear();
104
- }
105
- entry(e) {
106
- this.assertActive();
107
- const t = this.sessions.get(e);
108
- if (!t || t.closing) throw new l("target-not-found", `找不到打开的会话:${e}`);
109
- return t;
110
- }
111
- run(e, t) {
112
- const n = this.entry(e), o = n.queue.then(() => {
113
- if (!this.active || n.closing) throw new l("session-disposed", `会话已经关闭:${e}`);
114
- return t(n.session);
115
- });
116
- return n.queue = o.then(() => {
117
- }, () => {
118
- }), o;
119
- }
120
- assertActive() {
121
- if (!this.active) throw new l("session-disposed", "会话管理器已经释放");
122
- }
123
- }
124
- function y(s, e) {
125
- let t = s;
126
- for (; typeof t.$ref == "string"; )
127
- t = t.$ref.split("/").slice(1).reduce((r, i) => r[i], s);
128
- const n = { ...t.properties, sessionId: { type: "string" } };
129
- (e === "save" || e === "render") && (n.path = { type: "string" });
130
- const o = /* @__PURE__ */ new Set([...t.required ?? [], "sessionId"]);
131
- return e === "save" && o.add("path"), {
132
- ...t,
133
- type: "object",
134
- properties: n,
135
- required: [...o],
136
- ...s.definitions ? { definitions: s.definitions } : {}
137
- };
138
- }
139
- function N() {
140
- const s = [{
141
- name: "ppt_open",
142
- description: "打开本地 PPTX / PPT 并创建编辑会话",
143
- inputSchema: {
144
- type: "object",
145
- properties: { path: { type: "string" } },
146
- required: ["path"],
147
- additionalProperties: !1
148
- }
149
- }];
150
- for (const e of $()) {
151
- const t = e.name === "save" ? "save" : e.name === "render" ? "render" : "call";
152
- s.push({
153
- name: `ppt_${e.name}`,
154
- description: e.description,
155
- inputSchema: y(e.inputSchema, t)
156
- });
157
- }
158
- return s.push({
159
- name: "ppt_close",
160
- description: "关闭会话并释放文档资源",
161
- inputSchema: y({ type: "object", additionalProperties: !1 }, "close")
162
- }), s;
163
- }
164
- function f(s) {
165
- const e = s;
166
- return {
167
- isError: !0,
168
- content: [{ type: "text", text: JSON.stringify({
169
- ok: !1,
170
- error: {
171
- reason: typeof e?.reason == "string" ? e.reason : "tool-failed",
172
- message: typeof e?.message == "string" ? e.message : String(s),
173
- commandIndex: typeof e?.commandIndex == "number" ? e.commandIndex : null,
174
- elementId: typeof e?.elementId == "string" ? e.elementId : null,
175
- slideNumber: typeof e?.slideNumber == "number" ? e.slideNumber : null
176
- }
177
- }) }]
178
- };
179
- }
180
- function O(s) {
181
- if (!s || typeof s != "object" || Array.isArray(s)) throw new l("invalid-input", "工具参数必须是对象");
182
- return s;
183
- }
184
- function m(s) {
185
- if (typeof s.sessionId != "string" || !s.sessionId) throw new l("invalid-input", "sessionId 必须是非空字符串");
186
- return s.sessionId;
187
- }
188
- function J(s = {}) {
189
- const e = new T(s), t = new g({ name: "web-ppt-agent", version: "0.8.0-beta.1" }, { capabilities: { tools: {} } }), n = N();
190
- return t.setRequestHandler(v, async () => ({ tools: n })), t.setRequestHandler(b, async (o) => {
191
- try {
192
- const a = o.params.name, r = O(o.params.arguments ?? {});
193
- let i;
194
- if (a === "ppt_open") i = await e.open(r.path);
195
- else if (a === "ppt_close") i = await e.close(m(r));
196
- else if (a === "ppt_save") {
197
- const p = await e.save(m(r), r.path);
198
- if (!p.ok) return f(p.error);
199
- const { bytes: c, ...d } = p.value;
200
- i = d;
201
- } else if (a === "ppt_render") {
202
- const { sessionId: p, path: c, ...d } = r, u = await e.render(m(r), d, c);
203
- if (!u.ok) return f(u.error);
204
- i = u.value;
205
- } else if (a.startsWith("ppt_")) {
206
- const p = a.slice(4), { sessionId: c, ...d } = r, u = await e.call(m(r), p, d);
207
- if (!u.ok) return f(u.error);
208
- i = u.value;
209
- } else throw new l("target-not-found", `未知工具:${a}`);
210
- return { content: [{ type: "text", text: JSON.stringify({ ok: !0, value: i }) }] };
211
- } catch (a) {
212
- return f(a);
213
- }
214
- }), { server: t, manager: e };
215
- }
216
- export {
217
- l as A,
218
- T as a,
219
- J as c,
220
- h as l
221
- };