@cola1900/dsh-ppt 0.1.3 → 0.2.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/README.md +4 -4
- package/UPSTREAM.md +1 -1
- package/cordis.patch.yml +1 -0
- package/lib/client.js +32 -84
- package/lib/index.js +41 -6
- package/lib/preset.js +4 -0
- package/lib/types/index.d.ts +3 -1
- package/package.json +4 -2
- package/presets/ppt/agent.cordis.yml +4 -0
- package/presets/ppt/preset.yml +4 -0
- package/skills/dsh-ppt/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
从 [dataelement/dsh-desktop](https://github.com/dataelement/dsh-desktop) 提取的独立 **DSH / DeepSeek Harness 插件**。一个包包含 PPT 按钮、模板选择、PPTD 编写与校验、预览和可编辑 PPTX 导出,无需 Electron 或原 Desktop 仓库。
|
|
4
4
|
|
|
5
5
|
- 16 套模板、192 个版式,保留英文/中文 PPTD 示例和本地预览图。
|
|
6
|
-
-
|
|
6
|
+
- 提供原生 DSH **PPT 预设**;只有选择该预设时才注入 PPT 创作指引。
|
|
7
7
|
- 保留原有文件授权、路径限制、写入哈希检查、版本记录和导出校验。
|
|
8
8
|
- 提供 `dsh-pptd` 命令行和 `@cola1900/dsh-ppt/pptd` JavaScript API。
|
|
9
9
|
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
dsh plugin --profile web add @cola1900/dsh-ppt
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
把 `web` 替换为实际 profile,然后重启该 profile
|
|
20
|
+
把 `web` 替换为实际 profile,然后重启该 profile。新会话顶部的原生预设选择器会出现 **PPT**;选择后,输入框下方显示模板面板,在首次发送前选择模板,再描述需求。首次发送后预设和模板固定,新会话可以重新选择。插件首次启动会把内置 preset 写入 `$DSH_HOME/.agent-presets/ppt`,无需手动复制或配置。
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
界面只使用官方 `conversation.input.dock` 插槽,只设置插件自身样式,不修改原 DSH。模板名称继续在卡片内显示省略号,输入框底部不再显示 `PPT · 模板名` 控件。
|
|
23
23
|
|
|
24
24
|
如果目标 Desktop 已内置 `dsh-ppt-composer`,先在目标 profile 的插件配置中停用原 PPT bundle,再加载本包。不要同时启用两套 PPT bundle,否则会重复注册工具、路由和输入框按钮。本包已经合并 composer,无需再安装 `dsh-ppt-composer`。
|
|
25
25
|
|
|
@@ -40,7 +40,7 @@ dsh-pptd render /path/to/deck -o /path/to/output.pptx --json
|
|
|
40
40
|
|
|
41
41
|
## 开发
|
|
42
42
|
|
|
43
|
-
`lib/` 是上游维护的 JavaScript 运行时代码;`src/client.js`
|
|
43
|
+
`lib/` 是上游维护的 JavaScript 运行时代码;`src/client.js` 是输入框客户端的构建输入。`presets/ppt/` 是随插件安装的原生 Agent Preset 定义,首次启动会同步到 DSH 的用户 preset 根目录。完整原始 TypeScript 源码不在上游提取基线中,本项目没有把声明文件冒充实现源码。
|
|
44
44
|
|
|
45
45
|
`skills/dsh-ppt/references/` 保存模板元数据、设计说明、双语源文件和预览。修改元数据或预览后执行 `npm run build`,生成模板目录、预览白名单和客户端预览映射。构建使用已随包保存的预览,不依赖网络或原桌面工程。修改版式后可用 `dsh-pptd screenshot` 重新生成图片,再更新对应的 JPG 预览。
|
|
46
46
|
|
package/UPSTREAM.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
- 模板:`packages/ppt-runtime/templates/`
|
|
9
9
|
- 模板许可证与来源资料:`packages/ppt-runtime/upstream/`
|
|
10
10
|
|
|
11
|
-
独立化改动:合并核心和 composer 为单个 `dsh-ppt` 包;客户端模块标识统一为 `dsh-ppt
|
|
11
|
+
独立化改动:合并核心和 composer 为单个 `dsh-ppt` 包;客户端模块标识统一为 `dsh-ppt`;改用 DSH 原生 Agent Preset,随包提供 `presets/ppt/` 并在首次启动时同步到用户 preset 根目录;模板面板只在 PPT 预设的空白会话中通过官方 `conversation.input.dock` 插槽显示,首次发送后固定预设和模板;移除输入框底部 `PPT · 模板名` 控件;移除常驻的选中缩略图;移除指向缺失文件的 `client-standard` 导出,并使用匹配实际客户端的类型声明;将构建改为读取包内模板、生成目录和预览白名单;移除未使用的 TypeScript、Zod 运行依赖;增加独立安装、打包说明及运行验证。
|
|
12
12
|
|
|
13
13
|
输入框布局只通过插件自身 CSS 和标准会话插槽实现,不修改原 DSH 源码或宿主元素样式。
|
|
14
14
|
|
package/cordis.patch.yml
CHANGED
package/lib/client.js
CHANGED
|
@@ -30,21 +30,9 @@ window.__ModuleLoader__.load({
|
|
|
30
30
|
tag.dataset.plugin = "dsh-ppt";
|
|
31
31
|
tag.dataset.pluginCss = tagId;
|
|
32
32
|
tag.textContent = css + `
|
|
33
|
-
.dsh-ppt-control{display:inline-flex;align-items:center;flex:none;min-width:0}
|
|
34
|
-
.dsh-ppt-trigger{box-sizing:border-box;display:inline-flex;align-items:center;gap:6px;max-width:220px;min-height:30px;padding:5px 9px;border:1px solid transparent;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary,#626875);font:inherit;font-size:12px;line-height:18px;cursor:pointer}
|
|
35
|
-
.dsh-ppt-trigger:hover,.dsh-ppt-trigger[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover,#f3f4f6)}
|
|
36
|
-
.dsh-ppt-trigger[data-selected=true]{color:var(--dsw-alias-label-primary,#20232a);background:var(--dsw-alias-interactive-bg-hover,#f3f4f6)}
|
|
37
|
-
.dsh-ppt-trigger-mode{flex:none;white-space:nowrap}
|
|
38
|
-
.dsh-ppt-trigger-label{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
|
|
39
|
-
.dsh-ppt-trigger .desktop-ppt-icon{width:16px;height:16px;flex:none}
|
|
40
|
-
.dsh-ppt-chevron{font-size:10px;flex:none;opacity:.7}
|
|
41
33
|
.dsh-ppt-panel{order:1;align-self:center;display:flex;flex-direction:column;flex-shrink:0;margin:0;padding:0;box-sizing:border-box;width:calc(100% - 2 * var(--dsh-composer-side-clearance,16px));max-height:400px;overflow:hidden;border:1px solid var(--dsw-alias-border-l2-darkmode-thin,#e4e6eb);border-radius:14px;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary,#20232a);box-shadow:0 12px 40px #0000001a,0 2px 8px #00000008;font:13px/1.5 var(--font-sans,system-ui,sans-serif)}
|
|
42
34
|
.dsh-ppt-panel-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 16px 8px;flex:none}
|
|
43
35
|
.dsh-ppt-panel-title{font-size:14px;font-weight:600;margin:0}
|
|
44
|
-
.dsh-ppt-panel-actions{display:flex;align-items:center;gap:8px}
|
|
45
|
-
.dsh-ppt-exit,.dsh-ppt-close{border:0;background:transparent;color:var(--dsw-alias-label-secondary,#626875);font:inherit;cursor:pointer;border-radius:6px;padding:4px 8px}
|
|
46
|
-
.dsh-ppt-close{font-size:20px;line-height:20px;padding:2px 7px}
|
|
47
|
-
.dsh-ppt-exit:hover,.dsh-ppt-close:hover{background:var(--dsw-alias-interactive-bg-hover,#f3f4f6)}
|
|
48
36
|
.dsh-ppt-panel ._2S_x-q_categoryTabs{padding:0 12px 10px;flex:none;border-bottom:1px solid var(--dsw-alias-border-l2-darkmode-thin,#eceef1)}
|
|
49
37
|
.dsh-ppt-panel ._2S_x-q_categoryTabs button{font-size:12px;padding:4px 9px}
|
|
50
38
|
.dsh-ppt-panel ._2S_x-q_categoryTabs button[data-selected=true]{color:var(--dsw-alias-label-primary,#20232a);background:var(--dsw-alias-interactive-bg-hover,#f3f4f6)}
|
|
@@ -55,10 +43,10 @@ window.__ModuleLoader__.load({
|
|
|
55
43
|
.dsh-ppt-panel ._2S_x-q_templateName{font-size:12px;text-align:left;padding:6px 2px 0;width:100%;box-sizing:border-box}
|
|
56
44
|
.dsh-ppt-panel ._2S_x-q_previewViewport{border-radius:8px}
|
|
57
45
|
.dsh-ppt-selected{position:absolute;top:8px;right:8px;z-index:3;display:grid;place-items:center;width:20px;height:20px;border-radius:50%;background:var(--dsw-alias-label-primary,#20232a);color:var(--dsw-alias-bg-base,#fff);font-size:12px;box-shadow:0 1px 4px #0002;pointer-events:none}
|
|
58
|
-
.dsh-ppt-
|
|
46
|
+
.dsh-ppt-panel button:focus-visible{outline:2px solid var(--dsw-alias-label-primary,#20232a);outline-offset:2px}
|
|
59
47
|
.dsh-ppt-panel button:disabled{cursor:wait;opacity:.55}
|
|
60
48
|
.dsh-ppt-panel-notice{margin:0 16px 8px;color:var(--dsw-alias-label-secondary,#626875);font-size:12px}
|
|
61
|
-
@media(max-width:600px){.dsh-ppt-panel ._2S_x-q_templateGrid{grid-template-columns:repeat(2,minmax(0,1fr))}
|
|
49
|
+
@media(max-width:600px){.dsh-ppt-panel ._2S_x-q_templateGrid{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
|
62
50
|
`;
|
|
63
51
|
document.head.appendChild(tag);
|
|
64
52
|
}
|
|
@@ -418,57 +406,29 @@ window.__ModuleLoader__.load({
|
|
|
418
406
|
]
|
|
419
407
|
});
|
|
420
408
|
}
|
|
421
|
-
/**
|
|
422
|
-
function OfficePptChooser({ client, mode, sessionId, t
|
|
409
|
+
/** Template picker shown only for the native PPT agent preset. */
|
|
410
|
+
function OfficePptChooser({ client, mode, sessionId, t }) {
|
|
423
411
|
const state = useMode(mode, sessionId);
|
|
424
|
-
const open = state.pickerOpen;
|
|
425
|
-
const setOpen = value => mode.setPickerOpen(sessionId, value);
|
|
426
412
|
const [category, setCategory] = react.useState("all");
|
|
427
|
-
const panel = react.useRef(null);
|
|
428
|
-
const panelId = `dsh-ppt-picker-${encodeURIComponent(sessionId)}`;
|
|
429
|
-
const triggerId = `${panelId}-trigger`;
|
|
430
|
-
const active = state.activeMode === "ppt";
|
|
431
|
-
const selected = state.templates.find(template => template.id === state.selectedId);
|
|
432
|
-
const label = active && selected ? `${t("mode.label")} · ${selected.name}` : t("mode.label");
|
|
433
|
-
const close = () => { setOpen(false); document.getElementById(triggerId)?.focus({ preventScroll: true }); };
|
|
434
413
|
|
|
435
414
|
react.useEffect(() => {
|
|
436
|
-
if (
|
|
415
|
+
if (mode.snapshot(sessionId).loading || state.templates.length > 0 || state.error !== "") return;
|
|
437
416
|
mode.setLoading(sessionId, true);
|
|
438
417
|
loadTemplateState(client, t("templates.loadTimeout")).then(next => {
|
|
439
418
|
mode.setTemplates(sessionId, next.templates);
|
|
440
419
|
const template = next.templates.find(item => item.id === next.selectedTemplateId);
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
else mode.deselect(sessionId, activeMode);
|
|
420
|
+
if (template) mode.select(sessionId, template, "ppt");
|
|
421
|
+
else mode.deselect(sessionId, "ppt");
|
|
444
422
|
mode.setNotice(sessionId, next.templateMigration?.reason === "template-retired");
|
|
445
423
|
}).catch(reason => mode.setError(sessionId, reason instanceof Error ? reason.message : String(reason)));
|
|
446
|
-
}, [client, mode, sessionId,
|
|
447
|
-
|
|
448
|
-
react.useLayoutEffect(() => {
|
|
449
|
-
if (!open || placement !== "panel") return;
|
|
450
|
-
panel.current.querySelector('[data-office-ppt-template-viewport] button[aria-pressed="true"], [data-ppt-category]')?.focus({ preventScroll: true });
|
|
451
|
-
}, [open, placement]);
|
|
424
|
+
}, [client, mode, sessionId, state.loading, state.templates.length, state.error, t]);
|
|
452
425
|
|
|
453
426
|
const choose = async template => {
|
|
454
|
-
if (state.loading) return;
|
|
455
|
-
if (active && template.id === state.selectedId) { close(); return; }
|
|
427
|
+
if (state.loading || template.id === state.selectedId) return;
|
|
456
428
|
mode.setLoading(sessionId, true);
|
|
457
429
|
try {
|
|
458
430
|
await client.call("template/select", { templateId: template.id, mode: "ppt" });
|
|
459
431
|
mode.select(sessionId, template, "ppt");
|
|
460
|
-
close();
|
|
461
|
-
} catch (reason) {
|
|
462
|
-
mode.setError(sessionId, reason instanceof Error ? reason.message : String(reason));
|
|
463
|
-
}
|
|
464
|
-
};
|
|
465
|
-
const exitPpt = async () => {
|
|
466
|
-
mode.setLoading(sessionId, true);
|
|
467
|
-
try {
|
|
468
|
-
await client.call("presentation/mode", { mode: null });
|
|
469
|
-
mode.setMode(sessionId, null);
|
|
470
|
-
mode.setLoading(sessionId, false);
|
|
471
|
-
close();
|
|
472
432
|
} catch (reason) {
|
|
473
433
|
mode.setError(sessionId, reason instanceof Error ? reason.message : String(reason));
|
|
474
434
|
}
|
|
@@ -477,28 +437,13 @@ window.__ModuleLoader__.load({
|
|
|
477
437
|
const categories = ["all", ...new Set(templates.map(templateCategory))];
|
|
478
438
|
const visible = templates.filter(template => category === "all" || templateCategory(template) === category);
|
|
479
439
|
const h = react.createElement;
|
|
480
|
-
if (placement === "trigger") return h("span", { className: "dsh-ppt-control" },
|
|
481
|
-
h("button", {
|
|
482
|
-
id: triggerId, type: "button", className: "dsh-ppt-trigger", title: label, "aria-label": label,
|
|
483
|
-
"data-desktop-ppt": "", "data-selected": active || undefined,
|
|
484
|
-
"aria-expanded": open, "aria-pressed": active,
|
|
485
|
-
"aria-controls": open ? panelId : undefined,
|
|
486
|
-
onClick: () => setOpen(!open)
|
|
487
|
-
}, h(DesktopPptIcon), h("span", { className: "dsh-ppt-trigger-mode" }, t("mode.label") + (active && selected ? " ·" : "")),
|
|
488
|
-
active && selected && h("span", { className: "dsh-ppt-trigger-label" }, selected.name),
|
|
489
|
-
h("span", { className: "dsh-ppt-chevron", "aria-hidden": true }, "⌄")));
|
|
490
|
-
if (!open) return null;
|
|
491
440
|
return h("section", {
|
|
492
|
-
|
|
493
|
-
className: "dsh-ppt-panel", "data-office-ppt-template-panel": "", "data-placement": "bottom"
|
|
494
|
-
onKeyDown: event => { if (event.key === "Escape") { event.preventDefault(); event.stopPropagation(); close(); } }
|
|
441
|
+
"aria-label": t("templates.title"),
|
|
442
|
+
className: "dsh-ppt-panel", "data-office-ppt-template-panel": "", "data-placement": "bottom"
|
|
495
443
|
},
|
|
496
444
|
h("div", { className: "dsh-ppt-panel-header" },
|
|
497
|
-
h("h2", { className: "dsh-ppt-panel-title" }, t("templates.title")),
|
|
498
|
-
|
|
499
|
-
active && h("button", { type: "button", className: "dsh-ppt-exit", disabled: state.loading, onClick: exitPpt }, t("mode.exit")),
|
|
500
|
-
h("button", { type: "button", className: "dsh-ppt-close", "aria-label": t("templates.close"), onClick: close }, "×"))),
|
|
501
|
-
state.notice && active && h("p", { className: "dsh-ppt-panel-notice", role: "status" }, t("templates.migrated")),
|
|
445
|
+
h("h2", { className: "dsh-ppt-panel-title" }, t("templates.title"))),
|
|
446
|
+
state.notice && h("p", { className: "dsh-ppt-panel-notice", role: "status" }, t("templates.migrated")),
|
|
502
447
|
h("div", { className: OfficePptHero_module_css_default.categoryTabs, role: "group", "aria-label": t("templates.categories") },
|
|
503
448
|
categories.map(item => h("button", {
|
|
504
449
|
key: item, type: "button", "data-ppt-category": item, "aria-pressed": category === item,
|
|
@@ -509,13 +454,19 @@ window.__ModuleLoader__.load({
|
|
|
509
454
|
state.templates.length === 0 && h("button", { type: "button", className: OfficePptHero_module_css_default.retryButton, onClick: () => mode.setError(sessionId, "") }, t("templates.retry"))),
|
|
510
455
|
state.loading && templates.length === 0 ? h("div", { className: OfficePptHero_module_css_default.panelState }, t("status.loading")) :
|
|
511
456
|
h("div", { className: OfficePptHero_module_css_default.templateGrid }, visible.map(template => h(TemplateCard, {
|
|
512
|
-
key: template.id, template, selected:
|
|
457
|
+
key: template.id, template, selected: template.id === state.selectedId, choose, disabled: state.loading
|
|
513
458
|
})))));
|
|
514
459
|
}
|
|
515
460
|
function OfficePptComposer(props) {
|
|
516
|
-
const blank = props.useSession(
|
|
517
|
-
|
|
518
|
-
|
|
461
|
+
const blank = props.useSession(current => current.blank);
|
|
462
|
+
const agentPreset = props.useSessions(current => {
|
|
463
|
+
const summary = current.byId[props.sessionId];
|
|
464
|
+
return summary?.projectionValues?.agentPreset ?? summary?.agentPreset;
|
|
465
|
+
});
|
|
466
|
+
if (!blank || agentPreset !== "ppt") return null;
|
|
467
|
+
return react_jsx_runtime.jsx(OfficePptChooser, {
|
|
468
|
+
client: props.client, mode: props.mode, sessionId: props.sessionId, t: props.t
|
|
469
|
+
}, props.sessionId);
|
|
519
470
|
}
|
|
520
471
|
//#endregion
|
|
521
472
|
//#region ../office-ppt/src/client/locales.ts
|
|
@@ -697,25 +648,22 @@ window.__ModuleLoader__.load({
|
|
|
697
648
|
mode
|
|
698
649
|
});
|
|
699
650
|
}
|
|
700
|
-
/**
|
|
701
|
-
* Register the compact PPT picker in the public composer toolbar.
|
|
702
|
-
* @param ctx - Browser context that owns the standard Composer slots.
|
|
703
|
-
*/
|
|
651
|
+
/** Register the template picker below the composer for the native PPT preset. */
|
|
704
652
|
function applyStandard(ctx) {
|
|
705
653
|
const injectHero = officePptHeroInjection(ctx);
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
}
|
|
654
|
+
const name = "conversation.input.dock";
|
|
655
|
+
ctx.slots.inject(name, () => ctx.slots.register({
|
|
656
|
+
name, id: "dsh-ppt", order: 20, locale: NS, inject: injectHero
|
|
657
|
+
}, props => react_jsx_runtime.jsx(OfficePptComposer, {
|
|
658
|
+
client: props.client, mode: props.mode, sessionId: props.sessionId,
|
|
659
|
+
useSession: props.useSession, useSessions: props.useSessions, t: props.t
|
|
660
|
+
}, props.sessionId)));
|
|
713
661
|
}
|
|
714
662
|
//#endregion
|
|
715
663
|
//#region src/client/index.ts
|
|
716
664
|
/** Required standard browser services. */
|
|
717
665
|
const inject = standardInject;
|
|
718
|
-
/** Mount the PPT
|
|
666
|
+
/** Mount the native-PPT-preset template picker below the input card. */
|
|
719
667
|
function apply(ctx) {
|
|
720
668
|
applyStandard(ctx);
|
|
721
669
|
}
|
package/lib/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { definitions as DSH_PPT_TEMPLATE_DEFINITIONS, semantics as DSH_PPT_TEMPL
|
|
|
11
11
|
import { i as renderPptdProject, n as loadPptdProject, o as recommendedTextCapacity, r as parsePptdProject, t as checkPptdProject } from "./pptd-2VqVzr_T.js";
|
|
12
12
|
import z from "@deepseek-ai/schemastery";
|
|
13
13
|
import { fileURLToPath } from "node:url";
|
|
14
|
-
import { access, appendFile, link, lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
14
|
+
import { access, appendFile, copyFile, link, lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
15
15
|
import path from "node:path";
|
|
16
16
|
import { BUNDLED_SKILL_RANK, renderSkillContent } from "@deepseek-ai/dsh-skill";
|
|
17
17
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -758,8 +758,7 @@ var PptService = class {
|
|
|
758
758
|
state: {
|
|
759
759
|
...state,
|
|
760
760
|
selectedTemplateId: template.id,
|
|
761
|
-
|
|
762
|
-
presentationMode: "ppt"
|
|
761
|
+
templateMigration: undefined
|
|
763
762
|
},
|
|
764
763
|
value: template,
|
|
765
764
|
summary: `已选择模板 ${template.name}`,
|
|
@@ -3143,6 +3142,20 @@ function pptComposerContext(state) {
|
|
|
3143
3142
|
"workflow: direct local PPTD authoring with bounded pptd_* tools and final pptd_render conversion"
|
|
3144
3143
|
].join("\n");
|
|
3145
3144
|
}
|
|
3145
|
+
/** Resolve the preset currently running this session, including blank-session switches. */
|
|
3146
|
+
function sessionAgentPreset(session) {
|
|
3147
|
+
if (session === void 0 || typeof session !== "object") return void 0;
|
|
3148
|
+
for (let index = (session.events?.length ?? 0) - 1; index >= 0; index -= 1) {
|
|
3149
|
+
const event = session.events[index];
|
|
3150
|
+
if (event?.type === "agent-preset/selected" && typeof event.data?.agentPreset === "string") return event.data.agentPreset;
|
|
3151
|
+
}
|
|
3152
|
+
return typeof session.header?.agentPreset === "string" ? session.header.agentPreset : void 0;
|
|
3153
|
+
}
|
|
3154
|
+
/** New sessions use the native preset; the state flag remains for old sessions. */
|
|
3155
|
+
function isPptSession(agent, state) {
|
|
3156
|
+
const preset = sessionAgentPreset(agent?.session);
|
|
3157
|
+
return preset === "ppt" || (preset === void 0 && state.presentationMode === "ppt");
|
|
3158
|
+
}
|
|
3146
3159
|
function hasActiveSkill(agent) {
|
|
3147
3160
|
return agent.session.deriveMessages().some((message) => {
|
|
3148
3161
|
if (message.role !== "user") return false;
|
|
@@ -3207,7 +3220,7 @@ function registerPptTools(ctx, service) {
|
|
|
3207
3220
|
});
|
|
3208
3221
|
// Resolve the persisted composer state for this assembly, never a process-wide toggle.
|
|
3209
3222
|
ctx.on("system-prompt/assemble", async (_assembly, { agent }, next) => {
|
|
3210
|
-
const active = agent !== void 0 && (await service.state(agent.id))
|
|
3223
|
+
const active = agent !== void 0 && isPptSession(agent, await service.state(agent.id));
|
|
3211
3224
|
const assembly = await next();
|
|
3212
3225
|
return active ? assembly : {
|
|
3213
3226
|
...assembly,
|
|
@@ -3217,7 +3230,8 @@ function registerPptTools(ctx, service) {
|
|
|
3217
3230
|
ctx.on("agent/pre-step", async ({ agent, step, signal }, next) => {
|
|
3218
3231
|
const decision = await next();
|
|
3219
3232
|
if (decision.kind === "reject" || signal.aborted) return decision;
|
|
3220
|
-
const
|
|
3233
|
+
const state = await service.state(agent.id);
|
|
3234
|
+
const context = isPptSession(agent, state) ? pptComposerContext({ ...state, presentationMode: "ppt" }) : void 0;
|
|
3221
3235
|
if (signal.aborted) return decision;
|
|
3222
3236
|
if (context === void 0) {
|
|
3223
3237
|
clearAutomaticPptContext(agent);
|
|
@@ -3604,6 +3618,7 @@ const Config = z.object({
|
|
|
3604
3618
|
maxDecksPerSession: z.natural().min(1).default(50),
|
|
3605
3619
|
maxActivities: z.natural().min(1).default(200),
|
|
3606
3620
|
kimiPptSkillRoot: z.string(),
|
|
3621
|
+
presetRoot: z.string(),
|
|
3607
3622
|
pptSkillRoot: z.string()
|
|
3608
3623
|
});
|
|
3609
3624
|
/** Compose storage, browser RPC, and bounded model tools. */
|
|
@@ -3663,8 +3678,29 @@ function registerPptRpcRoute(webCtx, channel, rpcHandler) {
|
|
|
3663
3678
|
}), `dsh-ppt: ${channel} rpc route`);
|
|
3664
3679
|
}
|
|
3665
3680
|
|
|
3681
|
+
/** Make the package preset visible to the native DSH roster on first install. */
|
|
3682
|
+
async function ensurePptPreset(root) {
|
|
3683
|
+
if (typeof root !== "string" || !path.isAbsolute(root)) return;
|
|
3684
|
+
const source = fileURLToPath(new URL("../presets/ppt/", import.meta.url));
|
|
3685
|
+
const target = path.join(root, "ppt");
|
|
3686
|
+
await mkdir(target, { recursive: true });
|
|
3687
|
+
for (const file of ["agent.cordis.yml", "preset.yml"]) {
|
|
3688
|
+
const destination = path.join(target, file);
|
|
3689
|
+
try {
|
|
3690
|
+
await access(destination);
|
|
3691
|
+
} catch {
|
|
3692
|
+
await copyFile(path.join(source, file), destination);
|
|
3693
|
+
}
|
|
3694
|
+
}
|
|
3695
|
+
}
|
|
3696
|
+
|
|
3666
3697
|
async function apply(ctx, config) {
|
|
3667
3698
|
const bundledPptSkillRoot = fileURLToPath(new URL("../skills/dsh-ppt", import.meta.url));
|
|
3699
|
+
try {
|
|
3700
|
+
await ensurePptPreset(config.presetRoot ?? path.join(path.dirname(config.root), ".agent-presets"));
|
|
3701
|
+
} catch (error) {
|
|
3702
|
+
ctx.logger.warn(`dsh-ppt: could not install native PPT preset: ${error instanceof Error ? error.message : String(error)}`);
|
|
3703
|
+
}
|
|
3668
3704
|
registerPreviewAssets(ctx, previewFiles, path.join(bundledPptSkillRoot, "references"));
|
|
3669
3705
|
registerPptSkill(ctx, config.pptSkillRoot ?? config.kimiPptSkillRoot ?? process.env.DSH_PPT_SKILL_ROOT ?? process.env.DSH_KIMI_PPT_SKILL_ROOT ?? bundledPptSkillRoot);
|
|
3670
3706
|
const service = new PptService(new PptStore(config.root, {
|
|
@@ -3685,4 +3721,3 @@ async function apply(ctx, config) {
|
|
|
3685
3721
|
}
|
|
3686
3722
|
//#endregion
|
|
3687
3723
|
export { Config, apply, inject, name };
|
|
3688
|
-
|
package/lib/preset.js
ADDED
package/lib/types/index.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface Config {
|
|
|
15
15
|
maxDecksPerSession?: number;
|
|
16
16
|
/** Maximum recent activity records retained in session state. */
|
|
17
17
|
maxActivities?: number;
|
|
18
|
+
/** Absolute DSH agent-preset root used for the bundled PPT preset. */
|
|
19
|
+
presetRoot?: string;
|
|
18
20
|
/** Absolute DSH PPT Skill override. The package-bundled Skill is the default. */
|
|
19
21
|
pptSkillRoot?: string;
|
|
20
22
|
}
|
|
@@ -22,4 +24,4 @@ export interface Config {
|
|
|
22
24
|
export declare const Config: z<Config>;
|
|
23
25
|
/** Compose storage, browser RPC, and bounded model tools. */
|
|
24
26
|
export declare function apply(ctx: Context, config: Config): Promise<void>;
|
|
25
|
-
export type { PptService } from './ppt-service.ts';
|
|
27
|
+
export type { PptService } from './ppt-service.ts';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cola1900/dsh-ppt",
|
|
3
3
|
"description": "Standalone DSH plugin for PPT authoring, template selection, validation and editable PPTX export",
|
|
4
|
-
"version": "0.1
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/boe1900/dsh-ppt.git"
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"default": "./lib/pptd.js"
|
|
44
44
|
},
|
|
45
45
|
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
46
|
-
"./package.json": "./package.json"
|
|
46
|
+
"./package.json": "./package.json",
|
|
47
|
+
"./preset": "./lib/preset.js"
|
|
47
48
|
},
|
|
48
49
|
"dsh": {
|
|
49
50
|
"bundle": {
|
|
@@ -93,6 +94,7 @@
|
|
|
93
94
|
"files": [
|
|
94
95
|
"lib",
|
|
95
96
|
"skills",
|
|
97
|
+
"presets",
|
|
96
98
|
"cordis.patch.yml",
|
|
97
99
|
"LICENSE",
|
|
98
100
|
"THIRD_PARTY_NOTICES.md",
|